[Filter/Custom/Example] Add new example: do average
authorMyungJoo Ham <myungjoo.ham@samsung.com>
Mon, 2 Jul 2018 11:51:14 +0000 (20:51 +0900)
committer함명주/동작제어Lab(SR)/Principal Engineer/삼성전자 <myungjoo.ham@samsung.com>
Wed, 4 Jul 2018 02:29:45 +0000 (11:29 +0900)
Added a new test case to satisfy #58.

Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
include/tensor_common.h
include/tensor_typedef.h
nnstreamer_example/CMakeLists.txt
nnstreamer_example/custom_example_average/CMakeLists.txt [new file with mode: 0644]
nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c [new file with mode: 0644]

index 76c1d67..7503a8b 100644 (file)
@@ -103,20 +103,6 @@ typedef enum _nns_media_type {
 } media_type;
 
 /**
- * @brief Byte-per-element of each tensor element type.
- */
-static const unsigned int tensor_element_size[] = {
-        [_NNS_INT32] = 4,
-        [_NNS_UINT32] = 4,
-        [_NNS_INT16] = 2,
-        [_NNS_UINT16] = 2,
-        [_NNS_INT8] = 1,
-        [_NNS_UINT8] = 1,
-        [_NNS_FLOAT64] = 8,
-        [_NNS_FLOAT32] = 4,
-};
-
-/**
  * @brief String representations for each tensor element type.
  */
 extern const gchar* tensor_element_typename[];
