├── CMakeLists.txt
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── bubble-pop
├── CMakeLists.txt
├── gdf
│ └── AMD_BUBBLE_POP.gdf
├── image
│ └── b20.png
├── include
│ ├── internal_opencvTunnel.h
│ ├── internal_publishKernels.h
│ ├── vx_ext_pop.h
│ └── vx_pop.h
└── source
│ ├── AMD_VX_Pop_Bubble.cpp
│ ├── AMD_VX_Pop_Donut.cpp
│ ├── AMD_app.cpp
│ ├── internal_dataTranslator.cpp
│ ├── internal_publishKernels.cpp
│ └── internal_vxNodes.cpp
├── canny-edge-detector
├── CMakeLists.txt
└── src
│ └── canny.cpp
├── images
├── canny-app.png
├── canny_image.PNG
├── face.png
├── skintone-detect-app.png
└── vx-pop-app.gif
└── skin-tone-detector
├── CMakeLists.txt
└── src
└── skinToneDetector.cpp
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.10.2)
2 |
3 | if(NOT CMAKE_BUILD_TYPE)
4 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug, Release, or MinSizeRel." FORCE)
5 | message(STATUS "CMAKE_BUILD_TYPE not set, defaulting to Release.")
6 | endif()
7 |
8 | project(openvx-samples LANGUAGES CXX)
9 |
10 | add_subdirectory(bubble-pop)
11 | add_subdirectory(canny-edge-detector)
12 | add_subdirectory(skin-tone-detector)
13 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | A reminder that this issue tracker is managed by the Khronos Group. Interactions here should follow the Khronos Code of Conduct ([https://www.khronos.org/developers/code-of-conduct](https://www.khronos.org/developers/code-of-conduct)), which prohibits aggressive or derogatory language. Please keep the discussion friendly and civil.
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Kiriti Gowda
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://opensource.org/licenses/MIT)
2 |
3 |

4 |
5 | # OpenVX Samples
6 |
7 | Khronos OpenVX™ is an open, royalty-free standard for cross-platform acceleration of computer vision applications. OpenVX enables performance and power-optimized computer vision processing, especially important in embedded and real-time use cases such as face, body, and gesture tracking, smart video surveillance, advanced driver assistance systems (ADAS), object and scene reconstruction, augmented reality, visual inspection, robotics and more.
8 |
9 | In this project, we provide OpenVX sample applications to use with any conformant implementation of OpenVX.
10 |
11 | * [VX Bubble Pop Sample](#vx-bubble-pop-sample)
12 | * [VX Canny Edge Detector Sample](#canny-edge-detector-sample)
13 | * [VX Skin Tone Detector Sample](#skin-tone-detector-sample)
14 |
15 | ## VX Bubble Pop Sample
16 |
17 | In this sample we will create an OpenVX graph to run VX Bubble Pop on a live camera. This sample application uses OpenCV to decode input image, draw bubbles/donuts and display the output.
18 |
19 | 
20 |
21 | ### Prerequisites
22 |
23 | * [Conformant OpenVX Implementation](https://github.com/KhronosGroup/Khronosdotorg/blob/master/api/openvx/resources.md)
24 |
25 | * [OpenCV](https://github.com/opencv/opencv/releases/tag/3.4.0)
26 |
27 | * Camera
28 |
29 | ### Steps to run the Bubble Pop sample
30 |
31 | * **Step - 1:** Build and install [Conformant OpenVX Implementation](https://github.com/KhronosGroup/OpenVX-sample-impl). In this example we will use the OpenVX Sample Implementation available on [GitHub](https://github.com/KhronosGroup/OpenVX-sample-impl)
32 |
33 | ```
34 | Build OpenVX on Linux
35 |
36 | * Git Clone project with a recursive flag to get submodules
37 |
38 | git clone --recursive https://github.com/KhronosGroup/OpenVX-sample-impl.git
39 |
40 | * Use Build.py script
41 |
42 | cd OpenVX-sample-impl/
43 | python Build.py --os=Linux --arch=64 --conf=Debug --conf_vision --enh_vision --conf_nn
44 | ```
45 |
46 | * **Step - 2:** Export OpenVX Directory Path
47 |
48 | ```
49 | export OPENVX_DIR=$(pwd)/install/Linux/x64/Debug
50 | ```
51 |
52 | * **Step - 3:** Clone the OpenVX Samples project and build the bubble pop application
53 |
54 | ```
55 | cd ~/ && mkdir OpenVXSample-pop
56 | cd OpenVXSample-pop/
57 | git clone https://github.com/kiritigowda/openvx-samples.git
58 | ```
59 |
60 | * **Step - 4:** CMake and Build the pop application
61 |
62 | ```
63 | mkdir pop-build && cd pop-build
64 | cmake -DOPENVX_INCLUDES=$OPENVX_DIR/include -DOPENVX_LIBRARIES=$OPENVX_DIR/bin/libopenvx.so ../openvx-samples/bubble-pop/
65 | make
66 | ```
67 |
68 | * **Step - 5:** Run VX Pop application
69 |
70 | * **Bubbles**
71 |
72 | ```
73 | ./vxPop --bubble
74 | ```
75 |
76 | * **Donuts**
77 |
78 | ````
79 | ./vxPop --donut
80 | ````
81 |
82 | ## Canny Edge Detector Sample
83 |
84 | In this sample we will create an OpenVX graph to run canny edge detection on an image or a live camera. This sample application uses OpenCV to decode input image and display the output.
85 |
86 | 
87 |
88 | ### Prerequisites
89 |
90 | * [Conformant OpenVX Implementation](https://github.com/KhronosGroup/Khronosdotorg/blob/master/api/openvx/resources.md)
91 |
92 | * [OpenCV](https://github.com/opencv/opencv/releases/tag/3.4.0)
93 |
94 | ### Steps to run the canny sample
95 |
96 | * **Step - 1:** Build and install [Conformant OpenVX Implementation](https://github.com/KhronosGroup/OpenVX-sample-impl). In this example we will use the OpenVX Sample Implementation available on [GitHub](https://github.com/KhronosGroup/OpenVX-sample-impl)
97 |
98 | ```
99 | Build OpenVX on Linux
100 |
101 | * Git Clone project with a recursive flag to get submodules
102 |
103 | git clone --recursive https://github.com/KhronosGroup/OpenVX-sample-impl.git
104 |
105 | * Use Build.py script
106 |
107 | cd OpenVX-sample-impl/
108 | python Build.py --os=Linux --arch=64 --conf=Debug --conf_vision --enh_vision --conf_nn
109 | ```
110 |
111 | * **Step - 2:** Export OpenVX Directory Path
112 |
113 | ```
114 | export OPENVX_DIR=$(pwd)/install/Linux/x64/Debug
115 | ```
116 |
117 | * **Step - 3:** Clone the OpenVX Samples project and build the canny application
118 |
119 | ```
120 | cd ~/ && mkdir OpenVXSample-canny
121 | cd OpenVXSample-canny/
122 | git clone https://github.com/kiritigowda/openvx-samples.git
123 | ```
124 |
125 | * **Step - 4:** CMake and Build the canny application
126 |
127 | ```
128 | mkdir canny-build && cd canny-build
129 | cmake -DOPENVX_INCLUDES=$OPENVX_DIR/include -DOPENVX_LIBRARIES=$OPENVX_DIR/bin/libopenvx.so ../openvx-samples/canny-edge-detector/
130 | make
131 | ```
132 |
133 | * **Step - 5:** Run Canny application
134 |
135 | * **Live**
136 |
137 | ```
138 | ./cannyEdgeDetector --live
139 | ```
140 |
141 | * **Image**
142 |
143 | ````
144 | ./cannyEdgeDetector --image ../openvx-samples/images/face.png
145 | ````
146 | 
147 |
148 | ## Skin Tone Detector Sample
149 |
150 | In this sample we will create an OpenVX graph to run skintone detection on an image or a live camera. This sample application uses OpenCV to decode input image and display the output.
151 |
152 | 
153 |
154 | ### Prerequisites
155 |
156 | * [Conformant OpenVX Implementation](https://github.com/KhronosGroup/Khronosdotorg/blob/master/api/openvx/resources.md)
157 |
158 | * [OpenCV](https://github.com/opencv/opencv/releases/tag/3.4.0)
159 |
160 | ### Steps to run the skin tone sample
161 |
162 | * **Step - 1:** Build and install [Conformant OpenVX Implementation](https://github.com/KhronosGroup/OpenVX-sample-impl). In this example we will use the OpenVX Sample Implementation available on [GitHub](https://github.com/KhronosGroup/OpenVX-sample-impl)
163 |
164 | ```
165 | Build OpenVX on Linux
166 |
167 | * Git Clone project with a recursive flag to get submodules
168 |
169 | git clone --recursive https://github.com/KhronosGroup/OpenVX-sample-impl.git
170 |
171 | * Use Build.py script
172 |
173 | cd OpenVX-sample-impl/
174 | python Build.py --os=Linux --arch=64 --conf=Debug --conf_vision --enh_vision --conf_nn
175 | ```
176 |
177 | * **Step - 2:** Export OpenVX Directory Path
178 |
179 | ```
180 | export OPENVX_DIR=$(pwd)/install/Linux/x64/Debug
181 | ```
182 |
183 | * **Step - 3:** Clone the OpenVX Samples project and build the Skin Tone application
184 |
185 | ```
186 | cd ~/ && mkdir OpenVXSample-skintone
187 | cd OpenVXSample-skintone/
188 | git clone https://github.com/kiritigowda/openvx-samples.git
189 | ```
190 |
191 | * **Step - 4:** CMake and Build the Skin Tone application
192 |
193 | ```
194 | mkdir skintone-build && cd skintone-build
195 | cmake -DOPENVX_INCLUDES=$OPENVX_DIR/include -DOPENVX_LIBRARIES=$OPENVX_DIR/bin/libopenvx.so ../openvx-samples/skin-tone-detector/
196 | make
197 | ```
198 |
199 | * **Step - 5:** Run Skin Tone Detector application
200 |
201 | * **Live**
202 |
203 | ```
204 | ./skinToneDetector --live
205 | ```
206 |
207 | * **Image**
208 |
209 | ````
210 | ./skinToneDetector --image ../openvx-samples/images/face.png
211 | ````
212 | ## Contribution
213 | The samples VX Bubble Pop, VX Canny Edge Detector, & VX Skin Tone Detector are contributed by [AMD](https://www.amd.com/en) from their [MIVisionX Toolkit](https://gpuopen-professionalcompute-libraries.github.io/MIVisionX/). We welcome contributions to this project from all developers. Please open a pull request with details of your sample application to be accepted into this project.
214 |
--------------------------------------------------------------------------------
/bubble-pop/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | #
3 | # MIT License
4 | #
5 | # Copyright (c) 2020 Advanced Micro Devices, Inc.
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 | #
25 | ###############################################################################
26 | cmake_minimum_required(VERSION 2.8)
27 | project(vx_pop)
28 |
29 | set(CMAKE_CXX_STANDARD 11)
30 |
31 | find_package(OpenCV REQUIRED)
32 |
33 | include_directories(include)
34 |
35 | if(DEFINED OPENVX_INCLUDES)
36 | message(STATUS "OPENVX_INCLUDES: \t${OPENVX_INCLUDES}")
37 | include_directories(${OPENVX_INCLUDES})
38 | else()
39 | message(STATUS "OPENVX_INCLUDES: \t")
40 | endif()
41 |
42 | if(DEFINED OPENVX_LIBRARIES)
43 | message(STATUS "OPENVX_LIBRARIES: \t${OPENVX_LIBRARIES}")
44 | else()
45 | message(STATUS "OPENVX_LIBRARIES: \t")
46 | endif()
47 |
48 | list(APPEND SOURCES
49 | source/AMD_VX_Pop_Bubble.cpp
50 | source/AMD_VX_Pop_Donut.cpp
51 | source/internal_dataTranslator.cpp
52 | source/internal_publishKernels.cpp
53 | source/internal_vxNodes.cpp
54 | )
55 |
56 | add_library(${PROJECT_NAME} SHARED ${SOURCES})
57 | target_link_libraries(${PROJECT_NAME} ${OPENVX_LIBRARIES} ${OpenCV_LIBRARIES})
58 |
59 | add_executable(vxPop source/AMD_app.cpp)
60 | target_link_libraries(vxPop ${OPENVX_LIBRARIES} ${OpenCV_LIBRARIES} ${PROJECT_NAME})
61 |
62 | file(COPY image DESTINATION ${CMAKE_BINARY_DIR})
63 | file(COPY gdf DESTINATION ${CMAKE_BINARY_DIR})
64 |
65 | if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
66 | target_link_libraries(vx_opencv OpenVX)
67 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
68 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
69 | else()
70 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections")
71 | endif()
72 |
73 | install(TARGETS ${PROJECT_NAME} vxPop
74 | RUNTIME DESTINATION bin
75 | LIBRARY DESTINATION lib
76 | )
77 |
--------------------------------------------------------------------------------
/bubble-pop/gdf/AMD_BUBBLE_POP.gdf:
--------------------------------------------------------------------------------
1 | import vx_pop
2 |
3 | data input = image:640,480,RGB2:CAMERA,0:view,Input
4 | data skinTone_output = image:640,480,U008:view,skinTone_output
5 | data canny_output = image:640,480,U008:view,canny_output
6 | data bubble_output = image:640,480,U008:view,Bubble_Pop_Output
7 |
8 | # threshold objects
9 | data thr95 = threshold:BINARY,UINT8:INIT,95 # threshold for computing R > 95
10 | data thr40 = threshold:BINARY,UINT8:INIT,40 # threshold for computing G > 40
11 | data thr20 = threshold:BINARY,UINT8:INIT,20 # threshold for computing B > 20
12 | data thr15 = threshold:BINARY,UINT8:INIT,15 # threshold for computing R-G > 15
13 | data thr0 = threshold:BINARY,UINT8:INIT,0 # threshold for computing R-B > 0
14 |
15 | # virtual image objects for intermediate results
16 | data R = image-virtual:0,0,U008
17 | data G = image-virtual:0,0,U008
18 | data B = image-virtual:0,0,U008
19 | data RmG = image-virtual:0,0,U008
20 | data RmB = image-virtual:0,0,U008
21 | data R95 = image-virtual:0,0,U008
22 | data G40 = image-virtual:0,0,U008
23 | data B20 = image-virtual:0,0,U008
24 | data RmG15 = image-virtual:0,0,U008
25 | data RmB0 = image-virtual:0,0,U008
26 | data and1 = image-virtual:0,0,U008
27 | data and2 = image-virtual:0,0,U008
28 | data and3 = image-virtual:0,0,U008
29 |
30 | # extract R,G,B channels and compute R-G and R-B
31 | node org.khronos.openvx.channel_extract input !CHANNEL_R R # extract R channel
32 | node org.khronos.openvx.channel_extract input !CHANNEL_G G # extract G channel
33 | node org.khronos.openvx.channel_extract input !CHANNEL_B B # extract B channel
34 | node org.khronos.openvx.subtract R G !SATURATE RmG # compute R-G
35 | node org.khronos.openvx.subtract R B !SATURATE RmB # compute R-B
36 |
37 | # compute threshold
38 | node org.khronos.openvx.threshold R thr95 R95 # compute R > 95
39 | node org.khronos.openvx.threshold G thr40 G40 # compute G > 40
40 | node org.khronos.openvx.threshold B thr20 B20 # compute B > 20
41 | node org.khronos.openvx.threshold RmG thr15 RmG15 # compute RmG > 15
42 | node org.khronos.openvx.threshold RmB thr0 RmB0 # compute RmB > 0
43 |
44 | # aggregate all thresholded values to produce SKIN pixels
45 | node org.khronos.openvx.and R95 G40 and1 # compute R95 & G40
46 | node org.khronos.openvx.and and1 B20 and2 # compute B20 & and1
47 | node org.khronos.openvx.and RmG15 RmB0 and3 # compute RmG15 & RmB0
48 | node org.khronos.openvx.and and2 and3 skinTone_output # compute and2 & and3 as skinTone_output
49 |
50 | # Create Canny Edge Detector
51 | data inter_yuv = image-virtual:640,480,IYUV
52 | node org.khronos.openvx.color_convert input inter_yuv
53 |
54 | data inter_luma = image-virtual:640,480,U008
55 | node org.khronos.openvx.channel_extract inter_yuv !CHANNEL_Y inter_luma
56 |
57 | data input_hyst = threshold:RANGE,UINT8:INIT,60,80
58 | data input_gradient_size = scalar:INT32,3
59 | data inter_canny = image-virtual:640,480,U008
60 | node org.khronos.openvx.canny_edge_detector inter_luma input_hyst input_gradient_size !NORM_L1 inter_canny
61 |
62 | # OR skinTone skinTone_output with Canny skinTone_output
63 | node org.khronos.openvx.or inter_canny skinTone_output canny_output
64 |
65 | node org.pop.bubble_pop canny_output bubble_output
66 |
--------------------------------------------------------------------------------
/bubble-pop/image/b20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KhronosGroup/openvx-samples/458c983626ed2d574ccd1058a203f999e132131e/bubble-pop/image/b20.png
--------------------------------------------------------------------------------
/bubble-pop/include/internal_opencvTunnel.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #ifndef _CV_TUNNEL_
24 | #define _CV_TUNNEL_
25 |
26 | #if _WIN32
27 | #include
28 | #endif
29 |
30 | #include"vx_pop.h"
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 |
41 | using namespace cv;
42 | using namespace std;
43 |
44 | #define STATUS_ERROR_CHECK(call){vx_status status = call; if(status!= VX_SUCCESS) return status;}
45 | #define PARAM_ERROR_CHECK(call){vx_status status = call; if(status!= VX_SUCCESS) goto exit;}
46 |
47 | int VX_to_CV_Image(Mat**, vx_image);
48 | int VX_to_CV_MATRIX(Mat**, vx_matrix);
49 |
50 | int CV_to_VX_Pyramid(vx_pyramid, vector);
51 | int CV_to_VX_Image(vx_image, Mat*);
52 |
53 | int CV_to_VX_keypoints(vector, vx_array);
54 | int CVPoints2f_to_VX_keypoints(vector, vx_array);
55 | int CV_DESP_to_VX_DESP(Mat, vx_array, int);
56 |
57 | int match_vx_image_parameters(vx_image, vx_image);
58 | void overlay_bubble(const Mat &, const Mat &, Mat &, Point2i);
59 |
60 | class Kernellist
61 | {
62 | public:
63 | struct node{ public: std::function func; node* next; };
64 | int count;
65 | Kernellist(int max){ top = nullptr; maxnum = max; count = 0;}
66 |
67 | vx_status ADD(std::function element)
68 | {
69 | vx_status status = VX_SUCCESS;
70 | if (count == maxnum) return VX_ERROR_NO_RESOURCES;
71 | else
72 | {
73 | node *newTop = new node;
74 | if (top == nullptr){ newTop->func = element; newTop->next = nullptr; top = newTop; count++; }
75 | else{ newTop->func = element; newTop->next = top; top = newTop; count++; }
76 | }
77 | return status;
78 | }
79 |
80 | vx_status REMOVE()
81 | {
82 | vx_status status = VX_SUCCESS;
83 | if (top == nullptr) return VX_ERROR_NO_RESOURCES;
84 | else{ node * old = top; top = top->next; count--; delete(old); }
85 | return status;
86 | }
87 |
88 | vx_status PUBLISH(vx_context context)
89 | {
90 | vx_status status = VX_SUCCESS;
91 |
92 | if (top == nullptr) { vxAddLogEntry((vx_reference)context, VX_ERROR_NO_RESOURCES, "PUBLISH Fail, Kernel list is empty"); return VX_ERROR_NO_RESOURCES; }
93 |
94 | else
95 | {
96 | node * Kernel = top;
97 | for (int i = 0; i < count; i++){ STATUS_ERROR_CHECK(Kernel->func(context)); Kernel = Kernel->next;}
98 | }
99 | return status;
100 | }
101 |
102 | private:
103 | node *top; int maxnum;
104 | };
105 |
106 | static Kernellist *Kernel_List;
107 |
108 | #endif
109 |
--------------------------------------------------------------------------------
/bubble-pop/include/internal_publishKernels.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2015 Advanced Micro Devices, Inc. All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 | #ifndef _PUBLISH_KERNELS_H_
23 | #define _PUBLISH_KERNELS_H_
24 |
25 | #if _WIN32
26 | #define SHARED_PUBLIC __declspec(dllexport)
27 | #else
28 | #define SHARED_PUBLIC __attribute__ ((visibility ("default")))
29 | #endif
30 |
31 | #include "internal_opencvTunnel.h"
32 |
33 | #define MAX_KERNELS 10
34 |
35 | extern "C" SHARED_PUBLIC vx_status VX_API_CALL vxPublishKernels(vx_context context);
36 |
37 | vx_status ADD_KERENEL(std::function);
38 | vx_status get_kernels_to_publish();
39 |
40 | vx_status VX_bubbles_pop_Register(vx_context);
41 | vx_status VX_donut_pop_Register(vx_context);
42 |
43 | #define VX_KERNEL_EXT_POP_BUBBLE_POP_NAME "org.pop.bubble_pop"
44 | #define VX_KERNEL_EXT_POP_DONUT_POP_NAME "org.pop.donut_pop"
45 |
46 | #endif //_PUBLISH_KERNELS_H_
47 |
48 |
--------------------------------------------------------------------------------
/bubble-pop/include/vx_ext_pop.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 | #include "VX/vx.h"
23 | #include
24 | #include "opencv2/opencv.hpp"
25 |
26 | #if _WIN32
27 | #define SHARED_PUBLIC __declspec(dllexport)
28 | #else
29 | #define SHARED_PUBLIC __attribute__ ((visibility ("default")))
30 | #endif
31 |
32 | #ifndef dimof
33 | #define dimof(x) (sizeof(x)/sizeof(x[0]))
34 | #endif
35 |
36 | vx_node vxCreateNodeByStructure(vx_graph graph, vx_enum kernelenum, vx_reference params[], vx_uint32 num);
37 |
38 | #ifdef __cplusplus
39 | extern "C" {
40 | #endif
41 |
42 | /*!***********************************************************************************************************
43 | VX POP - Bubble Pop VX_API_ENTRY C Function NODE
44 | *************************************************************************************************************/
45 | /*! \brief [Graph] Creates a OpenCV blur function node.
46 | * \param [in] graph The reference to the graph.
47 | * \param [in] input The input image in \ref VX_DF_IMAGE_U8 format.
48 | * \param [out] output The output image is as same size and type of input.
49 | * \return \ref vx_node.
50 | * \retval vx_node A node reference. Any possible errors preventing a successful creation should be checked using \ref vxGetStatus*/
51 | extern "C" SHARED_PUBLIC vx_node VX_API_CALL vxExtPopNode_bubblePop(vx_graph graph, vx_image input, vx_image output);
52 |
53 | /*!***********************************************************************************************************
54 | VX POP - Donut Pop VX_API_ENTRY C Function NODE
55 | *************************************************************************************************************/
56 | /*! \brief [Graph] Creates a OpenCV blur function node.
57 | * \param [in] graph The reference to the graph.
58 | * \param [in] input The input image in \ref VX_DF_IMAGE_U8 format.
59 | * \param [out] output The output image is as same size and type of input.
60 | * \return \ref vx_node.
61 | * \retval vx_node A node reference. Any possible errors preventing a successful creation should be checked using \ref vxGetStatus*/
62 | extern "C" SHARED_PUBLIC vx_node VX_API_CALL vxExtPopNode_donutPop(vx_graph graph, vx_image input, vx_image output);
63 |
64 | #ifdef __cplusplus
65 | }
66 | #endif
67 |
--------------------------------------------------------------------------------
/bubble-pop/include/vx_pop.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #ifndef _VX_EXT_AMD_POP_H_
24 | #define _VX_EXT_AMD_POP_H_
25 |
26 | #include"vx_ext_pop.h"
27 |
28 | #ifdef __cplusplus
29 | extern "C" {
30 | #endif
31 |
32 | /*! \brief The AMD extension library for Pop */
33 | #define VX_LIBRARY_EXT_POP 3
34 |
35 | /*!
36 | * \brief The list of available vision kernels in the Pop extension library.
37 | */
38 | enum vx_kernel_ext_amd_pop_e
39 | {
40 | /*!
41 | * \brief The Bubble Pop kernel. Kernel name is "org.pop.bubble_pop".
42 | */
43 | VX_KERNEL_EXT_POP_BUBBLE_POP = VX_KERNEL_BASE(VX_ID_AMD, VX_LIBRARY_EXT_POP) + 0x001,
44 | /*!
45 | * \brief The Donut Pop kernel. Kernel name is "org.pop.donut_pop".
46 | */
47 | VX_KERNEL_EXT_POP_DONUT_POP = VX_KERNEL_BASE(VX_ID_AMD, VX_LIBRARY_EXT_POP) + 0x002,
48 | };
49 |
50 | #ifdef __cplusplus
51 | }
52 | #endif
53 |
54 | #endif
55 |
--------------------------------------------------------------------------------
/bubble-pop/source/AMD_VX_Pop_Bubble.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include"internal_publishKernels.h"
24 | #include
25 |
26 | int poppedBubbles = 0;
27 | int globalBubblesflag = 0;
28 | Mat globalBubblesRefImage;
29 | int globalBubblesChange = 0;
30 | Mat bubble_PNG = imread("image/b20.png",-1);
31 |
32 | /************************************************************************************************************
33 | Overlay Image Function
34 | *************************************************************************************************************/
35 | void overlayImage(const Mat &background, const Mat &foreground,Mat &output, Point2i location)
36 | {
37 | background.copyTo(output);
38 |
39 | for (int y = std::max(location.y, 0); y < background.rows; ++y)
40 | {
41 | int fY = y - location.y;
42 | if (fY >= foreground.rows)
43 | break;
44 |
45 | for (int x = std::max(location.x, 0); x < background.cols; ++x)
46 | {
47 | int fX = x - location.x;
48 |
49 |
50 | if (fX >= foreground.cols)
51 | break;
52 |
53 | double opacity =
54 | ((double)foreground.data[fY * foreground.step + fX * foreground.channels() + 3])
55 |
56 | / 255.;
57 |
58 | for (int c = 0; opacity > 0 && c < output.channels(); ++c)
59 | {
60 | unsigned char foregroundPx =
61 | foreground.data[fY * foreground.step + fX * foreground.channels() + c];
62 | unsigned char backgroundPx =
63 | background.data[y * background.step + x * background.channels() + c];
64 | output.data[y*output.step + output.channels()*x + c] =
65 | backgroundPx * (1. - opacity) + foregroundPx * opacity;
66 | }
67 | }
68 | }
69 | }
70 |
71 | /************************************************************************************************************
72 | Bubbles
73 | *************************************************************************************************************/
74 | class AMD_bubble_pop
75 | {
76 | private:
77 | int bubbleX, bubbleY, bubbleWidth, bubbleHeight;
78 |
79 | public:
80 | AMD_bubble_pop(int bX, int bY, int bW, int bH)
81 | {
82 | bubbleX = bX; bubbleY = bY; bubbleWidth = bW; bubbleHeight = bH;
83 | }
84 |
85 | ~AMD_bubble_pop()
86 | {
87 | bubbleX = 0; bubbleY = 0; bubbleWidth = 0; bubbleHeight = 0;
88 | }
89 |
90 | int update(int width, int height, Mat *Image)
91 | {
92 | int movementAmount = 0;
93 | if (globalBubblesflag > 10)
94 | {
95 | Mat diff_image;
96 | absdiff(*Image, globalBubblesRefImage, diff_image);
97 | blur(diff_image, diff_image, Size(3, 3));
98 |
99 | cv::erode(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
100 | cv::erode(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
101 | cv::dilate(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
102 | cv::dilate(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
103 |
104 | cv::threshold(diff_image, diff_image, 160, 255, 0);
105 |
106 | unsigned char *input = (unsigned char*)(diff_image.data);
107 | int b;
108 |
109 | for (int x = bubbleX; x <= (bubbleX + (bubbleWidth - 1)); x++)
110 | for (int y = bubbleY; y <= (bubbleY + (bubbleWidth - 1)); y++)
111 | {
112 | if ((x < diff_image.cols && x > 0) && (y < diff_image.rows && y > 0))
113 | {
114 | b = input[diff_image.cols * y + x];
115 | if (b == 255)
116 | movementAmount++;
117 | }
118 | }
119 | }
120 |
121 | if (movementAmount > 100)
122 | {
123 | poppedBubbles++;
124 | return 1;
125 | }
126 | else
127 | {
128 | bubbleY += 5;
129 |
130 | if (bubbleY > height)
131 | return 1;
132 |
133 | Mat test_image;
134 | test_image = *Image;
135 |
136 | // draw bubbles
137 | if(bubble_PNG.empty()){ printf("--image/b20.png-- Image not found\n"); return -1;};
138 | overlayImage(test_image, bubble_PNG, *Image, cv::Point(bubbleX, bubbleY));
139 |
140 | return 0;
141 | }
142 | }
143 | };
144 |
145 | struct Linked_list_pop{
146 | AMD_bubble_pop bubble;
147 | int data;
148 | struct Linked_list_pop* next;
149 | };
150 | typedef struct Linked_list_pop BubbleNode;
151 |
152 | //Function Prototyping
153 | BubbleNode* insert_pop(BubbleNode* head, BubbleNode* x);
154 | BubbleNode* pop_position_delete(BubbleNode* head, int p);
155 | BubbleNode* pop_clean_node(BubbleNode* head);
156 | void draw_pop_bubbles(int, int, Mat*);
157 | BubbleNode *POPbubble = NULL;
158 |
159 | /************************************************************************************************************
160 | Draw Bubbles
161 | *************************************************************************************************************/
162 | void draw_pop_bubbles(int width, int height, Mat *Image)
163 | {
164 | static int count = 0;
165 |
166 | int randx = rand() % (width + 1);
167 | AMD_bubble_pop new_element = AMD_bubble_pop(randx, 0, 20, 20);
168 |
169 | BubbleNode * temp = (BubbleNode*)malloc(sizeof(BubbleNode));
170 | temp->bubble = new_element;
171 | temp->next = NULL;
172 | POPbubble = insert_pop(POPbubble, temp);
173 | count++;
174 |
175 | BubbleNode *_bubbles;
176 | _bubbles = POPbubble;
177 | int K = 0;
178 | int flag = 0;
179 |
180 | while (_bubbles != NULL)
181 | {
182 | K++;
183 | flag = 0;
184 |
185 | if (_bubbles->bubble.update(width, height, Image) == 1)
186 | {
187 | _bubbles = _bubbles->next;
188 | POPbubble = pop_position_delete(POPbubble, K);
189 | count--;
190 | K--;
191 | flag = 1;
192 | }
193 |
194 | if (flag == 0)
195 | _bubbles = _bubbles->next;
196 | }
197 |
198 | return;
199 |
200 | }
201 |
202 | /************************************************************************************************************
203 | input parameter validator.
204 | param [in] node The handle to the node.
205 | param [in] index The index of the parameter to validate.
206 | *************************************************************************************************************/
207 | static vx_status VX_CALLBACK VX_bubbles_InputValidator(vx_node node, vx_uint32 index)
208 | {
209 | vx_status status = VX_SUCCESS;
210 | vx_parameter param = vxGetParameterByIndex(node, index);
211 |
212 | if (index == 0)
213 | {
214 | vx_image image;
215 | vx_df_image df_image = VX_DF_IMAGE_VIRT;
216 | STATUS_ERROR_CHECK(vxQueryParameter(param, VX_PARAMETER_ATTRIBUTE_REF, &image, sizeof(vx_image)));
217 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &df_image, sizeof(df_image)));
218 | if (df_image != VX_DF_IMAGE_U8)
219 | status = VX_ERROR_INVALID_VALUE;
220 | vxReleaseImage(&image);
221 | }
222 |
223 | else if (index == 1)
224 | {
225 | vx_image image;
226 | vx_df_image df_image = VX_DF_IMAGE_VIRT;
227 | STATUS_ERROR_CHECK(vxQueryParameter(param, VX_PARAMETER_ATTRIBUTE_REF, &image, sizeof(vx_image)));
228 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &df_image, sizeof(df_image)));
229 | if (df_image != VX_DF_IMAGE_U8 && df_image != VX_DF_IMAGE_RGB)
230 | status = VX_ERROR_INVALID_VALUE;
231 | vxReleaseImage(&image);
232 | }
233 |
234 | vxReleaseParameter(¶m);
235 | return status;
236 | }
237 |
238 | /************************************************************************************************************
239 | output parameter validator.
240 | *************************************************************************************************************/
241 | static vx_status VX_CALLBACK VX_bubbles_OutputValidator(vx_node node, vx_uint32 index, vx_meta_format meta)
242 | {
243 | vx_status status = VX_SUCCESS;
244 | if (index == 1)
245 | {
246 | vx_parameter output_param = vxGetParameterByIndex(node, 1);
247 | vx_image output; vx_uint32 width = 0, height = 0; vx_df_image format = VX_DF_IMAGE_VIRT;
248 |
249 | STATUS_ERROR_CHECK(vxQueryParameter(output_param, VX_PARAMETER_ATTRIBUTE_REF, &output, sizeof(vx_image)));
250 | STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
251 | STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
252 | STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
253 |
254 | if (format != VX_DF_IMAGE_U8 && format != VX_DF_IMAGE_RGB)
255 | status = VX_ERROR_INVALID_VALUE;
256 |
257 | STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
258 | STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
259 | STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
260 |
261 | vxReleaseImage(&output);
262 | vxReleaseParameter(&output_param);
263 | }
264 | return status;
265 | }
266 |
267 | /************************************************************************************************************
268 | Execution Kernel
269 | *************************************************************************************************************/
270 | static vx_status VX_CALLBACK VX_bubbles_Kernel(vx_node node, const vx_reference *parameters, vx_uint32 num)
271 | {
272 | vx_status status = VX_SUCCESS;
273 |
274 | vx_image image_in = (vx_image)parameters[0];
275 | vx_image image_out = (vx_image)parameters[1];
276 | Mat *mat, bl;
277 |
278 | // wait to restart - press any key
279 | if(poppedBubbles >= 1015){ poppedBubbles = 0; waitKey(0);}
280 |
281 | //Converting VX Image to OpenCV Mat
282 | STATUS_ERROR_CHECK(VX_to_CV_Image(&mat, image_in));
283 | Mat Image = *mat, clean_img;
284 | flip(Image, Image, 1);
285 |
286 | if (globalBubblesflag == 0){ globalBubblesRefImage = Image;} else{clean_img = Image;}
287 |
288 | draw_pop_bubbles(Image.cols, Image.rows, &Image);
289 |
290 | std::ostringstream statusStr;
291 | if (poppedBubbles >= 1000)
292 | {
293 | statusStr << "Congratulations! Click any Key to Contiue Popping!";
294 | cv::putText(Image, statusStr.str(), cv::Point(5, int(Image.rows/2)), FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(200, 200, 250), 1, cv::LINE_AA);
295 | }
296 | else
297 | {
298 | statusStr << "Bubbles Popped: " << poppedBubbles;
299 | cv::putText(Image, statusStr.str(), cv::Point(30, 30), FONT_HERSHEY_COMPLEX_SMALL, 1.2, cv::Scalar(200, 200, 250), 1, cv::LINE_AA);
300 | }
301 |
302 | //Converting OpenCV Mat into VX Image
303 | STATUS_ERROR_CHECK(CV_to_VX_Image(image_out, &Image));
304 |
305 | if (globalBubblesflag == 0) globalBubblesflag++; else{ globalBubblesRefImage = clean_img; globalBubblesflag++; }
306 |
307 | return status;
308 | }
309 |
310 | /************************************************************************************************************
311 | Function to Register the Kernel for Publish
312 | *************************************************************************************************************/
313 | vx_status VX_bubbles_pop_Register(vx_context context)
314 | {
315 | vx_status status = VX_SUCCESS;
316 | vx_kernel kernel = vxAddKernel(context,
317 | "org.pop.bubble_pop",
318 | VX_KERNEL_EXT_POP_BUBBLE_POP,
319 | VX_bubbles_Kernel,
320 | 2,
321 | VX_bubbles_InputValidator,
322 | VX_bubbles_OutputValidator,
323 | nullptr,
324 | nullptr);
325 |
326 | if (kernel)
327 | {
328 | PARAM_ERROR_CHECK(vxAddParameterToKernel(kernel, 0, VX_INPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED));
329 | PARAM_ERROR_CHECK(vxAddParameterToKernel(kernel, 1, VX_OUTPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED));
330 | PARAM_ERROR_CHECK(vxFinalizeKernel(kernel));
331 | }
332 |
333 | if (status != VX_SUCCESS)
334 | {
335 | exit: vxRemoveKernel(kernel); return VX_FAILURE;
336 | }
337 |
338 | return status;
339 | }
340 |
341 | /*
342 | * linked_list.c
343 | * Author: Kiriti Nagesh Gowda
344 | */
345 |
346 | //Insert a variable function
347 | BubbleNode* insert_pop(BubbleNode* head, BubbleNode* x)
348 | {
349 | BubbleNode* temp;
350 | BubbleNode* temp1 = x;
351 |
352 | if (head == NULL)
353 | head = temp1;
354 |
355 | else{
356 | temp = head;
357 | while (temp->next != NULL){
358 | temp = temp->next;
359 | }
360 | temp->next = temp1;
361 | }
362 | return (head);
363 | }
364 |
365 | //Delete a node from the list
366 | BubbleNode* pop_position_delete(BubbleNode* head, int p)
367 | {
368 | BubbleNode* temp;
369 | BubbleNode* temp1;
370 | int count = 2;
371 | temp = head;
372 |
373 | if (temp == NULL || p <= 0){
374 | printf("The List is empty or the position is invalid\n");
375 | return (head);
376 | }
377 |
378 | if (p == 1){
379 | head = temp->next;
380 | free(temp);
381 | return (head);
382 | }
383 | while (temp != NULL){
384 | if (count == (p))
385 | {
386 | temp1 = temp->next;
387 | temp->next = temp1->next;
388 | free(temp1);
389 | return (head);
390 | }
391 | temp = temp->next;
392 |
393 | if (temp == NULL) break;
394 | ++count;
395 | }
396 | return head;
397 | }
398 |
399 | //clean node
400 | BubbleNode *pop_clean_node(BubbleNode * head)
401 | {
402 |
403 | BubbleNode *temp1;
404 | while (head != NULL){
405 | temp1 = head->next;
406 | free(head);
407 | head = temp1;
408 | }
409 | return(head);
410 | }
411 |
--------------------------------------------------------------------------------
/bubble-pop/source/AMD_VX_Pop_Donut.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include"internal_publishKernels.h"
24 | #include
25 |
26 | int poppedDonuts = 0;
27 | int globalDonutFlag = 0;
28 | Mat globalDonutRefImage;
29 | int globalDonutChange = 0;
30 |
31 | /************************************************************************************************************
32 | Bubbles
33 | *************************************************************************************************************/
34 | class AMD_donut_pop
35 | {
36 | private:
37 | int donutX, donutY, donutWidth, donutHeight;
38 |
39 | public:
40 | AMD_donut_pop(int bX, int bY, int bW, int bH)
41 | {
42 | donutX = bX; donutY = bY; donutWidth = bW; donutHeight = bH;
43 | }
44 |
45 | ~AMD_donut_pop()
46 | {
47 | donutX = 0; donutY = 0; donutWidth = 0; donutHeight = 0;
48 | }
49 |
50 | int update(int width, int height, Mat *Image)
51 | {
52 | int movementAmount = 0;
53 | if (globalDonutFlag > 10)
54 | {
55 | Mat diff_image;
56 | absdiff(*Image, globalDonutRefImage, diff_image);
57 | blur(diff_image, diff_image, Size(3, 3));
58 |
59 | cv::erode(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
60 | cv::erode(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
61 | cv::dilate(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
62 | cv::dilate(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
63 |
64 | cv::threshold(diff_image, diff_image, 160, 255, 0);
65 |
66 | unsigned char *input = (unsigned char*)(diff_image.data);
67 | int b;
68 |
69 | for (int x = donutX; x <= (donutX + (donutWidth - 1)); x++)
70 | for (int y = donutY; y <= (donutY + (donutWidth - 1)); y++)
71 | {
72 | if ((x < diff_image.cols && x > 0) && (y < diff_image.rows && y > 0))
73 | {
74 | b = input[diff_image.cols * y + x];
75 | if (b == 255)
76 | movementAmount++;
77 | }
78 | }
79 | }
80 |
81 | if (movementAmount > 100)
82 | {
83 | poppedDonuts++;
84 | return 1;
85 | }
86 | else
87 | {
88 | donutY += 5;
89 |
90 | if (donutY > height)
91 | return 1;
92 |
93 | Mat test_image;
94 | test_image = *Image;
95 |
96 | // draw Donuts
97 | if (globalDonutChange == 0)
98 | {
99 | Point2f cen(donutX, donutY);
100 | cv::circle(*Image, cen, 8, Scalar(255, 255, 55), 5);
101 | }
102 | else
103 | {
104 | Point2f cen(donutX, donutY);
105 | cv::circle(*Image, cen, 5, Scalar(255, 255, 55), 5);
106 | }
107 |
108 | return 0;
109 | }
110 | }
111 | };
112 |
113 | struct Linked_list_pop{
114 | AMD_donut_pop donut;
115 | int data;
116 | struct Linked_list_pop* next;
117 | };
118 | typedef struct Linked_list_pop donutNode;
119 |
120 | //Function Prototyping
121 | donutNode* donut_insert(donutNode* head, donutNode* x);
122 | donutNode* donut_position_delete(donutNode* head, int p);
123 | donutNode* donut_clean_node(donutNode* head);
124 | int draw_pop_donuts(int, int, Mat*);
125 | donutNode *PopDonuts = NULL;
126 |
127 | /************************************************************************************************************
128 | Draw Bubbles
129 | *************************************************************************************************************/
130 | int draw_pop_donuts(int width, int height, Mat *Image)
131 | {
132 | static int count = 0;
133 |
134 | int randx = rand() % (width + 1);
135 | AMD_donut_pop new_element = AMD_donut_pop(randx, 0, 20, 20);
136 |
137 | donutNode * temp = (donutNode*)malloc(sizeof(donutNode));
138 | temp->donut = new_element;
139 | temp->next = NULL;
140 | PopDonuts = donut_insert(PopDonuts, temp);
141 | count++;
142 |
143 | donutNode *_donuts;
144 | _donuts = PopDonuts;
145 | int K = 0;
146 | int flag = 0;
147 |
148 | while (_donuts != NULL)
149 | {
150 | K++;
151 | flag = 0;
152 |
153 | if (_donuts->donut.update(width, height, Image) == 1)
154 | {
155 | _donuts = _donuts->next;
156 | PopDonuts = donut_position_delete(PopDonuts, K);
157 | count--;
158 | K--;
159 | flag = 1;
160 | }
161 |
162 | if (flag == 0)
163 | _donuts = _donuts->next;
164 | }
165 |
166 | return 0;
167 |
168 | }
169 |
170 | /************************************************************************************************************
171 | input parameter validator.
172 | param [in] node The handle to the node.
173 | param [in] index The index of the parameter to validate.
174 | *************************************************************************************************************/
175 | vx_status VX_CALLBACK VX_bubbles_InputValidator(vx_node node, vx_uint32 index)
176 | {
177 | vx_status status = VX_SUCCESS;
178 | vx_parameter param = vxGetParameterByIndex(node, index);
179 |
180 | if (index == 0)
181 | {
182 | vx_image image;
183 | vx_df_image df_image = VX_DF_IMAGE_VIRT;
184 | STATUS_ERROR_CHECK(vxQueryParameter(param, VX_PARAMETER_ATTRIBUTE_REF, &image, sizeof(vx_image)));
185 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &df_image, sizeof(df_image)));
186 | if (df_image != VX_DF_IMAGE_U8)
187 | status = VX_ERROR_INVALID_VALUE;
188 | vxReleaseImage(&image);
189 | }
190 |
191 | else if (index == 1)
192 | {
193 | vx_image image;
194 | vx_df_image df_image = VX_DF_IMAGE_VIRT;
195 | STATUS_ERROR_CHECK(vxQueryParameter(param, VX_PARAMETER_ATTRIBUTE_REF, &image, sizeof(vx_image)));
196 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &df_image, sizeof(df_image)));
197 | if (df_image != VX_DF_IMAGE_U8 && df_image != VX_DF_IMAGE_RGB)
198 | status = VX_ERROR_INVALID_VALUE;
199 | vxReleaseImage(&image);
200 | }
201 |
202 | vxReleaseParameter(¶m);
203 | return status;
204 | }
205 |
206 | /************************************************************************************************************
207 | output parameter validator.
208 | *************************************************************************************************************/
209 | vx_status VX_CALLBACK VX_bubbles_OutputValidator(vx_node node, vx_uint32 index, vx_meta_format meta)
210 | {
211 | vx_status status = VX_SUCCESS;
212 | if (index == 1)
213 | {
214 | vx_parameter output_param = vxGetParameterByIndex(node, 1);
215 | vx_image output; vx_uint32 width = 0, height = 0; vx_df_image format = VX_DF_IMAGE_VIRT;
216 |
217 | STATUS_ERROR_CHECK(vxQueryParameter(output_param, VX_PARAMETER_ATTRIBUTE_REF, &output, sizeof(vx_image)));
218 | STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
219 | STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
220 | STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
221 |
222 | if (format != VX_DF_IMAGE_U8 && format != VX_DF_IMAGE_RGB)
223 | status = VX_ERROR_INVALID_VALUE;
224 |
225 | STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
226 | STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
227 | STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
228 |
229 | vxReleaseImage(&output);
230 | vxReleaseParameter(&output_param);
231 | }
232 | return status;
233 | }
234 |
235 | /************************************************************************************************************
236 | Execution Kernel
237 | *************************************************************************************************************/
238 | vx_status VX_CALLBACK VX_bubbles_Kernel(vx_node node, const vx_reference *parameters, vx_uint32 num)
239 | {
240 | vx_status status = VX_SUCCESS;
241 |
242 | vx_image image_in = (vx_image)parameters[0];
243 | vx_image image_out = (vx_image)parameters[1];
244 | Mat *mat, bl;
245 |
246 | // wait to restart - press any key
247 | if(poppedDonuts >= 1015){ poppedDonuts = 0; waitKey(0);}
248 |
249 | //Converting VX Image to OpenCV Mat
250 | STATUS_ERROR_CHECK(VX_to_CV_Image(&mat, image_in));
251 | Mat Image = *mat, clean_img;
252 | flip(Image, Image, 1);
253 |
254 | if (globalDonutFlag == 0){
255 | globalDonutRefImage = Image;
256 | }
257 | else{
258 | clean_img = Image;
259 | }
260 |
261 | // change donut size - press "d"
262 | if(waitKey(2) == 100){if (globalDonutChange == 0) globalDonutChange = 1; else globalDonutChange = 0;}
263 | if(draw_pop_donuts(Image.cols, Image.rows, &Image))
264 | return VX_FAILURE;
265 |
266 | std::ostringstream statusStr;
267 | if (poppedDonuts >= 1000)
268 | {
269 | statusStr << "Congratulations! Click any Key to Contiue Popping!";
270 | cv::putText(Image, statusStr.str(), cv::Point(5, int(Image.rows/2)), FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(200, 200, 250), 1, cv::LINE_AA);
271 | }
272 | else
273 | {
274 | statusStr << "Bubbles Popped: " << poppedDonuts;
275 | cv::putText(Image, statusStr.str(), cv::Point(30, 30), FONT_HERSHEY_COMPLEX_SMALL, 1.2, cv::Scalar(200, 200, 250), 1, cv::LINE_AA);
276 | }
277 |
278 | //Converting OpenCV Mat into VX Image
279 | STATUS_ERROR_CHECK(CV_to_VX_Image(image_out, &Image));
280 |
281 | if (globalDonutFlag == 0) globalDonutFlag++; else{ globalDonutRefImage = clean_img; globalDonutFlag++; }
282 |
283 | return status;
284 | }
285 |
286 | /************************************************************************************************************
287 | Function to Register the Kernel for Publish
288 | *************************************************************************************************************/
289 | vx_status VX_donut_pop_Register(vx_context context)
290 | {
291 | vx_status status = VX_SUCCESS;
292 | vx_kernel kernel = vxAddKernel(context,
293 | "org.pop.donut_pop",
294 | VX_KERNEL_EXT_POP_DONUT_POP,
295 | VX_bubbles_Kernel,
296 | 2,
297 | VX_bubbles_InputValidator,
298 | VX_bubbles_OutputValidator,
299 | nullptr,
300 | nullptr);
301 |
302 | if (kernel)
303 | {
304 | PARAM_ERROR_CHECK(vxAddParameterToKernel(kernel, 0, VX_INPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED));
305 | PARAM_ERROR_CHECK(vxAddParameterToKernel(kernel, 1, VX_OUTPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED));
306 | PARAM_ERROR_CHECK(vxFinalizeKernel(kernel));
307 | }
308 |
309 | if (status != VX_SUCCESS)
310 | {
311 | exit: vxRemoveKernel(kernel); return VX_FAILURE;
312 | }
313 |
314 | return status;
315 | }
316 |
317 | /*
318 | * linked_list.c
319 | * Author: Kiriti Nagesh Gowda
320 | */
321 |
322 | //Insert a variable function
323 | donutNode* donut_insert(donutNode* head, donutNode* x)
324 | {
325 | donutNode* temp;
326 | donutNode* temp1 = x;
327 |
328 | if (head == NULL)
329 | head = temp1;
330 |
331 | else{
332 | temp = head;
333 | while (temp->next != NULL){
334 | temp = temp->next;
335 | }
336 | temp->next = temp1;
337 | }
338 | return (head);
339 | }
340 |
341 | //Delete a node from the list
342 | donutNode* donut_position_delete(donutNode* head, int p)
343 | {
344 | donutNode* temp;
345 | donutNode* temp1;
346 | int count = 2;
347 | temp = head;
348 |
349 | if (temp == NULL || p <= 0){
350 | printf("The List is empty or the position is invalid\n");
351 | return (head);
352 | }
353 |
354 | if (p == 1){
355 | head = temp->next;
356 | free(temp);
357 | return (head);
358 | }
359 | while (temp != NULL){
360 | if (count == (p))
361 | {
362 | temp1 = temp->next;
363 | temp->next = temp1->next;
364 | free(temp1);
365 | return (head);
366 | }
367 | temp = temp->next;
368 |
369 | if (temp == NULL) break;
370 | ++count;
371 | }
372 | return head;
373 | }
374 |
375 | //clean node
376 | donutNode *donut_clean_node(donutNode * head)
377 | {
378 |
379 | donutNode *temp1;
380 | while (head != NULL){
381 | temp1 = head->next;
382 | free(head);
383 | head = temp1;
384 | }
385 | return(head);
386 | }
--------------------------------------------------------------------------------
/bubble-pop/source/AMD_app.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "opencv2/opencv.hpp"
4 | #include "vx_ext_pop.h"
5 | #include
6 |
7 | using namespace cv;
8 | using namespace std;
9 |
10 | #define ERROR_CHECK_STATUS( status ) { \
11 | vx_status status_ = (status); \
12 | if(status_ != VX_SUCCESS) { \
13 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
14 | exit(1); \
15 | } \
16 | }
17 |
18 | #define ERROR_CHECK_OBJECT( obj ) { \
19 | vx_status status_ = vxGetStatus((vx_reference)(obj)); \
20 | if(status_ != VX_SUCCESS) { \
21 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
22 | exit(1); \
23 | } \
24 | }
25 |
26 | static void VX_CALLBACK log_callback(vx_context context, vx_reference ref, vx_status status, const vx_char string[])
27 | {
28 | size_t len = strlen(string);
29 | if (len > 0) {
30 | printf("%s", string);
31 | if (string[len - 1] != '\n')
32 | printf("\n");
33 | fflush(stdout);
34 | }
35 | }
36 |
37 | int main(int argc, char **argv)
38 | {
39 | if (argc < 2) {
40 | printf("Usage:\n"
41 | "./vxPop --donut\n"
42 | "./vxPop --bubble \n");
43 | return 0;
44 | }
45 |
46 | int width = 720, height = 480;
47 |
48 | // create OpenVX Context
49 | vx_context context = vxCreateContext();
50 | ERROR_CHECK_OBJECT(context);
51 | vxRegisterLogCallback(context, log_callback, vx_false_e);
52 |
53 | // load vx_pop kernels
54 | ERROR_CHECK_STATUS(vxLoadKernels(context, "vx_pop"));
55 |
56 | // create OpenVX Graph
57 | vx_graph graph = vxCreateGraph(context);
58 | ERROR_CHECK_OBJECT(graph);
59 |
60 | // create OpenVX Images
61 | vx_image input_rgb_image = vxCreateImage(context, width, height, VX_DF_IMAGE_RGB);
62 | vx_image output_pop_image = vxCreateImage(context, width, height, VX_DF_IMAGE_U8);
63 | ERROR_CHECK_OBJECT(input_rgb_image);
64 | ERROR_CHECK_OBJECT(output_pop_image);
65 |
66 | // create intermediate images
67 | vx_image yuv_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_IYUV);
68 | vx_image luma_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
69 | vx_image output_canny_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
70 | vx_image output_skinTone_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
71 | vx_image output_canny_skinTone_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
72 | ERROR_CHECK_OBJECT(yuv_image);
73 | ERROR_CHECK_OBJECT(luma_image);
74 | ERROR_CHECK_OBJECT(output_canny_image);
75 | ERROR_CHECK_OBJECT(output_skinTone_image);
76 | ERROR_CHECK_OBJECT(output_canny_skinTone_image);
77 |
78 | // create threshold variable
79 | vx_threshold hyst = vxCreateThreshold(context, VX_THRESHOLD_TYPE_RANGE, VX_TYPE_UINT8);
80 | vx_int32 lower = 80, upper = 100;
81 | vxSetThresholdAttribute(hyst, VX_THRESHOLD_ATTRIBUTE_THRESHOLD_LOWER, &lower, sizeof(lower));
82 | vxSetThresholdAttribute(hyst, VX_THRESHOLD_ATTRIBUTE_THRESHOLD_UPPER, &upper, sizeof(upper));
83 | ERROR_CHECK_OBJECT(hyst);
84 | vx_int32 gradient_size = 3;
85 |
86 | // create intermediate images which are not accessed by the user to be mem optimized
87 | vx_image R_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
88 | vx_image G_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
89 | vx_image B_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
90 | vx_image RmG_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
91 | vx_image RmB_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
92 | vx_image R95_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
93 | vx_image G40_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
94 | vx_image B20_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
95 | vx_image RmG15_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
96 | vx_image RmB0_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
97 | vx_image and1_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
98 | vx_image and2_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
99 | vx_image and3_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
100 | ERROR_CHECK_OBJECT(R_image);
101 | ERROR_CHECK_OBJECT(G_image);
102 | ERROR_CHECK_OBJECT(B_image);
103 | ERROR_CHECK_OBJECT(RmG_image);
104 | ERROR_CHECK_OBJECT(RmB_image);
105 | ERROR_CHECK_OBJECT(R95_image);
106 | ERROR_CHECK_OBJECT(G40_image);
107 | ERROR_CHECK_OBJECT(B20_image);
108 | ERROR_CHECK_OBJECT(RmG15_image);
109 | ERROR_CHECK_OBJECT(RmB0_image);
110 | ERROR_CHECK_OBJECT(and1_image);
111 | ERROR_CHECK_OBJECT(and2_image);
112 | ERROR_CHECK_OBJECT(and3_image);
113 |
114 | // create threshold values
115 | vx_threshold thresh95 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
116 | vx_int32 thresValue95 = 95;
117 | vxSetThresholdAttribute(thresh95, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue95, sizeof(vx_int32));
118 | ERROR_CHECK_OBJECT(thresh95);
119 | vx_threshold thresh40 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
120 | vx_int32 thresValue40 = 40;
121 | vxSetThresholdAttribute(thresh40, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue40, sizeof(vx_int32));
122 | ERROR_CHECK_OBJECT(thresh40);
123 | vx_threshold thresh20 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
124 | vx_int32 thresValue20 = 20;
125 | vxSetThresholdAttribute(thresh20, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue20, sizeof(vx_int32));
126 | ERROR_CHECK_OBJECT(thresh20);
127 | vx_threshold thresh15 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
128 | vx_int32 thresValue15 = 15;
129 | vxSetThresholdAttribute(thresh15, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue15, sizeof(vx_int32));
130 | ERROR_CHECK_OBJECT(thresh15);
131 | vx_threshold thresh0 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
132 | vx_int32 thresValue0 = 0;
133 | vxSetThresholdAttribute(thresh0, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue0, sizeof(vx_int32));
134 | ERROR_CHECK_OBJECT(thresh0);
135 |
136 | // add nodes to the graph
137 | string option = argv[1];
138 | if (option == "--bubble")
139 | {
140 | vx_node nodes[] =
141 | {
142 | // extract R,G,B channels and compute R-G and R-B
143 | vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_R, R_image),
144 | vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_G, G_image),
145 | vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_B, B_image),
146 | vxSubtractNode(graph, R_image, G_image, VX_CONVERT_POLICY_SATURATE, RmG_image),
147 | vxSubtractNode(graph, R_image, B_image, VX_CONVERT_POLICY_SATURATE, RmB_image),
148 | // compute threshold
149 | vxThresholdNode(graph, R_image, thresh95, R95_image),
150 | vxThresholdNode(graph, G_image, thresh40, G40_image),
151 | vxThresholdNode(graph, B_image, thresh20, B20_image),
152 | vxThresholdNode(graph, RmG_image, thresh15, RmG15_image),
153 | vxThresholdNode(graph, RmB_image, thresh0, RmB0_image),
154 | // aggregate all thresholded values to produce SKIN pixels
155 | vxAndNode(graph, R95_image, G40_image, and1_image),
156 | vxAndNode(graph, and1_image, B20_image, and2_image),
157 | vxAndNode(graph, RmG15_image, RmB0_image, and3_image),
158 | vxAndNode(graph, and2_image, and3_image, output_skinTone_image),
159 | // create canny edge
160 | vxColorConvertNode(graph, input_rgb_image, yuv_image),
161 | vxChannelExtractNode(graph, yuv_image, VX_CHANNEL_Y, luma_image),
162 | vxCannyEdgeDetectorNode(graph, luma_image, hyst, gradient_size, VX_NORM_L1, output_canny_image),
163 | // or - canny & skintone images
164 | vxOrNode(graph, output_canny_image, output_skinTone_image, output_canny_skinTone_image),
165 | // vx pop - bubble pop
166 | vxExtPopNode_bubblePop(graph, output_canny_skinTone_image, output_pop_image)
167 | };
168 | for( vx_size i = 0; i < sizeof( nodes ) / sizeof( nodes[0] ); i++ )
169 | {
170 | ERROR_CHECK_OBJECT( nodes[i] );
171 | ERROR_CHECK_STATUS( vxReleaseNode( &nodes[i] ) );
172 | }
173 | }
174 | else
175 | {
176 | vx_node nodes[] =
177 | {
178 | // extract R,G,B channels and compute R-G and R-B
179 | vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_R, R_image),
180 | vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_G, G_image),
181 | vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_B, B_image),
182 | vxSubtractNode(graph, R_image, G_image, VX_CONVERT_POLICY_SATURATE, RmG_image),
183 | vxSubtractNode(graph, R_image, B_image, VX_CONVERT_POLICY_SATURATE, RmB_image),
184 | // compute threshold
185 | vxThresholdNode(graph, R_image, thresh95, R95_image),
186 | vxThresholdNode(graph, G_image, thresh40, G40_image),
187 | vxThresholdNode(graph, B_image, thresh20, B20_image),
188 | vxThresholdNode(graph, RmG_image, thresh15, RmG15_image),
189 | vxThresholdNode(graph, RmB_image, thresh0, RmB0_image),
190 | // aggregate all thresholded values to produce SKIN pixels
191 | vxAndNode(graph, R95_image, G40_image, and1_image),
192 | vxAndNode(graph, and1_image, B20_image, and2_image),
193 | vxAndNode(graph, RmG15_image, RmB0_image, and3_image),
194 | vxAndNode(graph, and2_image, and3_image, output_skinTone_image),
195 | // create canny edge
196 | vxColorConvertNode(graph, input_rgb_image, yuv_image),
197 | vxChannelExtractNode(graph, yuv_image, VX_CHANNEL_Y, luma_image),
198 | vxCannyEdgeDetectorNode(graph, luma_image, hyst, gradient_size, VX_NORM_L1, output_canny_image),
199 | // or - canny & skintone images
200 | vxOrNode(graph, output_canny_image, output_skinTone_image, output_canny_skinTone_image),
201 | // vx pop - donut pop
202 | vxExtPopNode_donutPop(graph, output_canny_skinTone_image, output_pop_image)
203 | };
204 | for( vx_size i = 0; i < sizeof( nodes ) / sizeof( nodes[0] ); i++ )
205 | {
206 | ERROR_CHECK_OBJECT( nodes[i] );
207 | ERROR_CHECK_STATUS( vxReleaseNode( &nodes[i] ) );
208 | }
209 | }
210 |
211 | // verify graph - only once
212 | ERROR_CHECK_STATUS( vxVerifyGraph( graph ) );
213 |
214 | Mat input, input_rgb;
215 | cv::namedWindow("VX POP - LIVE", cv::WINDOW_GUI_EXPANDED);
216 | VideoCapture cap(0);
217 | if (!cap.isOpened()) {
218 | printf("Unable to open camera\n");
219 | return 0;
220 | }
221 | for(;;)
222 | {
223 | cap >> input;
224 | resize(input, input, Size(width, height));
225 | cvtColor(input, input_rgb, COLOR_BGR2RGB);
226 | if(waitKey(30) >= 0) break;
227 | vx_rectangle_t cv_rgb_image_region;
228 | cv_rgb_image_region.start_x = 0;
229 | cv_rgb_image_region.start_y = 0;
230 | cv_rgb_image_region.end_x = width;
231 | cv_rgb_image_region.end_y = height;
232 | vx_imagepatch_addressing_t cv_rgb_image_layout{};
233 | cv_rgb_image_layout.dim_x = input_rgb.cols;
234 | cv_rgb_image_layout.dim_y = input_rgb.rows;
235 | cv_rgb_image_layout.stride_x = input_rgb.elemSize();
236 | cv_rgb_image_layout.stride_y = input_rgb.step;
237 | vx_uint8 * cv_rgb_image_buffer = input_rgb.data;
238 | ERROR_CHECK_STATUS( vxCopyImagePatch( input_rgb_image, &cv_rgb_image_region, 0,
239 | &cv_rgb_image_layout, cv_rgb_image_buffer,
240 | VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST ) );
241 | ERROR_CHECK_STATUS( vxProcessGraph( graph ) );
242 | vx_rectangle_t rect = { 0, 0, (vx_uint32)width, (vx_uint32)height };
243 | vx_map_id map_id;
244 | vx_imagepatch_addressing_t addr;
245 | void * ptr;
246 | ERROR_CHECK_STATUS( vxMapImagePatch( output_pop_image, &rect, 0, &map_id, &addr, &ptr,
247 | VX_READ_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X ) );
248 | Mat mat( height, width, CV_8U, ptr, addr.stride_y );
249 | imshow( "VX POP - LIVE", mat );
250 | if(waitKey(30) >= 0) break;
251 | ERROR_CHECK_STATUS( vxUnmapImagePatch( output_pop_image, map_id ) );
252 | }
253 |
254 | // release objects
255 | ERROR_CHECK_STATUS(vxReleaseGraph( &graph ) );
256 | ERROR_CHECK_STATUS(vxReleaseThreshold( &hyst ));
257 | ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh95 ));
258 | ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh40 ));
259 | ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh20 ));
260 | ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh15 ));
261 | ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh0 ));
262 | ERROR_CHECK_STATUS(vxReleaseImage( &yuv_image ) );
263 | ERROR_CHECK_STATUS(vxReleaseImage( &luma_image ) );
264 | ERROR_CHECK_STATUS(vxReleaseImage( &output_canny_image ) );
265 | ERROR_CHECK_STATUS(vxReleaseImage( &input_rgb_image ) );
266 | ERROR_CHECK_STATUS(vxReleaseImage( &R_image ));
267 | ERROR_CHECK_STATUS(vxReleaseImage( &G_image ));
268 | ERROR_CHECK_STATUS(vxReleaseImage( &B_image ));
269 | ERROR_CHECK_STATUS(vxReleaseImage( &RmG_image ));
270 | ERROR_CHECK_STATUS(vxReleaseImage( &RmB_image ));
271 | ERROR_CHECK_STATUS(vxReleaseImage( &R95_image ));
272 | ERROR_CHECK_STATUS(vxReleaseImage( &G40_image ));
273 | ERROR_CHECK_STATUS(vxReleaseImage( &B20_image ));
274 | ERROR_CHECK_STATUS(vxReleaseImage( &RmG15_image ));
275 | ERROR_CHECK_STATUS(vxReleaseImage( &RmB0_image ));
276 | ERROR_CHECK_STATUS(vxReleaseImage( &and1_image ));
277 | ERROR_CHECK_STATUS(vxReleaseImage( &and2_image ));
278 | ERROR_CHECK_STATUS(vxReleaseImage( &and3_image ));
279 | ERROR_CHECK_STATUS(vxReleaseImage( &output_skinTone_image ));
280 | ERROR_CHECK_STATUS(vxReleaseImage( &output_canny_skinTone_image ));
281 | ERROR_CHECK_STATUS(vxReleaseImage( &output_pop_image ) );
282 | ERROR_CHECK_STATUS(vxReleaseContext( &context ) );
283 | return 0;
284 | }
285 |
--------------------------------------------------------------------------------
/bubble-pop/source/internal_dataTranslator.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 |
24 | #include"internal_opencvTunnel.h"
25 |
26 | /************************************************************************************************************
27 | Converting CV Pyramid into an OpenVX Pyramid
28 | *************************************************************************************************************/
29 | int CV_to_VX_Pyramid(vx_pyramid pyramid_vx, vector pyramid_cv)
30 | {
31 | vx_status status = VX_SUCCESS;
32 | vx_size Level_vx = 0; vx_uint32 width = 0; vx_uint32 height = 0; vx_int32 i;
33 |
34 | STATUS_ERROR_CHECK(vxQueryPyramid(pyramid_vx, VX_PYRAMID_ATTRIBUTE_LEVELS, &Level_vx, sizeof(Level_vx)));
35 | for (i = 0; i < (int)Level_vx; i++)
36 | {
37 | vx_image this_level = vxGetPyramidLevel(pyramid_vx, i);
38 | STATUS_ERROR_CHECK(vxQueryImage(this_level, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
39 | STATUS_ERROR_CHECK(vxQueryImage(this_level, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
40 | if (width != pyramid_cv[i].cols && height != pyramid_cv[i].rows)
41 | {
42 | vxAddLogEntry((vx_reference)pyramid_vx, VX_ERROR_INVALID_DIMENSION, "CV_to_VX_Pyramid ERROR: Pyramid Image Mismatch\n"); return VX_ERROR_INVALID_DIMENSION;
43 | }
44 | Mat* pyr_level;
45 | pyr_level = &pyramid_cv[i];
46 | CV_to_VX_Image(this_level, pyr_level);
47 | }
48 | return 0;
49 | }
50 |
51 | /************************************************************************************************************
52 | Converting VX matrix into an OpenCV Mat
53 | *************************************************************************************************************/
54 | int VX_to_CV_MATRIX(Mat** mat, vx_matrix matrix_vx)
55 | {
56 | vx_status status = VX_SUCCESS;
57 | vx_size numRows = 0; vx_size numCols = 0; vx_enum type; int Type_CV = 0;
58 |
59 | STATUS_ERROR_CHECK(vxQueryMatrix(matrix_vx, VX_MATRIX_ATTRIBUTE_ROWS, &numRows, sizeof(numRows)));
60 | STATUS_ERROR_CHECK(vxQueryMatrix(matrix_vx, VX_MATRIX_ATTRIBUTE_COLUMNS, &numCols, sizeof(numCols)));
61 | STATUS_ERROR_CHECK(vxQueryMatrix(matrix_vx, VX_MATRIX_ATTRIBUTE_TYPE, &type, sizeof(type)));
62 |
63 | if (type == VX_TYPE_INT32)Type_CV = CV_32S;
64 | if (type == VX_TYPE_FLOAT32)Type_CV = CV_32F;
65 |
66 | if (type != VX_TYPE_FLOAT32 && type != VX_TYPE_INT32)
67 | {
68 | vxAddLogEntry((vx_reference)matrix_vx, VX_ERROR_INVALID_FORMAT, "VX_to_CV_MATRIX ERROR: Matrix type not Supported in this RELEASE\n"); return VX_ERROR_INVALID_FORMAT;
69 | }
70 |
71 | Mat * m_cv; m_cv = new Mat((int)numRows, (int)numCols, Type_CV); vx_size mat_size = numRows * numCols;
72 | float *dyn_matrix = new float[mat_size]; int z = 0;
73 |
74 | STATUS_ERROR_CHECK(vxReadMatrix(matrix_vx, (void *)dyn_matrix));
75 | for (int i = 0; i < (int)numRows; i++)
76 | for (int j = 0; j < (int)numCols; j++)
77 | {
78 | m_cv->at(i, j) = dyn_matrix[z]; z++;
79 | }
80 |
81 | *mat = m_cv;
82 | return status;
83 | }
84 |
85 | /************************************************************************************************************
86 | Converting VX Image into an OpenCV Mat
87 | *************************************************************************************************************/
88 | int VX_to_CV_Image(Mat** mat, vx_image image)
89 | {
90 | vx_status status = VX_SUCCESS;
91 | vx_uint32 width = 0; vx_uint32 height = 0; vx_df_image format = VX_DF_IMAGE_VIRT; int CV_format = 0; vx_size planes = 0;
92 |
93 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
94 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
95 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
96 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_PLANES, &planes, sizeof(planes)));
97 |
98 | if (format == VX_DF_IMAGE_U8)CV_format = CV_8U;
99 | if (format == VX_DF_IMAGE_S16)CV_format = CV_16S;
100 | if (format == VX_DF_IMAGE_RGB)CV_format = CV_8UC3;
101 |
102 | if (format != VX_DF_IMAGE_U8 && format != VX_DF_IMAGE_S16 && format != VX_DF_IMAGE_RGB)
103 | {
104 | vxAddLogEntry((vx_reference)image, VX_ERROR_INVALID_FORMAT, "VX_to_CV_Image ERROR: Image type not Supported in this RELEASE\n"); return VX_ERROR_INVALID_FORMAT;
105 | }
106 |
107 | Mat * m_cv; m_cv = new Mat(height, width, CV_format); Mat *pMat = (Mat *)m_cv;
108 | vx_rectangle_t rect; rect.start_x = 0; rect.start_y = 0; rect.end_x = width; rect.end_y = height;
109 |
110 | vx_uint8 *src[4] = { NULL, NULL, NULL, NULL }; vx_uint32 p; void *ptr = NULL;
111 | vx_imagepatch_addressing_t addr[4] = { 0, 0, 0, 0 }; vx_uint32 y = 0u;
112 |
113 | for (p = 0u; (p < (int)planes); p++)
114 | {
115 | STATUS_ERROR_CHECK(vxAccessImagePatch(image, &rect, p, &addr[p], (void **)&src[p], VX_READ_ONLY));
116 | size_t len = addr[p].stride_x * (addr[p].dim_x * addr[p].scale_x) / VX_SCALE_UNITY;
117 | for (y = 0; y < height; y += addr[p].step_y)
118 | {
119 | ptr = vxFormatImagePatchAddress2d(src[p], 0, y - rect.start_y, &addr[p]);
120 | memcpy(pMat->data + y * pMat->step, ptr, len);
121 | }
122 | }
123 |
124 | for (p = 0u; p < (int)planes; p++)
125 | STATUS_ERROR_CHECK(vxCommitImagePatch(image, &rect, p, &addr[p], src[p]));
126 |
127 | *mat = pMat;
128 |
129 | return status;
130 | }
131 |
132 | /************************************************************************************************************
133 | Converting CV Image into an OpenVX Image
134 | *************************************************************************************************************/
135 | int CV_to_VX_Image(vx_image image, Mat* mat)
136 | {
137 | vx_status status = VX_SUCCESS; vx_uint32 width = 0; vx_uint32 height = 0; vx_size planes = 0;
138 |
139 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
140 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
141 | STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_PLANES, &planes, sizeof(planes)));
142 |
143 | Mat *pMat = mat; vx_rectangle_t rect; rect.start_x = 0; rect.start_y = 0; rect.end_x = width; rect.end_y = height;
144 |
145 | vx_uint8 *src[4] = { NULL, NULL, NULL, NULL }; vx_uint32 p; void *ptr = NULL;
146 | vx_imagepatch_addressing_t addr[4] = { 0, 0, 0, 0 }; vx_uint32 y = 0u;
147 |
148 | for (p = 0u; (p <(int)planes); p++)
149 | {
150 | STATUS_ERROR_CHECK(vxAccessImagePatch(image, &rect, p, &addr[p], (void **)&src[p], VX_READ_ONLY));
151 | size_t len = addr[p].stride_x * (addr[p].dim_x * addr[p].scale_x) / VX_SCALE_UNITY;
152 | for (y = 0; y < height; y += addr[p].step_y)
153 | {
154 | ptr = vxFormatImagePatchAddress2d(src[p], 0, y - rect.start_y, &addr[p]);
155 | memcpy(ptr, pMat->data + y * pMat->step, len);
156 | }
157 | }
158 |
159 | for (p = 0u; p < (int)planes; p++)
160 | STATUS_ERROR_CHECK(vxCommitImagePatch(image, &rect, p, &addr[p], src[p]));
161 |
162 | return status;
163 | }
164 |
165 | /************************************************************************************************************
166 | sort function.
167 | *************************************************************************************************************/
168 | bool sortbysize_CV(const KeyPoint &lhs, const KeyPoint &rhs)
169 | {
170 | return lhs.size < rhs.size;
171 | }
172 |
173 | /************************************************************************************************************
174 | OpenCV Keypoints to OpenVX Keypoints
175 | *************************************************************************************************************/
176 | int CV_to_VX_keypoints(vector key_points, vx_array array)
177 | {
178 |
179 | vx_status status = VX_SUCCESS;
180 | vector Keypoint_VX;
181 |
182 | float X, Y, K_Size, K_Angle, K_Response; int x, y, j = 0;
183 | void *ptr = NULL; vx_size size = 0;
184 |
185 | STATUS_ERROR_CHECK(vxQueryArray(array, VX_ARRAY_ATTRIBUTE_CAPACITY, &size, sizeof(size)));
186 |
187 | size_t S = key_points.size(); Keypoint_VX.resize(S);
188 | sort(key_points.begin(), key_points.end(), sortbysize_CV);
189 | vx_size stride = 0; void *base = NULL; vx_size L = 0;
190 |
191 | for (vector::const_iterator i = key_points.begin(); i != key_points.end(); ++i)
192 | {
193 | X = key_points[j].pt.x; Y = key_points[j].pt.y;
194 | K_Size = key_points[j].size; K_Angle = key_points[j].angle; K_Response = key_points[j].response;
195 |
196 | if (fmod(X, 1) >= 0.5)x = (int)ceil(X); else x = (int)floor(X);
197 | if (fmod(Y, 1) >= 0.5)y = (int)ceil(Y); else y = (int)floor(Y);
198 |
199 | Keypoint_VX[j].x = x; Keypoint_VX[j].y = y;
200 | Keypoint_VX[j].strength = K_Size; Keypoint_VX[j].orientation = K_Angle; Keypoint_VX[j].scale = K_Response;
201 | Keypoint_VX[j].tracking_status = 1; Keypoint_VX[j].error = 0;
202 | j++;
203 | }
204 |
205 | vx_keypoint_t * keypoint_ptr = &Keypoint_VX[0]; size = min(size, S);
206 |
207 | status = vxTruncateArray(array, 0);
208 | if (status){ vxAddLogEntry((vx_reference)array, status, "CV_to_VX_keypoints ERROR: vxTruncateArray failed\n"); return status; }
209 |
210 | status = vxAddArrayItems(array, size, keypoint_ptr, sizeof(vx_keypoint_t));
211 | if (status){ vxAddLogEntry((vx_reference)array, status, "CV_to_VX_keypoints ERROR: vxAddArrayItems failed\n"); return status; }
212 |
213 | return status;
214 | }
215 |
216 | /************************************************************************************************************
217 | OpenCV Points to OpenVX Keypoints
218 | *************************************************************************************************************/
219 | int CVPoints2f_to_VX_keypoints(vector key_points, vx_array array)
220 | {
221 | vx_status status = VX_SUCCESS;
222 | vector Keypoint_VX; float X, Y; int x, y, j = 0;
223 | void *ptr = NULL; vx_size size = 0;
224 |
225 | STATUS_ERROR_CHECK(vxQueryArray(array, VX_ARRAY_ATTRIBUTE_CAPACITY, &size, sizeof(size)));
226 |
227 | size_t S = key_points.size(); Keypoint_VX.resize(S);
228 |
229 | for (int i = 0; i < (int)key_points.size(); ++i)
230 | {
231 | X = key_points[j].x; Y = key_points[j].y;
232 |
233 | if (fmod(X, 1) >= 0.5)x = (int)ceil(X); else x = (int)floor(X);
234 | if (fmod(Y, 1) >= 0.5)y = (int)ceil(Y); else y = (int)floor(Y);
235 |
236 | Keypoint_VX[j].x = x; Keypoint_VX[j].y = y;
237 | Keypoint_VX[j].strength = 0; Keypoint_VX[j].orientation = 0; Keypoint_VX[j].scale = 0;
238 | Keypoint_VX[j].tracking_status = 0; Keypoint_VX[j].error = 0;
239 |
240 | j++;
241 | }
242 |
243 | vx_keypoint_t * keypoint_ptr = &Keypoint_VX[0]; size = min(size, S);
244 |
245 | status = vxTruncateArray(array, 0);
246 | if (status){ vxAddLogEntry((vx_reference)array, status, "CVPoints2f_to_VX_keypoints ERROR: vxTruncateArray failed\n"); return status; }
247 |
248 | status = vxAddArrayItems(array, size, keypoint_ptr, sizeof(vx_keypoint_t));
249 | if (status){ vxAddLogEntry((vx_reference)array, status, "CVPoints2f_to_VX_keypoints ERROR: vxAddArrayItems failed\n"); return status; }
250 |
251 | return status;
252 |
253 | }
254 |
255 | /************************************************************************************************************
256 | OpenCV Descriptors to OpenVX Descriptors
257 | *************************************************************************************************************/
258 | int CV_DESP_to_VX_DESP(Mat mat, vx_array array, int stride)
259 | {
260 | vx_status status = VX_SUCCESS; vx_size size = 0;
261 |
262 | STATUS_ERROR_CHECK(vxQueryArray(array, VX_ARRAY_ATTRIBUTE_CAPACITY, &size, sizeof(size)));
263 |
264 | uchar *p = mat.data;
265 |
266 | status = vxTruncateArray(array, 0);
267 | if (status){ vxAddLogEntry((vx_reference)array, status, "CV_DESP_to_VX_DESP ERROR: vxTruncateArray failed\n"); return status; }
268 |
269 | status = vxAddArrayItems(array, size, p, stride);
270 | if (status){ vxAddLogEntry((vx_reference)array, status, "CV_DESP_to_VX_DESP ERROR: vxAddArrayItems failed\n"); return status; }
271 |
272 | return status;
273 | }
274 |
275 | /************************************************************************************************************
276 | Match VX in and out image size
277 | *************************************************************************************************************/
278 | int match_vx_image_parameters(vx_image image1, vx_image image2)
279 | {
280 | vx_status status = VX_SUCCESS;
281 | vx_uint32 W1 = 0; vx_uint32 H1 = 0;
282 | STATUS_ERROR_CHECK(vxQueryImage(image1, VX_IMAGE_ATTRIBUTE_WIDTH, &W1, sizeof(W1)));
283 | STATUS_ERROR_CHECK(vxQueryImage(image1, VX_IMAGE_ATTRIBUTE_HEIGHT, &H1, sizeof(H1)));
284 |
285 | vx_uint32 W2 = 0; vx_uint32 H2 = 0;
286 | STATUS_ERROR_CHECK(vxQueryImage(image2, VX_IMAGE_ATTRIBUTE_WIDTH, &W2, sizeof(W2)));
287 | STATUS_ERROR_CHECK(vxQueryImage(image2, VX_IMAGE_ATTRIBUTE_HEIGHT, &H2, sizeof(H2)));
288 |
289 | //Input and Output image size match check
290 | if (W1 != W2 || H1 != H2)
291 | {
292 | status = VX_ERROR_INVALID_DIMENSION;
293 | vxAddLogEntry((vx_reference)image1, status, "match_vx_image_parameters ERROR: Image1 Height or Width Not Equal to Image2\n");
294 | return status;
295 | }
296 |
297 | return status;
298 | }
299 |
--------------------------------------------------------------------------------
/bubble-pop/source/internal_publishKernels.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include"internal_publishKernels.h"
24 | #include"vx_ext_pop.h"
25 |
26 | /**********************************************************************
27 | PUBLIC FUNCTION for VX POP user defined functions
28 | **********************************************************************/
29 | extern "C" SHARED_PUBLIC vx_status VX_API_CALL vxPublishKernels(vx_context context)
30 | {
31 | vx_status status = VX_SUCCESS;
32 | printf("vxPublishKernels\n");
33 |
34 | STATUS_ERROR_CHECK(get_kernels_to_publish());
35 | STATUS_ERROR_CHECK(Kernel_List->PUBLISH(context));
36 |
37 | return status;
38 | }
39 |
40 | /************************************************************************************************************
41 | Add All Kernels to the Kernel List
42 | *************************************************************************************************************/
43 | vx_status get_kernels_to_publish()
44 | {
45 | vx_status status = VX_SUCCESS;
46 |
47 | Kernel_List = new Kernellist(MAX_KERNELS);
48 |
49 | STATUS_ERROR_CHECK(ADD_KERENEL(VX_bubbles_pop_Register));
50 | STATUS_ERROR_CHECK(ADD_KERENEL(VX_donut_pop_Register));
51 | return status;
52 | }
53 |
54 | /************************************************************************************************************
55 | Add Kernels to the Kernel List
56 | *************************************************************************************************************/
57 | vx_status ADD_KERENEL(std::function func)
58 | {
59 | vx_status status = VX_SUCCESS;
60 | STATUS_ERROR_CHECK(Kernel_List->ADD(func));
61 | return status;
62 | }
--------------------------------------------------------------------------------
/bubble-pop/source/internal_vxNodes.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 | */
22 |
23 | #include"internal_publishKernels.h"
24 | #include"vx_ext_pop.h"
25 |
26 | vx_node vxCreateNodeByStructure(vx_graph graph,
27 | vx_enum kernelenum,
28 | vx_reference params[],
29 | vx_uint32 num)
30 | {
31 | vx_status status = VX_SUCCESS;
32 | vx_node node = 0;
33 | vx_context context = vxGetContext((vx_reference)graph);
34 | vx_kernel kernel = vxGetKernelByEnum(context, kernelenum);
35 | if (kernel)
36 | {
37 | node = vxCreateGenericNode(graph, kernel);
38 | if (node)
39 | {
40 | vx_uint32 p = 0;
41 | for (p = 0; p < num; p++)
42 | {
43 | if (params[p])
44 | {
45 | status = vxSetParameterByIndex(node,
46 | p,
47 | params[p]);
48 | if (status != VX_SUCCESS)
49 | {
50 | vxAddLogEntry((vx_reference)graph, status, "Kernel %d Parameter %u is invalid.\n", kernelenum, p);
51 | vxReleaseNode(&node);
52 | node = 0;
53 | break;
54 | }
55 | }
56 | }
57 | }
58 | else
59 | {
60 | vxAddLogEntry((vx_reference)graph, VX_ERROR_INVALID_PARAMETERS, "Failed to create node with kernel enum %d\n", kernelenum);
61 | status = VX_ERROR_NO_MEMORY;
62 | }
63 | vxReleaseKernel(&kernel);
64 | }
65 | else
66 | {
67 | vxAddLogEntry((vx_reference)graph, VX_ERROR_INVALID_PARAMETERS, "failed to retrieve kernel enum %d\n", kernelenum);
68 | status = VX_ERROR_NOT_SUPPORTED;
69 | }
70 | return node;
71 | }
72 |
73 | /*******************************************************************************************************************
74 | Bubble Pop C Function
75 | *******************************************************************************************************************/
76 | extern "C" SHARED_PUBLIC vx_node VX_API_CALL vxExtPopNode_bubblePop(vx_graph graph, vx_image input, vx_image output)
77 | {
78 |
79 | vx_reference params[] = {
80 | (vx_reference)input,
81 | (vx_reference)output,
82 | };
83 |
84 | return vxCreateNodeByStructure(graph,
85 | VX_KERNEL_EXT_POP_BUBBLE_POP,
86 | params,
87 | dimof(params));
88 | }
89 |
90 | /*******************************************************************************************************************
91 | Donut Pop C Function
92 | *******************************************************************************************************************/
93 | extern "C" SHARED_PUBLIC vx_node VX_API_CALL vxExtPopNode_donutPop(vx_graph graph, vx_image input, vx_image output)
94 | {
95 |
96 | vx_reference params[] = {
97 | (vx_reference)input,
98 | (vx_reference)output,
99 | };
100 |
101 | return vxCreateNodeByStructure(graph,
102 | VX_KERNEL_EXT_POP_DONUT_POP,
103 | params,
104 | dimof(params));
105 | }
--------------------------------------------------------------------------------
/canny-edge-detector/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | #
3 | # MIT License
4 | #
5 | # Copyright (c) 2020 Advanced Micro Devices, Inc.
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 | #
25 | ###############################################################################
26 |
27 | cmake_minimum_required (VERSION 2.8)
28 |
29 | project(cannyEdgeDetector)
30 |
31 | set(CMAKE_CXX_STANDARD 11)
32 |
33 | find_package(OpenCV REQUIRED)
34 |
35 | if(DEFINED OPENVX_INCLUDES)
36 | message(STATUS "OPENVX_INCLUDES: \t${OPENVX_INCLUDES}")
37 | include_directories(${OPENVX_INCLUDES})
38 | else()
39 | message(STATUS "OPENVX_INCLUDES: \t")
40 | endif()
41 |
42 | if(DEFINED OPENVX_LIBRARIES)
43 | message(STATUS "OPENVX_LIBRARIES: \t${OPENVX_LIBRARIES}")
44 | else()
45 | message(STATUS "OPENVX_LIBRARIES: \t")
46 | endif()
47 |
48 | add_executable(${PROJECT_NAME} src/canny.cpp)
49 | target_link_libraries(${PROJECT_NAME} ${OPENVX_LIBRARIES} ${OpenCV_LIBRARIES})
50 | install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
51 |
--------------------------------------------------------------------------------
/canny-edge-detector/src/canny.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "opencv2/opencv.hpp"
4 | #include
5 |
6 | using namespace cv;
7 | using namespace std;
8 |
9 | #define ERROR_CHECK_STATUS( status ) { \
10 | vx_status status_ = (status); \
11 | if(status_ != VX_SUCCESS) { \
12 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
13 | exit(1); \
14 | } \
15 | }
16 |
17 | #define ERROR_CHECK_OBJECT( obj ) { \
18 | vx_status status_ = vxGetStatus((vx_reference)(obj)); \
19 | if(status_ != VX_SUCCESS) { \
20 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
21 | exit(1); \
22 | } \
23 | }
24 |
25 | static void VX_CALLBACK log_callback(vx_context context, vx_reference ref, vx_status status, const vx_char string[])
26 | {
27 | size_t len = strlen(string);
28 | if (len > 0) {
29 | printf("%s", string);
30 | if (string[len - 1] != '\n')
31 | printf("\n");
32 | fflush(stdout);
33 | }
34 | }
35 |
36 | int main(int argc, char **argv)
37 | {
38 | if (argc < 2) {
39 | printf("Usage:\n"
40 | "./cannyDetect --image \n"
41 | "./cannyDetect --live \n");
42 | return 0;
43 | }
44 |
45 | int width = 480, height = 360;
46 |
47 | vx_context context = vxCreateContext();
48 | ERROR_CHECK_OBJECT(context);
49 | vxRegisterLogCallback(context, log_callback, vx_false_e);
50 |
51 | vx_graph graph = vxCreateGraph(context);
52 | ERROR_CHECK_OBJECT(graph);
53 |
54 | vx_image input_rgb_image = vxCreateImage(context, width, height, VX_DF_IMAGE_RGB);
55 | vx_image output_filtered_image = vxCreateImage(context, width, height, VX_DF_IMAGE_U8);
56 | ERROR_CHECK_OBJECT(input_rgb_image);
57 | ERROR_CHECK_OBJECT(output_filtered_image);
58 |
59 | vx_image yuv_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_IYUV);
60 | vx_image luma_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
61 | ERROR_CHECK_OBJECT(yuv_image);
62 | ERROR_CHECK_OBJECT(luma_image);
63 |
64 | vx_threshold hyst = vxCreateThreshold(context, VX_THRESHOLD_TYPE_RANGE, VX_TYPE_UINT8);
65 | vx_int32 lower = 80, upper = 100;
66 | vxSetThresholdAttribute(hyst, VX_THRESHOLD_ATTRIBUTE_THRESHOLD_LOWER, &lower, sizeof(lower));
67 | vxSetThresholdAttribute(hyst, VX_THRESHOLD_ATTRIBUTE_THRESHOLD_UPPER, &upper, sizeof(upper));
68 | ERROR_CHECK_OBJECT(hyst);
69 | vx_int32 gradient_size = 3;
70 |
71 | vx_node nodes[] =
72 | {
73 | vxColorConvertNode(graph, input_rgb_image, yuv_image),
74 | vxChannelExtractNode(graph, yuv_image, VX_CHANNEL_Y, luma_image),
75 | vxCannyEdgeDetectorNode(graph, luma_image, hyst, gradient_size, VX_NORM_L1, output_filtered_image)
76 | };
77 |
78 | for( vx_size i = 0; i < sizeof( nodes ) / sizeof( nodes[0] ); i++ )
79 | {
80 | ERROR_CHECK_OBJECT( nodes[i] );
81 | ERROR_CHECK_STATUS( vxReleaseNode( &nodes[i] ) );
82 | }
83 |
84 | ERROR_CHECK_STATUS( vxVerifyGraph( graph ) );
85 |
86 | string option = argv[1];
87 | Mat input;
88 |
89 | if (option == "--image")
90 | {
91 | string imageLocation = argv[2];
92 | input = imread(imageLocation.c_str());
93 | if (input.empty()) {
94 | printf("Image not found\n");
95 | return 0;
96 | }
97 | resize(input, input, Size(width, height));
98 | imshow("inputWindow", input);
99 | vx_rectangle_t cv_rgb_image_region;
100 | cv_rgb_image_region.start_x = 0;
101 | cv_rgb_image_region.start_y = 0;
102 | cv_rgb_image_region.end_x = width;
103 | cv_rgb_image_region.end_y = height;
104 | vx_imagepatch_addressing_t cv_rgb_image_layout{};
105 | cv_rgb_image_layout.dim_x = input.cols;
106 | cv_rgb_image_layout.dim_y = input.rows;
107 | cv_rgb_image_layout.stride_x = input.elemSize();
108 | cv_rgb_image_layout.stride_y = input.step;
109 | vx_uint8 * cv_rgb_image_buffer = input.data;
110 | ERROR_CHECK_STATUS( vxCopyImagePatch( input_rgb_image, &cv_rgb_image_region, 0,
111 | &cv_rgb_image_layout, cv_rgb_image_buffer,
112 | VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST ) );
113 | ERROR_CHECK_STATUS( vxProcessGraph( graph ) );
114 | vx_rectangle_t rect = { 0, 0, (vx_uint32)width, (vx_uint32)height };
115 | vx_map_id map_id;
116 | vx_imagepatch_addressing_t addr;
117 | void * ptr;
118 | ERROR_CHECK_STATUS( vxMapImagePatch( output_filtered_image, &rect, 0, &map_id, &addr, &ptr,
119 | VX_READ_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X ) );
120 | Mat mat( height, width, CV_8U, ptr, addr.stride_y );
121 | imshow( "CannyDetect", mat );
122 | waitKey(0);
123 | ERROR_CHECK_STATUS( vxUnmapImagePatch( output_filtered_image, map_id ) );
124 | }
125 | else if (option == "--live")
126 | {
127 | VideoCapture cap(0);
128 | if (!cap.isOpened()) {
129 | printf("Unable to open camera\n");
130 | return 0;
131 | }
132 | for(;;) {
133 | cap >> input;
134 | resize(input, input, Size(width, height));
135 | imshow("inputWindow", input);
136 | if(waitKey(30) >= 0) break;
137 | vx_rectangle_t cv_rgb_image_region;
138 | cv_rgb_image_region.start_x = 0;
139 | cv_rgb_image_region.start_y = 0;
140 | cv_rgb_image_region.end_x = width;
141 | cv_rgb_image_region.end_y = height;
142 | vx_imagepatch_addressing_t cv_rgb_image_layout;
143 | cv_rgb_image_layout.stride_x = 3;
144 | cv_rgb_image_layout.stride_y = input.step;
145 | vx_uint8 * cv_rgb_image_buffer = input.data;
146 | ERROR_CHECK_STATUS( vxCopyImagePatch( input_rgb_image, &cv_rgb_image_region, 0,
147 | &cv_rgb_image_layout, cv_rgb_image_buffer,
148 | VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST ) );
149 | ERROR_CHECK_STATUS( vxProcessGraph( graph ) );
150 | vx_rectangle_t rect = { 0, 0, (vx_uint32)width, (vx_uint32)height };
151 | vx_map_id map_id;
152 | vx_imagepatch_addressing_t addr;
153 | void * ptr;
154 | ERROR_CHECK_STATUS( vxMapImagePatch( output_filtered_image, &rect, 0, &map_id, &addr, &ptr,
155 | VX_READ_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X ) );
156 | Mat mat( height, width, CV_8U, ptr, addr.stride_y );
157 | imshow( "CannyDetect", mat );
158 | if(waitKey(30) >= 0) break;
159 | ERROR_CHECK_STATUS( vxUnmapImagePatch( output_filtered_image, map_id ) );
160 | }
161 | }
162 | else {
163 | printf("Usage:\n"
164 | "./cannyDetect --image \n"
165 | "./cannyDetect --live \n");
166 | return 0;
167 | }
168 |
169 | ERROR_CHECK_STATUS( vxReleaseGraph( &graph ) );
170 | ERROR_CHECK_STATUS( vxReleaseImage( &yuv_image ) );
171 | ERROR_CHECK_STATUS( vxReleaseImage( &luma_image ) );
172 | ERROR_CHECK_STATUS( vxReleaseImage( &input_rgb_image ) );
173 | ERROR_CHECK_STATUS( vxReleaseImage( &output_filtered_image ) );
174 | ERROR_CHECK_STATUS( vxReleaseContext( &context ) );
175 | return 0;
176 | }
177 |
--------------------------------------------------------------------------------
/images/canny-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KhronosGroup/openvx-samples/458c983626ed2d574ccd1058a203f999e132131e/images/canny-app.png
--------------------------------------------------------------------------------
/images/canny_image.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KhronosGroup/openvx-samples/458c983626ed2d574ccd1058a203f999e132131e/images/canny_image.PNG
--------------------------------------------------------------------------------
/images/face.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KhronosGroup/openvx-samples/458c983626ed2d574ccd1058a203f999e132131e/images/face.png
--------------------------------------------------------------------------------
/images/skintone-detect-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KhronosGroup/openvx-samples/458c983626ed2d574ccd1058a203f999e132131e/images/skintone-detect-app.png
--------------------------------------------------------------------------------
/images/vx-pop-app.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/KhronosGroup/openvx-samples/458c983626ed2d574ccd1058a203f999e132131e/images/vx-pop-app.gif
--------------------------------------------------------------------------------
/skin-tone-detector/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | #
3 | # MIT License
4 | #
5 | # Copyright (c) 2020 Advanced Micro Devices, Inc.
6 | #
7 | # Permission is hereby granted, free of charge, to any person obtaining a copy
8 | # of this software and associated documentation files (the "Software"), to deal
9 | # in the Software without restriction, including without limitation the rights
10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | # copies of the Software, and to permit persons to whom the Software is
12 | # furnished to do so, subject to the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be included in all
15 | # copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | # SOFTWARE.
24 | #
25 | ###############################################################################
26 |
27 | cmake_minimum_required (VERSION 2.8)
28 |
29 | project(skinToneDetector)
30 |
31 | set(CMAKE_CXX_STANDARD 11)
32 |
33 | find_package(OpenCV REQUIRED)
34 |
35 | if(DEFINED OPENVX_INCLUDES)
36 | message(STATUS "OPENVX_INCLUDES: \t${OPENVX_INCLUDES}")
37 | include_directories(${OPENVX_INCLUDES})
38 | else()
39 | message(STATUS "OPENVX_INCLUDES: \t")
40 | endif()
41 |
42 | if(DEFINED OPENVX_LIBRARIES)
43 | message(STATUS "OPENVX_LIBRARIES: \t${OPENVX_LIBRARIES}")
44 | else()
45 | message(STATUS "OPENVX_LIBRARIES: \t")
46 | endif()
47 |
48 | add_executable(${PROJECT_NAME} src/skinToneDetector.cpp)
49 | target_link_libraries(${PROJECT_NAME} ${OPENVX_LIBRARIES} ${OpenCV_LIBRARIES})
50 | install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
51 |
--------------------------------------------------------------------------------
/skin-tone-detector/src/skinToneDetector.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "opencv2/opencv.hpp"
4 | #include
5 |
6 | using namespace cv;
7 | using namespace std;
8 |
9 | #define ERROR_CHECK_STATUS( status ) { \
10 | vx_status status_ = (status); \
11 | if(status_ != VX_SUCCESS) { \
12 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
13 | exit(1); \
14 | } \
15 | }
16 |
17 | #define ERROR_CHECK_OBJECT( obj ) { \
18 | vx_status status_ = vxGetStatus((vx_reference)(obj)); \
19 | if(status_ != VX_SUCCESS) { \
20 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
21 | exit(1); \
22 | } \
23 | }
24 |
25 | static void VX_CALLBACK log_callback(vx_context context, vx_reference ref, vx_status status, const vx_char string[])
26 | {
27 | size_t len = strlen(string);
28 | if (len > 0) {
29 | printf("%s", string);
30 | if (string[len - 1] != '\n')
31 | printf("\n");
32 | fflush(stdout);
33 | }
34 | }
35 |
36 | int main(int argc, char **argv)
37 | {
38 | if (argc < 2) {
39 | printf("Usage:\n"
40 | "./skinToneDetect --image \n"
41 | "./skinToneDetect --live \n");
42 | return 0;
43 | }
44 | // set image height & width
45 | int width = 720, height = 480;
46 |
47 | // create OpenVX context
48 | vx_context context = vxCreateContext();
49 | ERROR_CHECK_OBJECT(context);
50 | vxRegisterLogCallback(context, log_callback, vx_false_e);
51 |
52 | // create OpenVX Graph using the created context
53 | vx_graph graph = vxCreateGraph(context);
54 | ERROR_CHECK_OBJECT(graph);
55 |
56 | // create input & output images
57 | vx_image input_rgb_image = vxCreateImage(context, width, height, VX_DF_IMAGE_RGB);
58 | vx_image output_skinTone_image = vxCreateImage(context, width, height, VX_DF_IMAGE_U8);
59 | ERROR_CHECK_OBJECT(input_rgb_image);
60 | ERROR_CHECK_OBJECT(output_skinTone_image);
61 |
62 | // create intermediate images which are not accessed by the user to be mem optimized
63 | vx_image R_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
64 | vx_image G_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
65 | vx_image B_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
66 | vx_image RmG_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
67 | vx_image RmB_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
68 | vx_image R95_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
69 | vx_image G40_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
70 | vx_image B20_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
71 | vx_image RmG15_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
72 | vx_image RmB0_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
73 | vx_image and1_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
74 | vx_image and2_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
75 | vx_image and3_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
76 | ERROR_CHECK_OBJECT(R_image);
77 | ERROR_CHECK_OBJECT(G_image);
78 | ERROR_CHECK_OBJECT(B_image);
79 | ERROR_CHECK_OBJECT(RmG_image);
80 | ERROR_CHECK_OBJECT(RmB_image);
81 | ERROR_CHECK_OBJECT(R95_image);
82 | ERROR_CHECK_OBJECT(G40_image);
83 | ERROR_CHECK_OBJECT(B20_image);
84 | ERROR_CHECK_OBJECT(RmG15_image);
85 | ERROR_CHECK_OBJECT(RmB0_image);
86 | ERROR_CHECK_OBJECT(and1_image);
87 | ERROR_CHECK_OBJECT(and2_image);
88 | ERROR_CHECK_OBJECT(and3_image);
89 |
90 | // create threshold values
91 | vx_threshold thresh95 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
92 | vx_int32 thresValue95 = 95;
93 | vxSetThresholdAttribute(thresh95, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue95, sizeof(vx_int32));
94 | ERROR_CHECK_OBJECT(thresh95);
95 | vx_threshold thresh40 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
96 | vx_int32 thresValue40 = 40;
97 | vxSetThresholdAttribute(thresh40, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue40, sizeof(vx_int32));
98 | ERROR_CHECK_OBJECT(thresh40);
99 | vx_threshold thresh20 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
100 | vx_int32 thresValue20 = 20;
101 | vxSetThresholdAttribute(thresh20, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue20, sizeof(vx_int32));
102 | ERROR_CHECK_OBJECT(thresh20);
103 | vx_threshold thresh15 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
104 | vx_int32 thresValue15 = 15;
105 | vxSetThresholdAttribute(thresh15, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue15, sizeof(vx_int32));
106 | ERROR_CHECK_OBJECT(thresh15);
107 | vx_threshold thresh0 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
108 | vx_int32 thresValue0 = 0;
109 | vxSetThresholdAttribute(thresh0, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue0, sizeof(vx_int32));
110 | ERROR_CHECK_OBJECT(thresh0);
111 |
112 | // add nodes to the graph
113 | vx_node nodes[] =
114 | {
115 | // extract R,G,B channels and compute R-G and R-B
116 | vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_R, R_image),
117 | vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_G, G_image),
118 | vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_B, B_image),
119 | vxSubtractNode(graph, R_image, G_image, VX_CONVERT_POLICY_SATURATE, RmG_image),
120 | vxSubtractNode(graph, R_image, B_image, VX_CONVERT_POLICY_SATURATE, RmB_image),
121 | // compute threshold
122 | vxThresholdNode(graph, R_image, thresh95, R95_image),
123 | vxThresholdNode(graph, G_image, thresh40, G40_image),
124 | vxThresholdNode(graph, B_image, thresh20, B20_image),
125 | vxThresholdNode(graph, RmG_image, thresh15, RmG15_image),
126 | vxThresholdNode(graph, RmB_image, thresh0, RmB0_image),
127 | // aggregate all thresholded values to produce SKIN pixels
128 | vxAndNode(graph, R95_image, G40_image, and1_image),
129 | vxAndNode(graph, and1_image, B20_image, and2_image),
130 | vxAndNode(graph, RmG15_image, RmB0_image, and3_image),
131 | vxAndNode(graph, and2_image, and3_image, output_skinTone_image)
132 | };
133 |
134 | for( vx_size i = 0; i < sizeof( nodes ) / sizeof( nodes[0] ); i++ )
135 | {
136 | ERROR_CHECK_OBJECT( nodes[i] );
137 | }
138 |
139 | // verify graph
140 | ERROR_CHECK_STATUS( vxVerifyGraph( graph ) );
141 |
142 | string option = argv[1];
143 | Mat input, input_rgb;
144 | cv::namedWindow("VX SkinTone Detect", cv::WINDOW_GUI_EXPANDED);
145 |
146 | if (option == "--image")
147 | {
148 | string imageLocation = argv[2];
149 | input = imread(imageLocation.c_str());
150 | if (input.empty()) {
151 | printf("Image not found\n");
152 | return -1;
153 | }
154 | resize(input, input, Size(width, height));
155 | cvtColor(input, input_rgb, COLOR_BGR2RGB);
156 | imshow("inputWindow", input);
157 | vx_rectangle_t cv_rgb_image_region;
158 | cv_rgb_image_region.start_x = 0;
159 | cv_rgb_image_region.start_y = 0;
160 | cv_rgb_image_region.end_x = width;
161 | cv_rgb_image_region.end_y = height;
162 | vx_imagepatch_addressing_t cv_rgb_image_layout{};
163 | cv_rgb_image_layout.dim_x = input_rgb.cols;
164 | cv_rgb_image_layout.dim_y = input_rgb.rows;
165 | cv_rgb_image_layout.stride_x = input_rgb.elemSize();
166 | cv_rgb_image_layout.stride_y = input_rgb.step;
167 | vx_uint8 * cv_rgb_image_buffer = input_rgb.data;
168 | ERROR_CHECK_STATUS( vxCopyImagePatch( input_rgb_image, &cv_rgb_image_region, 0,
169 | &cv_rgb_image_layout, cv_rgb_image_buffer,
170 | VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST ) );
171 | ERROR_CHECK_STATUS( vxProcessGraph( graph ) );
172 | vx_rectangle_t rect = { 0, 0, (vx_uint32)width, (vx_uint32)height };
173 | vx_map_id map_id;
174 | vx_imagepatch_addressing_t addr;
175 | void * ptr;
176 | ERROR_CHECK_STATUS( vxMapImagePatch( output_skinTone_image, &rect, 0, &map_id, &addr, &ptr,
177 | VX_READ_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X ) );
178 | Mat mat( height, width, CV_8U, ptr, addr.stride_y );
179 | imshow( "VX SkinTone Detect", mat );
180 | waitKey(0);
181 | ERROR_CHECK_STATUS( vxUnmapImagePatch( output_skinTone_image, map_id ) );
182 | }
183 | else if (option == "--live")
184 | {
185 | VideoCapture cap(0);
186 | if (!cap.isOpened()) {
187 | printf("Unable to open camera\n");
188 | return -1;
189 | }
190 | for(;;) {
191 | cap >> input;
192 | resize(input, input, Size(width, height));
193 | cvtColor(input, input_rgb, COLOR_BGR2RGB);
194 | imshow("inputWindow", input);
195 | if(waitKey(30) >= 0) break;
196 | vx_rectangle_t cv_rgb_image_region;
197 | cv_rgb_image_region.start_x = 0;
198 | cv_rgb_image_region.start_y = 0;
199 | cv_rgb_image_region.end_x = width;
200 | cv_rgb_image_region.end_y = height;
201 | vx_imagepatch_addressing_t cv_rgb_image_layout;
202 | cv_rgb_image_layout.stride_x = 3;
203 | cv_rgb_image_layout.stride_y = input_rgb.step;
204 | vx_uint8 * cv_rgb_image_buffer = input_rgb.data;
205 | ERROR_CHECK_STATUS( vxCopyImagePatch( input_rgb_image, &cv_rgb_image_region, 0,
206 | &cv_rgb_image_layout, cv_rgb_image_buffer,
207 | VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST ) );
208 | ERROR_CHECK_STATUS( vxProcessGraph( graph ) );
209 | vx_rectangle_t rect = { 0, 0, (vx_uint32)width, (vx_uint32)height };
210 | vx_map_id map_id;
211 | vx_imagepatch_addressing_t addr;
212 | void * ptr;
213 | ERROR_CHECK_STATUS( vxMapImagePatch( output_skinTone_image, &rect, 0, &map_id, &addr, &ptr,
214 | VX_READ_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X ) );
215 | Mat mat( height, width, CV_8U, ptr, addr.stride_y );
216 | imshow( "VX SkinTone Detect", mat );
217 | if(waitKey(30) >= 0) break;
218 | ERROR_CHECK_STATUS( vxUnmapImagePatch( output_skinTone_image, map_id ) );
219 | }
220 | }
221 | else {
222 | printf("Usage:\n"
223 | "./skinToneDetect --image \n"
224 | "./skinToneDetect --live \n");
225 | return -1;
226 | }
227 |
228 | // release objects
229 | for( vx_size i = 0; i < sizeof( nodes ) / sizeof( nodes[0] ); i++ )
230 | {
231 | ERROR_CHECK_STATUS( vxReleaseNode( &nodes[i] ) );
232 | }
233 | ERROR_CHECK_STATUS(vxReleaseGraph( &graph ));
234 | ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh95 ));
235 | ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh40 ));
236 | ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh20 ));
237 | ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh15 ));
238 | ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh0 ));
239 | ERROR_CHECK_STATUS(vxReleaseImage( &R_image ));
240 | ERROR_CHECK_STATUS(vxReleaseImage( &G_image ));
241 | ERROR_CHECK_STATUS(vxReleaseImage( &B_image ));
242 | ERROR_CHECK_STATUS(vxReleaseImage( &RmG_image ));
243 | ERROR_CHECK_STATUS(vxReleaseImage( &RmB_image ));
244 | ERROR_CHECK_STATUS(vxReleaseImage( &R95_image ));
245 | ERROR_CHECK_STATUS(vxReleaseImage( &G40_image ));
246 | ERROR_CHECK_STATUS(vxReleaseImage( &B20_image ));
247 | ERROR_CHECK_STATUS(vxReleaseImage( &RmG15_image ));
248 | ERROR_CHECK_STATUS(vxReleaseImage( &RmB0_image ));
249 | ERROR_CHECK_STATUS(vxReleaseImage( &and1_image ));
250 | ERROR_CHECK_STATUS(vxReleaseImage( &and2_image ));
251 | ERROR_CHECK_STATUS(vxReleaseImage( &and3_image ));
252 | ERROR_CHECK_STATUS(vxReleaseImage( &input_rgb_image ));
253 | ERROR_CHECK_STATUS(vxReleaseImage( &output_skinTone_image ));
254 | ERROR_CHECK_STATUS(vxReleaseContext( &context ));
255 | return 0;
256 | }
257 |
--------------------------------------------------------------------------------