From 66194099b434ec3e09da8c4e0830aac274272d94 Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Mon, 2 Jul 2018 20:51:14 +0900 Subject: [PATCH] [Filter/Custom/Example] Add new example: do average Added a new test case to satisfy #58. Signed-off-by: MyungJoo Ham --- include/tensor_common.h | 14 -- include/tensor_typedef.h | 14 ++ nnstreamer_example/CMakeLists.txt | 1 + .../custom_example_average/CMakeLists.txt | 13 ++ .../nnstreamer_customfilter_example_average.c | 154 +++++++++++++++++++++ 5 files changed, 182 insertions(+), 14 deletions(-) create mode 100644 nnstreamer_example/custom_example_average/CMakeLists.txt create mode 100644 nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c diff --git a/include/tensor_common.h b/include/tensor_common.h index 76c1d67..7503a8b 100644 --- a/include/tensor_common.h +++ b/include/tensor_common.h @@ -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[]; diff --git a/include/tensor_typedef.h b/include/tensor_typedef.h index 57c2a38..dcc3a90 100644 --- a/include/tensor_typedef.h +++ b/include/tensor_typedef.h @@ -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 { diff --git a/nnstreamer_example/CMakeLists.txt b/nnstreamer_example/CMakeLists.txt index 9b91e90..3e2d782 100644 --- a/nnstreamer_example/CMakeLists.txt +++ b/nnstreamer_example/CMakeLists.txt @@ -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 index 0000000..2761894 --- /dev/null +++ b/nnstreamer_example/custom_example_average/CMakeLists.txt @@ -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 index 0000000..15779d1 --- /dev/null +++ b/nnstreamer_example/custom_example_average/nnstreamer_customfilter_example_average.c @@ -0,0 +1,154 @@ +/** + * NNStreamer Custom Filter Example 4. Average + * Copyright (C) 2018 MyungJoo Ham + * + * LICENSE: LGPL-2.1 + * + * @file nnstreamer_customfilter_example_average.c + * @date 02 Jul 2018 + * @brief Custom NNStreamer Filter Example 4. "Average" + * @author MyungJoo Ham + * + * 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 +#include +#include +#include +#include + +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; -- 2.7.4