index 57c2a38..dcc3a90 100644 (file)
@@ -77,6 +77,20 @@ typedef enum _nns_tensor_type {
 } tensor_type;
 
 /**
+ * @brief Byte-per-element of each tensor element type.
+ */
+static const unsigned int tensor_element_size[] = {
+        [_NNS_INT32] = 4,
+        [_NNS_UINT32] = 4,
+        [_NNS_INT16] = 2,
+        [_NNS_UINT16] = 2,
+        [_NNS_INT8] = 1,
+        [_NNS_UINT8] = 1,
+        [_NNS_FLOAT64] = 8,
+        [_NNS_FLOAT32] = 4,
+};
+
+/**
  * @brief NN Frameworks available for the tensor_filter element.
  */
 typedef enum _nnfw_type {
index 9b91e90..3e2d782 100644 (file)
@@ -2,3 +2,4 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
 
 ADD_SUBDIRECTORY(custom_example_passthrough)
 ADD_SUBDIRECTORY(custom_example_scaler)
+ADD_SUBDIRECTORY(custom_example_average)
diff --git a/nnstreamer_example/custom_example_average/CMakeLists.txt b/nnstreamer_example/custom_example_average/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2761894
--- /dev/null
@@ -0,0 +1,13 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+ADD_LIBRARY(nnstreamer_customfilter_average SHARED nnstreamer_customfilter_example_average.c)
+
+TARGET_LINK_LIBRARIES(nnstreamer_customfilter_average ${pkgs_LIBRARIES})
+TARGET_INCLUDE_DIRECTORIES(nnstreamer_customfilter_average PUBLIC ${pkgs_INCLUDE_DIRS})
+TARGET_COMPILE_OPTIONS(nnstreamer_customfilter_average PUBLIC ${pkgs_CFLAGS_OTHER})
+
+INSTALL(TARGETS nnstreamer_customfilter_average
+       RUNTIME DESTINATION ${EXEC_PREFIX}
+       LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+       ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+       )
diff --git a/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c b/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c
new file mode 100644 (file)
index 0000000..15779d1
--- /dev/null
@@ -0,0 +1,154 @@
+/**
+ * NNStreamer Custom Filter Example 4. Average
+ * Copyright (C) 2018 MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * LICENSE: LGPL-2.1
+ *
+ * @file  nnstreamer_customfilter_example_average.c
+ * @date  02 Jul 2018
+ * @brief  Custom NNStreamer Filter Example 4. "Average"
+ * @author  MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * This scales a tensor of [N][y][x][M] to [N][1][1][M]
+ *
+ * This heavliy suffers from overflows. Do not use this for real applications!!!!!!
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <tensor_filter_custom.h>
+
+typedef struct _pt_data
+{
+  uint32_t id; /***< Just for testing */
+} pt_data;
+
+static void *
+pt_init (const GstTensor_Filter_Properties * prop)
+{
+  pt_data *data = (pt_data *) malloc (sizeof (pt_data));
+
+  data->id = 0;
+  return data;
+}
+
+static void
+pt_exit (void *private_data, const GstTensor_Filter_Properties * prop)
+{
+  pt_data *data = private_data;
+  assert (data);
+  free (data);
+}
+
+static int
+set_inputDim (void *private_data, const GstTensor_Filter_Properties * prop,
+    const tensor_dim iDim, const tensor_type iType,
+    tensor_dim oDim, tensor_type * oType)
+{
+  int i;
+  pt_data *data = private_data;
+  assert (data);
+
+  for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++)
+    oDim[i] = iDim[i];
+
+  /* Update [1] and [2] oDim with new-x, new-y */
+  oDim[1] = 1;
+  oDim[2] = 1;
+
+  *oType = iType;
+  return 0;
+}
+
+
+#define do_avg(type) do {\
+      type *avg = (type *) malloc(sizeof(type) * prop->inputDimension[0]); \
+      type *iptr = (type *) inptr; \
+      type *optr = (type *) outptr; \
+      for (z = 0; z < prop->inputDimension[3]; z++) { \
+        for (y = 0; y < prop->inputDimension[0]; y++) \
+          avg[y] = 0; \
+        for (y = 0; y < prop->inputDimension[2]; y++) { \
+          for (x = 0; x < prop->inputDimension[1]; x++) { \
+            for (c = 0; c < prop->inputDimension[0]; c++) { \
+              avg[c] += *(iptr + c + x * ix + y * iy + z * iz); \
+            } \
+          } \
+        } \
+        for (c = 0; c < prop->inputDimension[0]; c++) { \
+          *(optr + c + z * prop->inputDimension[0]) = (type) (avg[c] / xy); \
+        } \
+      } \
+      free(avg); \
+  } while (0)
+
+static int
+pt_invoke (void *private_data, const GstTensor_Filter_Properties * prop,
+    const uint8_t * inptr, uint8_t * outptr)
+{
+  pt_data *data = private_data;
+  uint32_t c, x, y, z;
+
+  unsigned ix = prop->inputDimension[0];
+  unsigned iy = prop->inputDimension[0] * prop->inputDimension[1];
+  unsigned iz =
+      prop->inputDimension[0] * prop->inputDimension[1] *
+      prop->inputDimension[2];
+  unsigned xy = prop->inputDimension[1] * prop->inputDimension[2];
+
+  assert (data);
+  assert (inptr);
+  assert (outptr);
+
+  /* This assumes the limit is 4 */
+  assert (NNS_TENSOR_RANK_LIMIT == 4);
+
+  assert (prop->inputDimension[0] == prop->outputDimension[0]);
+  assert (prop->inputDimension[3] == prop->outputDimension[3]);
+  assert (prop->inputType == prop->outputType);
+
+  switch (prop->inputType) {
+    case _NNS_INT8:
+      do_avg (int8_t);
+      break;
+    case _NNS_INT16:
+      do_avg (int16_t);
+      break;
+    case _NNS_INT32:
+      do_avg (int32_t);
+      break;
+    case _NNS_UINT8:
+      do_avg (uint8_t);
+      break;
+    case _NNS_UINT16:
+      do_avg (uint16_t);
+      break;
+    case _NNS_UINT32:
+      do_avg (uint32_t);
+      break;
+    case _NNS_FLOAT32:
+      do_avg (float);
+      break;
+    case _NNS_FLOAT64:
+      do_avg (double);
+      break;
+
+    default:
+      assert (0);               /* Type Mismatch */
+  }
+  assert (inptr != outptr);
+
+  return 0;
+}
+
+static NNStreamer_custom_class NNStreamer_custom_body = {
+  .initfunc = pt_init,
+  .exitfunc = pt_exit,
+  .setInputDim = set_inputDim,
+  .invoke = pt_invoke,
+};
+
+/* The dyn-loaded object */
+NNStreamer_custom_class *NNStreamer_custom = &NNStreamer_custom_body;