* (e.g., multiarray.x86_64-linux-gnu.so: undefined symbol: PyExc_SystemError)
*/
gchar libname[32];
-#if PY_VERSION_HEX >= 0x03000000
- g_snprintf (libname, sizeof(libname), "libpython%fm.so.1", PYTHON3_VERSION);
+
+ g_snprintf (libname, sizeof(libname),
+#if PY_VERSION_HEX >= 0x03000000
+ "libpython%d.%dm.so.1.0",
#else
- g_snprintf (libname, sizeof(libname), "libpython%f.so.1", PYTHON2_VERSION);
+ "libpython%d.%d.so.1.0",
#endif
+ PY_MAJOR_VERSION, PY_MINOR_VERSION);
+
handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
g_assert(handle);
Py_XDECREF(sys_module);
/** Find nnstreamer_api module */
-#if PY_VERSION_HEX >= 0x03000000
- PyObject *api_module = PyImport_ImportModule("nnstreamer_python3");
-#else
- PyObject *api_module = PyImport_ImportModule("nnstreamer_python2");
-#endif
+ PyObject *api_module = PyImport_ImportModule("nnstreamer_python");
g_assert(api_module);
shape_cls = PyObject_GetAttrString(api_module, "TensorShape");
Py_XDECREF(api_module);
have_python3 = false
if get_option('enable-python')
- prog_pkgconfig = find_program('pkg-config')
+ pg_pkgconfig = find_program('pkg-config')
# Check python 2.7
python2_dep = dependency('python-2.7', required: false)
if python2_dep.found()
- python2_incs = run_command(prog_pkgconfig, ['python-2.7', '--cflags']).stdout().strip().split()
+ python2_incs = run_command(pg_pkgconfig, ['python-2.7', '--cflags']).stdout().strip().split()
if cc.has_header('numpy/arrayobject.h', args: python2_incs)
- add_project_arguments('-DPYTHON2_VERSION=2.7', language: ['c', 'cpp'])
have_python2 = true
endif
endif
# Check python 3.x
python3_dep = dependency('python3', required: false)
if python3_dep.found()
- python3_version = run_command(prog_pkgconfig, ['python3', '--modversion']).stdout().strip()
- python3_incs = run_command(prog_pkgconfig, ['python3', '--cflags']).stdout().strip().split()
+ python3_incs = run_command(pg_pkgconfig, ['python3', '--cflags']).stdout().strip().split()
if cc.has_header('numpy/arrayobject.h', args: python3_incs)
- add_project_arguments('-DPYTHON3_VERSION=' + python3_version, language: ['c', 'cpp'])
have_python3 = true
endif
endif
--- /dev/null
+#!/usr/bin/env python
+
+##
+# Copyright (C) 2018 Samsung Electronics
+# License: LGPL-2.1
+#
+# @file checkScaledTensor.py
+# @brief Check if the scaled results are correct
+# This script is imported from tests/nnstreamer_filter_custom/
+# @author MyungJoo Ham <myungjoo.ham@samsung.com>
+
+import sys
+
+## @brief Compare original content and scaled one
+def compare (data1, width1, height1, data2, width2, height2, innerdim):
+ if (len(data1) * width2 * height2) != (len(data2) * width1 * height1):
+ print(str(len(data1) * width2 * height2)+" / "+str(len(data2) * width1 * height1))
+ return 1
+
+ count = 0
+ count2 = 0
+ while (count < len(data1)):
+ # Terminated incorrectly
+ if (count + (innerdim * width1 * height1)) > len(data1):
+ return 2
+ if (count2 + (innerdim * width2 * height2)) > len(data2):
+ return 3
+ if count2 >= len(data2):
+ return 4
+
+ for y in range(0, height2):
+ for x in range(0, width2):
+ for c in range(0, innerdim):
+ ix = x * width1 / width2
+ iy = y * height1 / height2
+ if data1[count + c + ix * innerdim + iy * width1 * innerdim] != data2[count2 + c + x * innerdim + y * width2 * innerdim]:
+ print("At "+str(x)+","+str(y))
+ return 5
+ count = count + innerdim * width1 * height1
+ count2 = count2 + innerdim * width2 * height2
+
+ if count > len(data1):
+ return 6
+ if count2 > len(data2):
+ return 7
+ return 0
+
+## @brief Read file and return its content
+def readfile (filename):
+ F = open(filename, 'r')
+ readfile = F.read()
+ F.close()
+ return readfile
+
+if len(sys.argv) != 8:
+ exit(9)
+
+data1 = readfile(sys.argv[1])
+width1 = int(sys.argv[2])
+height1 = int(sys.argv[3])
+data2 = readfile(sys.argv[4])
+width2 = int(sys.argv[5])
+height2 = int(sys.argv[6])
+innerdim = int(sys.argv[7])
+
+exit(compare(data1, width1, height1, data2, width2, height2, innerdim))
--- /dev/null
+##
+# Copyright (C) 2019 Samsung Electronics
+# License: LGPL-2.1
+#
+# @file Passthrough.py
+# @brief Python custom filter example: passthrough
+# @author Dongju Chae <dongju.chae@samsung.com>
+
+import numpy as np
+import nnstreamer_python as nns
+
+D1 = 3
+D2 = 280
+D3 = 40
+
+## @brief User-defined custom filter; DO NOT CHANGE CLASS NAME
+class CustomFilter(object):
+
+## @breif The constructor for custom filter: passthrough
+# @param None
+ def __init__ (self, *args):
+ self.input_dims = [nns.TensorShape([D1, D2, D3], np.uint8)]
+ self.output_dims = [nns.TensorShape([D1, D2, D3], np.uint8)]
+
+## @breif python callback: getInputDim
+# @param None
+# @return user-assigned input dimensions
+ def getInputDim (self):
+ return self.input_dims
+
+## @breif Python callback: getOutputDim
+# @param None
+# @return user-assigned output dimensions
+ def getOutputDim (self):
+ return self.output_dims
+
+## @breif Python callback: invoke
+# @param Input tensors: list of input numpy array
+# @return output tensors: list of output numpy array
+ def invoke (self, input_array):
+ # passthrough; just return
+ return input_array;
--- /dev/null
+##
+# Copyright (C) 2019 Samsung Electronics
+# License: LGPL-2.1
+#
+# @file Scaler.py
+# @brief Python custom filter example: scaler
+# @author Dongju Chae <dongju.chae@samsung.com>
+
+import numpy as np
+import nnstreamer_python as nns
+
+## @brief User-defined custom filter; DO NOT CHANGE CLASS NAME
+class CustomFilter(object):
+ new_x = 0
+ new_y = 0
+
+## @breif The constructor for custom filter: scaler
+# @param Dimensions to scale
+ def __init__ (self, *args):
+ if len (args) == 1:
+ try:
+ (self.new_x, self.new_y) = [int (dim) for dim in args[0].split('x')]
+ except:
+ print ("Dimension should have this format: AAAxBBB (e.g., 640x480)")
+
+## @breif Python callback: setInputDim
+# @param Input dimensions: list of nns.TensorShape
+ def setInputDim (self, input_dims):
+ if len(input_dims) != 1:
+ print ("One input tensor is allowed")
+ return None
+
+ self.input_dims = input_dims
+ self.output_dims = [nns.TensorShape(self.input_dims[0].getDims(),
+ self.input_dims[0].getType())]
+
+ dims = self.output_dims[0].getDims()
+ if (self.new_x > 0):
+ dims[1] = self.new_x
+ if (self.new_y > 0):
+ dims[2] = self.new_y
+
+ return self.output_dims
+
+## @breif Python callback: invoke
+# @param Input tensors: list of input numpy array
+# @return Output tensors: list of output numpy array
+ def invoke (self, input_array):
+ # reshape to n-D array (in reverse order)
+ input_tensor = np.reshape(input_array[0], self.input_dims[0].getDims()[::-1])
+ output_tensor = np.empty(self.output_dims[0].getDims()[::-1],
+ dtype=self.output_dims[0].getType())
+ in_dims = self.input_dims[0].getDims()
+ out_dims = self.output_dims[0].getDims()
+ for z in range(out_dims[3]):
+ for y in range(out_dims[2]):
+ for x in range(out_dims[1]):
+ for c in range(out_dims[0]):
+ ix = int(x * in_dims[1] / out_dims[1]);
+ iy = int(y * in_dims[2] / out_dims[2]);
+ output_tensor[z][y][x][c] = input_tensor[z][iy][ix][c]
+
+ # to 1-D array
+ return [np.ravel(output_tensor)]
--- /dev/null
+#!/usr/bin/env bash
+##
+## @file runTest.sh
+## @author Dongju Chae <dongju.chae@samsung.com>
+## @date Apr 3 2019
+## @brief SSAT Test Cases for NNStreamer
+##
+
+if [[ "$SSATAPILOADED" != "1" ]];then
+ SILENT=0
+ INDEPENDENT=1
+ search="ssat-api.sh"
+ source $search
+ printf "${Blue}Independent Mode${NC}
+"
+fi
+
+# This is compatible with SSAT (https://github.com/myungjoo/SSAT)
+testInit $1
+
+PATH_TO_PLUGIN="../../build"
+# Check python libraies are built
+if [[ -d $PATH_TO_PLUGIN ]]; then
+ ini_path="${PATH_TO_PLUGIN}/ext/nnstreamer/tensor_filter"
+ if [[ -d ${ini_path} ]]; then
+ check=$(ls ${ini_path} | grep python2.so)
+ if [[ ! $check ]]; then
+ echo "Cannot find python shared lib"
+ report
+ exit
+ fi
+ else
+ echo "Cannot find ${ini_path}"
+ report exit
+ fi
+else
+ echo "No build directory"
+ report
+ exit
+fi
+
+FRAMEWORK="python2"
+# This symlink is necessary only for testcases; when installed, symlinks will be made
+pushd ../../build/ext/nnstreamer/tensor_filter
+ln -s nnstreamer_python2.so nnstreamer_python.so
+popd
+
+# Passthrough test
+export PYTHONPATH=../../build/ext/nnstreamer/tensor_filter/:$PYTHONPATH
+PATH_TO_SCRIPT="python/passthrough.py"
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=1 ! video/x-raw,format=RGB,width=280,height=40,framerate=0/1 ! videoconvert ! video/x-raw, format=RGB ! tensor_converter ! tee name=t ! queue ! tensor_filter framework=\"${FRAMEWORK}\" model=\"${PATH_TO_SCRIPT}\" input=\"3:280:40\" inputtype=\"uint8\" output=\"3:280:40\" outputtype=\"uint8\" ! filesink location=\"testcase1.passthrough.log\" sync=true t. ! queue ! filesink location=\"testcase1.direct.log\" sync=true" 1 0 0 $PERFORMANCE
+callCompareTest testcase1.direct.log testcase1.passthrough.log 1 "Compare 1" 0 0
+
+# Scaler test
+# 1) 640x480 --> 320x240
+PATH_TO_SCRIPT="python/scaler.py"
+ARGUMENTS="320x240"
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=1 ! video/x-raw,format=RGB,width=640,height=480,framerate=0/1 ! videoconvert ! video/x-raw, format=RGB ! tensor_converter ! tee name=t ! queue ! tensor_filter framework=\"${FRAMEWORK}\" model=\"${PATH_TO_SCRIPT}\" custom=\"${ARGUMENTS}\" ! filesink location=\"testcase2.scaled.log\" sync=true t. ! queue ! filesink location=\"testcase2.direct.log\" sync=true" 2 0 0 $PERFORMANCE
+python checkScaledTensor.py testcase2.direct.log 640 480 testcase2.scaled.log 320 240 3
+testResult $? 2 "Golden test comparison" 0 1
+
+# 2) 640x480 --> 1280x960
+ARGUMENTS="1280x960"
+gstTest "--gst-plugin-path=${PATH_TO_PLUGIN} videotestsrc num-buffers=1 ! video/x-raw,format=RGB,width=640,height=480,framerate=0/1 ! videoconvert ! video/x-raw, format=RGB ! tensor_converter ! tee name=t ! queue ! tensor_filter framework=\"${FRAMEWORK}\" model=\"${PATH_TO_SCRIPT}\" custom=\"${ARGUMENTS}\" ! filesink location=\"testcase3.scaled.log\" sync=true t. ! queue ! filesink location=\"testcase3.direct.log\" sync=true" 3 0 0 $PERFORMANCE
+python checkScaledTensor.py testcase3.direct.log 640 480 testcase3.scaled.log 1280 960 3
+testResult $? 3 "Golden test comparison" 0 1
+
+report