- `gst_tensor_data_raw_*` get double pointer for result as input. And allocate memory for it.
- Correspond change in tensor_transform and gsttensorif
- Divide with N, not N - 1 when calculate standard deviation
Signed-off-by: Yongjoo Ahn <yongjoo1.ahn@samsung.com>
* @param raw pointer of raw tensor data
* @param length byte size of raw tensor data
* @param type tensor type
- * @return average value
+ * @param result double pointer for average value of given tensor. Caller should release allocated memory.
+ * @return TRUE if no error
*/
-gdouble
-gst_tensor_data_raw_average (gpointer raw, gsize length, tensor_type type)
+gboolean
+gst_tensor_data_raw_average (gpointer raw, gsize length, tensor_type type,
+ gdouble ** result)
{
gdouble value, average;
gulong i, num;
gsize element_size;
guint8 *data;
- g_return_val_if_fail (raw != NULL, 0.0);
- g_return_val_if_fail (length > 0, 0.0);
- g_return_val_if_fail (type != _NNS_END, 0.0);
+ g_return_val_if_fail (raw != NULL, FALSE);
+ g_return_val_if_fail (length > 0, FALSE);
+ g_return_val_if_fail (type != _NNS_END, FALSE);
element_size = gst_tensor_get_element_size (type);
num = length / element_size;
average = 0.0;
+ *result = (gdouble *) g_try_malloc0 (sizeof (gdouble));
+ if (*result == NULL) {
+ nns_loge ("Failed to allocate memory for calculating average");
+ return FALSE;
+ }
+
for (i = 0; i < num; ++i) {
/* extract value and typecast to double */
data = (guint8 *) raw + element_size * i;
average = (value - average) / (i + 1) + average;
}
- return average;
+ **result = average;
+
+ return TRUE;
}
/**
* @param length byte size of raw tensor data
* @param type tensor type
* @param tensor_dim tensor dimension
- * @param results double array contains average values of each channel
+ * @param results double array contains average values of each channel. Caller should release allocated array.
* @return TRUE if no error
*/
gboolean
gst_tensor_data_raw_average_per_channel (gpointer raw, gsize length,
- tensor_type type, tensor_dim dim, gdouble * results)
+ tensor_type type, tensor_dim dim, gdouble ** results)
{
gdouble value, average;
gulong ch, i, num, offset;
offset = dim[0];
num = num / offset;
+ *results = (gdouble *) g_try_malloc0 (sizeof (gdouble) * offset);
+ if (*results == NULL) {
+ nns_loge ("Failed to allocate memory for calculating average");
+ return FALSE;
+ }
for (ch = 0; ch < offset; ++ch) {
average = 0.0;
average = (value - average) / (i + 1) + average;
}
- results[ch] = average;
+ (*results)[ch] = average;
}
return TRUE;
* @param length byte size of raw tensor data
* @param type tensor type
* @param average average value of given tensor
- * @return standard deviation
+ * @param result double pointer for standard deviation of given tensor. Caller should release allocated memory.
+ * @return TRUE if no error
*/
-gdouble
+gboolean
gst_tensor_data_raw_std (gpointer raw, gsize length, tensor_type type,
- gdouble average)
+ gdouble * average, gdouble ** result)
{
gdouble value, std;
gulong i, num;
gsize element_size;
guint8 *data;
- g_return_val_if_fail (raw != NULL, 0.0);
- g_return_val_if_fail (length > 0, 0.0);
- g_return_val_if_fail (type != _NNS_END, 0.0);
+ g_return_val_if_fail (raw != NULL, FALSE);
+ g_return_val_if_fail (length > 0, FALSE);
+ g_return_val_if_fail (type != _NNS_END, FALSE);
element_size = gst_tensor_get_element_size (type);
num = length / element_size;
+ *result = (gdouble *) g_try_malloc0 (sizeof (gdouble));
+ if (*result == NULL) {
+ nns_loge ("Failed to allocate memory for calculating standard deviation");
+ return FALSE;
+ }
std = 0.0;
for (i = 0; i < num; ++i) {
data = (guint8 *) raw + element_size * i;
gst_tensor_data_raw_typecast (data, type, &value, _NNS_FLOAT64);
- std += pow (value - average, 2) / (num - 1);
+ std += pow (value - *average, 2) / num;
}
std = (std != 0.0) ? sqrt (std) : (1e-10);
+ **result = std;
- return std;
+ return TRUE;
}
/**
* @param type tensor type
* @param tensor_dim tensor dimension
* @param averages average values of given tensor per-channel
- * @param results double array contains standard deviation of each channel
+ * @param results double array contains standard deviation of each channel. Caller should release allocated array.
* @return TRUE if no error
*/
gboolean
gst_tensor_data_raw_std_per_channel (gpointer raw, gsize length,
- tensor_type type, tensor_dim dim, gdouble * averages, gdouble * results)
+ tensor_type type, tensor_dim dim, gdouble * averages, gdouble ** results)
{
gdouble value, std;
gulong ch, i, num, offset;
offset = dim[0];
num = num / offset;
+ *results = (gdouble *) g_try_malloc0 (sizeof (gdouble) * offset);
+ if (*results == NULL) {
+ nns_loge ("Failed to allocate memory for calculating standard deviation");
+ return FALSE;
+ }
for (ch = 0; ch < offset; ++ch) {
std = 0.0;
/* extract value and typecast to double */
data = (guint8 *) raw + element_size * ((i * offset) + ch);
gst_tensor_data_raw_typecast (data, type, &value, _NNS_FLOAT64);
- std += pow (value - averages[ch], 2) / (num - 1);
+ std += pow (value - averages[ch], 2) / num;
}
std = (std != 0.0) ? sqrt (std) : (1e-10);
- results[ch] = std;
+ (*results)[ch] = std;
}
return TRUE;
* @param raw pointer of raw tensor data
* @param length byte size of raw tensor data
* @param type tensor type
- * @return average value
+ * @param result double pointer for average value of given tensor. Caller should release allocated memory.
+ * @return TRUE if no error
*/
-extern gdouble
-gst_tensor_data_raw_average (gpointer raw, gsize length, tensor_type type);
+extern gboolean
+gst_tensor_data_raw_average (gpointer raw, gsize length, tensor_type type,
+ gdouble ** result);
/**
* @brief Calculate average value of the tensor per channel (the first dim).
* @param length byte size of raw tensor data
* @param type tensor type
* @param tensor_dim tensor dimension
- * @param results double array contains average values of each channel
+ * @param results double array contains average values of each channel. Caller should release allocated array.
* @return TRUE if no error
*/
extern gboolean
gst_tensor_data_raw_average_per_channel (gpointer raw, gsize length,
- tensor_type type, tensor_dim dim, gdouble * results);
+ tensor_type type, tensor_dim dim, gdouble ** results);
/**
* @brief Calculate standard deviation of the tensor.
* @param length byte size of raw tensor data
* @param type tensor type
* @param average average value of given tensor
- * @return standard deviation
+ * @param result double pointer for standard deviation of given tensor. Caller should release allocated memory.
+ * @return TRUE if no error
*/
-extern gdouble
+extern gboolean
gst_tensor_data_raw_std (gpointer raw, gsize length, tensor_type type,
- gdouble average);
+ gdouble * average, gdouble ** result);
/**
* @brief Calculate standard deviation of the tensor per channel (the first dim).
* @param type tensor type
* @param tensor_dim tensor dimension
* @param averages average values of given tensor per-channel
- * @param results double array contains standard deviation of each channel
+ * @param results double array contains standard deviation of each channel. Caller should release allocated array.
* @return TRUE if no error
*/
extern gboolean
gst_tensor_data_raw_std_per_channel (gpointer raw, gsize length,
- tensor_type type, tensor_dim dim, gdouble * averages, gdouble * results);
+ tensor_type type, tensor_dim dim, gdouble * averages, gdouble ** results);
G_END_DECLS
#endif /* __NNS_TENSOR_DATA_H__ */
{
GstMemory *in_mem;
GstMapInfo in_info;
- double avg;
+ gdouble *avg = NULL;
tensor_type type = tensor_if->in_config.info.info[nth].type;
in_mem = gst_buffer_peek_memory (buf, nth);
return FALSE;
}
- avg = gst_tensor_data_raw_average (in_info.data, in_info.size, type);
+ gst_tensor_data_raw_average (in_info.data, in_info.size, type, &avg);
gst_memory_unmap (in_mem, &in_info);
- gst_tensor_data_set (cv, _NNS_FLOAT64, &avg);
+ gst_tensor_data_set (cv, _NNS_FLOAT64, avg);
gst_tensor_data_typecast (cv, type);
+
+ g_free (avg);
return TRUE;
}
gst_tensor_transform_stand (GstTensorTransform * filter,
guint idx, const uint8_t * inptr, uint8_t * outptr)
{
- tensor_type in_tensor_type = filter->in_config.info.info[idx].type;
- tensor_type out_tensor_type = filter->out_config.info.info[idx].type;
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstTensorInfo *in_info, *out_info;
+ tensor_type in_tensor_type, out_tensor_type;
gsize in_element_size, out_element_size, data_size, ch_size;
gulong i, num, data_idx, ch;
- gdouble tmp, average, std;
- gdouble *avg_per_ch, *std_per_ch;
+ gdouble tmp, *average, *std;
+
+ in_info = &filter->in_config.info.info[idx];
+ out_info = &filter->out_config.info.info[idx];
+ in_tensor_type = in_info->type;
+ out_tensor_type = out_info->type;
in_element_size = gst_tensor_get_element_size (in_tensor_type);
out_element_size = gst_tensor_get_element_size (out_tensor_type);
- num =
- gst_tensor_get_element_count (filter->in_config.info.info[idx].dimension);
+ num = gst_tensor_get_element_count (in_info->dimension);
- ch_size = filter->in_config.info.info[idx].dimension[0];
+ data_size = gst_tensor_info_get_size (in_info);
+ ch_size = in_info->dimension[0];
/* calc average and std */
- data_size = gst_tensor_info_get_size (&filter->in_config.info.info[idx]);
- average = gst_tensor_data_raw_average ((gpointer) inptr, data_size,
- in_tensor_type);
- std =
+ average = std = NULL;
+ if (filter->data_stand.per_channel) {
+ gst_tensor_data_raw_average_per_channel ((gpointer) inptr, data_size,
+ in_tensor_type, in_info->dimension, &average);
+ /* calculate std only for default mode */
+ if (filter->data_stand.mode == STAND_DEFAULT)
+ gst_tensor_data_raw_std_per_channel ((gpointer) inptr, data_size,
+ in_tensor_type, in_info->dimension, average, &std);
+ } else {
+ gst_tensor_data_raw_average ((gpointer) inptr, data_size,
+ in_tensor_type, &average);
+ /* calculate std only for default mode */
+ if (filter->data_stand.mode == STAND_DEFAULT)
gst_tensor_data_raw_std ((gpointer) inptr, data_size, in_tensor_type,
- average);
+ average, &std);
+ }
switch (filter->data_stand.mode) {
case STAND_DEFAULT:
gst_tensor_data_raw_typecast ((gpointer) (inptr + data_idx),
in_tensor_type, &tmp, _NNS_FLOAT64);
- tmp = fabs ((tmp - average) / std);
+ tmp = fabs ((tmp - *average) / *std);
data_idx = out_element_size * i;
gst_tensor_data_raw_typecast (&tmp, _NNS_FLOAT64,
(gpointer) (outptr + data_idx), out_tensor_type);
}
} else {
- avg_per_ch =
- (gdouble *) g_malloc0 (sizeof (gdouble) *
- filter->in_config.info.info[idx].dimension[0]);
-
- gst_tensor_data_raw_average_per_channel ((gpointer) inptr, data_size,
- in_tensor_type, filter->in_config.info.info[idx].dimension,
- avg_per_ch);
-
- std_per_ch =
- (gdouble *) g_malloc0 (sizeof (gdouble) *
- filter->in_config.info.info[idx].dimension[0]);
- gst_tensor_data_raw_std_per_channel ((gpointer) inptr, data_size,
- in_tensor_type, filter->in_config.info.info[idx].dimension,
- avg_per_ch, std_per_ch);
-
for (ch = 0; ch < ch_size; ++ch) {
for (i = 0; i < num / ch_size; i++) {
data_idx = in_element_size * ((i * ch_size) + ch);
gst_tensor_data_raw_typecast ((gpointer) (inptr + data_idx),
in_tensor_type, &tmp, _NNS_FLOAT64);
- tmp = fabs ((tmp - avg_per_ch[ch]) / std_per_ch[ch]);
+ tmp = fabs ((tmp - average[ch]) / std[ch]);
data_idx = out_element_size * ((i * ch_size) + ch);
gst_tensor_data_raw_typecast (&tmp, _NNS_FLOAT64,
(gpointer) (outptr + data_idx), out_tensor_type);
}
}
-
- g_free (avg_per_ch);
- g_free (std_per_ch);
}
break;
}
gst_tensor_data_raw_typecast ((gpointer) (inptr + data_idx),
in_tensor_type, &tmp, _NNS_FLOAT64);
- tmp -= average;
+ tmp -= *average;
+
data_idx = out_element_size * i;
gst_tensor_data_raw_typecast (&tmp, _NNS_FLOAT64,
(gpointer) (outptr + data_idx), out_tensor_type);
}
} else {
- avg_per_ch =
- (gdouble *) g_malloc0 (sizeof (gdouble) *
- filter->in_config.info.info[idx].dimension[0]);
-
- gst_tensor_data_raw_average_per_channel ((gpointer) inptr, data_size,
- in_tensor_type, filter->in_config.info.info[idx].dimension,
- avg_per_ch);
-
for (ch = 0; ch < ch_size; ++ch) {
for (i = 0; i < num / ch_size; i++) {
data_idx = in_element_size * ((i * ch_size) + ch);
gst_tensor_data_raw_typecast ((gpointer) (inptr + data_idx),
in_tensor_type, &tmp, _NNS_FLOAT64);
- tmp -= avg_per_ch[ch];
+ tmp -= average[ch];
data_idx = out_element_size * ((i * ch_size) + ch);
gst_tensor_data_raw_typecast (&tmp, _NNS_FLOAT64,
(gpointer) (outptr + data_idx), out_tensor_type);
}
}
-
- g_free (avg_per_ch);
}
break;
}
default:
GST_ERROR_OBJECT (filter, "Cannot identify mode\n");
- return GST_FLOW_ERROR;
+ ret = GST_FLOW_ERROR;
}
- return GST_FLOW_OK;
+ g_free (average);
+ g_free (std);
+
+ return ret;
}
/**