├── 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 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](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 | --------------------------------------------------------------------------------