├── scripts ├── qt-clean.sh ├── clean-all.sh ├── download-amdovx.sh ├── download-videos.sh └── download-khronos-sample.sh ├── .gitignore ├── LICENSE ├── tutorial_exercises ├── exercise1 │ ├── CMakeLists.txt │ └── exercise1.cpp ├── exercise2 │ ├── CMakeLists.txt │ └── exercise2.cpp ├── exercise3 │ ├── CMakeLists.txt │ └── exercise3.cpp ├── exercise4 │ └── CMakeLists.txt ├── exercise2a │ └── CMakeLists.txt ├── solution_exercise1 │ ├── CMakeLists.txt │ └── solution_exercise1.cpp ├── solution_exercise2 │ ├── CMakeLists.txt │ └── solution_exercise2.cpp ├── solution_exercise2a │ └── CMakeLists.txt ├── solution_exercise3 │ ├── CMakeLists.txt │ └── solution_exercise3.cpp ├── solution_exercise4 │ └── CMakeLists.txt ├── include │ ├── VX │ │ ├── vx.h │ │ ├── vx_vendors.h │ │ └── vx_kernels.h │ └── opencv_camera_display.h └── CMakeLists.txt └── README.md /scripts/qt-clean.sh: -------------------------------------------------------------------------------- 1 | # remove Qt cmake intermediate files; run this script from openvx_tutorial folder 2 | # 3 | \rm -rf build-* tutorial_exercises/CMakeLists.txt.user 4 | -------------------------------------------------------------------------------- /scripts/clean-all.sh: -------------------------------------------------------------------------------- 1 | # remove all downloaded and intermediate files 2 | # 3 | \rm -rf build-* tutorial_exercises/CMakeLists.txt.user tutorial_videos tutorial_exercises/amdovx-core 4 | -------------------------------------------------------------------------------- /scripts/download-amdovx.sh: -------------------------------------------------------------------------------- 1 | # download and extract amdovx-core/openvx into tutorial_exercises folder 2 | # 3 | \rm -rf master.zip tutorial_exercises/amdovx-core 4 | wget https://github.com/GPUOpen-ProfessionalCompute-Libraries/amdovx-core/archive/master.zip 5 | echo creating tutorial_exercises/amdovx-core ... 6 | unzip -q master.zip 7 | mv amdovx-core-master tutorial_exercises/amdovx-core 8 | \rm -rf master.zip 9 | -------------------------------------------------------------------------------- /scripts/download-videos.sh: -------------------------------------------------------------------------------- 1 | # run this script from openvx_tutorial folder; the current C code requires 2 | # tutorial_videos folder to be under the openvx_tutorial folder to be able 3 | # pick the default video sequence when launching from Qt Creator 4 | # 5 | \rm -rf tutorial_videos 6 | mkdir tutorial_videos 7 | cd tutorial_videos 8 | wget http://ewh.ieee.org/r6/scv/sps/openvx-material/PETS09-S1-L1-View001.avi 9 | cd .. 10 | -------------------------------------------------------------------------------- /scripts/download-khronos-sample.sh: -------------------------------------------------------------------------------- 1 | # download and extract openvx_sample into tutorial_exercises folder 2 | # 3 | \rm -rf openvx_sample_1.0.1.tar.bz2 tutorial_exercises/openvx_sample 4 | wget https://www.khronos.org/registry/vx/sample/openvx_sample_1.0.1.tar.bz2 5 | echo creating tutorial_exercises/openvx_sample ... 6 | bunzip2 -c openvx_sample_1.0.1.tar.bz2 | tar xf - 7 | mv openvx_sample tutorial_exercises/openvx_sample 8 | \rm -rf openvx_sample_1.0.1.tar.bz2 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # Downloaded and build files 31 | tutorial_videos/ 32 | tutorial_exercises/amdovx-core/ 33 | tutorial_exercises/openvx_sample/ 34 | build-*/ 35 | tutorial_exercises/CMakeLists.txt.user 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Radha Giduthuri 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 | -------------------------------------------------------------------------------- /tutorial_exercises/exercise1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # Assumes that there is only one .cpp file with same name as project folder name 24 | 25 | cmake_minimum_required ( VERSION 2.8 ) 26 | get_filename_component ( project_dir ${CMAKE_CURRENT_LIST_DIR} NAME ) 27 | project ( ${project_dir} ) 28 | find_package ( OpenCV REQUIRED ) 29 | include_directories ( ${OpenCV_INCLUDE_DIRS} ) 30 | include_directories ( ${OpenVX_INCLUDE_DIRS} ) 31 | include_directories ( ${CMAKE_SOURCE_DIR}/include ) 32 | link_directories ( ${OpenVX_LIBS_DIR} ) 33 | if( POLICY CMP0054 ) 34 | cmake_policy( SET CMP0054 OLD ) 35 | endif() 36 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 37 | set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT" ) 38 | set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" ) 39 | endif() 40 | add_executable ( ${PROJECT_NAME} ${project_dir}.cpp ) 41 | target_link_libraries ( ${PROJECT_NAME} ${OpenVX_LIBS} ${OpenCV_LIBRARIES} ) 42 | -------------------------------------------------------------------------------- /tutorial_exercises/exercise2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # Assumes that there is only one .cpp file with same name as project folder name 24 | 25 | cmake_minimum_required ( VERSION 2.8 ) 26 | get_filename_component ( project_dir ${CMAKE_CURRENT_LIST_DIR} NAME ) 27 | project ( ${project_dir} ) 28 | find_package ( OpenCV REQUIRED ) 29 | include_directories ( ${OpenCV_INCLUDE_DIRS} ) 30 | include_directories ( ${OpenVX_INCLUDE_DIRS} ) 31 | include_directories ( ${CMAKE_SOURCE_DIR}/include ) 32 | link_directories ( ${OpenVX_LIBS_DIR} ) 33 | if( POLICY CMP0054 ) 34 | cmake_policy( SET CMP0054 OLD ) 35 | endif() 36 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 37 | set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT" ) 38 | set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" ) 39 | endif() 40 | add_executable ( ${PROJECT_NAME} ${project_dir}.cpp ) 41 | target_link_libraries ( ${PROJECT_NAME} ${OpenVX_LIBS} ${OpenCV_LIBRARIES} ) 42 | -------------------------------------------------------------------------------- /tutorial_exercises/exercise3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # Assumes that there is only one .cpp file with same name as project folder name 24 | 25 | cmake_minimum_required ( VERSION 2.8 ) 26 | get_filename_component ( project_dir ${CMAKE_CURRENT_LIST_DIR} NAME ) 27 | project ( ${project_dir} ) 28 | find_package ( OpenCV REQUIRED ) 29 | include_directories ( ${OpenCV_INCLUDE_DIRS} ) 30 | include_directories ( ${OpenVX_INCLUDE_DIRS} ) 31 | include_directories ( ${CMAKE_SOURCE_DIR}/include ) 32 | link_directories ( ${OpenVX_LIBS_DIR} ) 33 | if( POLICY CMP0054 ) 34 | cmake_policy( SET CMP0054 OLD ) 35 | endif() 36 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 37 | set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT" ) 38 | set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" ) 39 | endif() 40 | add_executable ( ${PROJECT_NAME} ${project_dir}.cpp ) 41 | target_link_libraries ( ${PROJECT_NAME} ${OpenVX_LIBS} ${OpenCV_LIBRARIES} ) 42 | -------------------------------------------------------------------------------- /tutorial_exercises/exercise4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # Assumes that there is only one .cpp file with same name as project folder name 24 | 25 | cmake_minimum_required ( VERSION 2.8 ) 26 | get_filename_component ( project_dir ${CMAKE_CURRENT_LIST_DIR} NAME ) 27 | project ( ${project_dir} ) 28 | find_package ( OpenCV REQUIRED ) 29 | include_directories ( ${OpenCV_INCLUDE_DIRS} ) 30 | include_directories ( ${OpenVX_INCLUDE_DIRS} ) 31 | include_directories ( ${CMAKE_SOURCE_DIR}/include ) 32 | link_directories ( ${OpenVX_LIBS_DIR} ) 33 | if( POLICY CMP0054 ) 34 | cmake_policy( SET CMP0054 OLD ) 35 | endif() 36 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 37 | set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT" ) 38 | set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" ) 39 | endif() 40 | add_executable ( ${PROJECT_NAME} ${project_dir}.cpp ) 41 | target_link_libraries ( ${PROJECT_NAME} ${OpenVX_LIBS} ${OpenCV_LIBRARIES} ) 42 | -------------------------------------------------------------------------------- /tutorial_exercises/exercise2a/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # Assumes that there is only one .cpp file with same name as project folder name 24 | 25 | cmake_minimum_required ( VERSION 2.8 ) 26 | get_filename_component ( project_dir ${CMAKE_CURRENT_LIST_DIR} NAME ) 27 | project ( ${project_dir} ) 28 | find_package ( OpenCV REQUIRED ) 29 | include_directories ( ${OpenCV_INCLUDE_DIRS} ) 30 | include_directories ( ${OpenVX_INCLUDE_DIRS} ) 31 | include_directories ( ${CMAKE_SOURCE_DIR}/include ) 32 | link_directories ( ${OpenVX_LIBS_DIR} ) 33 | if( POLICY CMP0054 ) 34 | cmake_policy( SET CMP0054 OLD ) 35 | endif() 36 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 37 | set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT" ) 38 | set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" ) 39 | endif() 40 | add_executable ( ${PROJECT_NAME} ${project_dir}.cpp ) 41 | target_link_libraries ( ${PROJECT_NAME} ${OpenVX_LIBS} ${OpenCV_LIBRARIES} ) 42 | -------------------------------------------------------------------------------- /tutorial_exercises/solution_exercise1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # Assumes that there is only one .cpp file with same name as project folder name 24 | 25 | cmake_minimum_required ( VERSION 2.8 ) 26 | get_filename_component ( project_dir ${CMAKE_CURRENT_LIST_DIR} NAME ) 27 | project ( ${project_dir} ) 28 | find_package ( OpenCV REQUIRED ) 29 | include_directories ( ${OpenCV_INCLUDE_DIRS} ) 30 | include_directories ( ${OpenVX_INCLUDE_DIRS} ) 31 | include_directories ( ${CMAKE_SOURCE_DIR}/include ) 32 | link_directories ( ${OpenVX_LIBS_DIR} ) 33 | if( POLICY CMP0054 ) 34 | cmake_policy( SET CMP0054 OLD ) 35 | endif() 36 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 37 | set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT" ) 38 | set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" ) 39 | endif() 40 | add_executable ( ${PROJECT_NAME} ${project_dir}.cpp ) 41 | target_link_libraries ( ${PROJECT_NAME} ${OpenVX_LIBS} ${OpenCV_LIBRARIES} ) 42 | -------------------------------------------------------------------------------- /tutorial_exercises/solution_exercise2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # Assumes that there is only one .cpp file with same name as project folder name 24 | 25 | cmake_minimum_required ( VERSION 2.8 ) 26 | get_filename_component ( project_dir ${CMAKE_CURRENT_LIST_DIR} NAME ) 27 | project ( ${project_dir} ) 28 | find_package ( OpenCV REQUIRED ) 29 | include_directories ( ${OpenCV_INCLUDE_DIRS} ) 30 | include_directories ( ${OpenVX_INCLUDE_DIRS} ) 31 | include_directories ( ${CMAKE_SOURCE_DIR}/include ) 32 | link_directories ( ${OpenVX_LIBS_DIR} ) 33 | if( POLICY CMP0054 ) 34 | cmake_policy( SET CMP0054 OLD ) 35 | endif() 36 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 37 | set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT" ) 38 | set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" ) 39 | endif() 40 | add_executable ( ${PROJECT_NAME} ${project_dir}.cpp ) 41 | target_link_libraries ( ${PROJECT_NAME} ${OpenVX_LIBS} ${OpenCV_LIBRARIES} ) 42 | -------------------------------------------------------------------------------- /tutorial_exercises/solution_exercise2a/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # Assumes that there is only one .cpp file with same name as project folder name 24 | 25 | cmake_minimum_required ( VERSION 2.8 ) 26 | get_filename_component ( project_dir ${CMAKE_CURRENT_LIST_DIR} NAME ) 27 | project ( ${project_dir} ) 28 | find_package ( OpenCV REQUIRED ) 29 | include_directories ( ${OpenCV_INCLUDE_DIRS} ) 30 | include_directories ( ${OpenVX_INCLUDE_DIRS} ) 31 | include_directories ( ${CMAKE_SOURCE_DIR}/include ) 32 | link_directories ( ${OpenVX_LIBS_DIR} ) 33 | if( POLICY CMP0054 ) 34 | cmake_policy( SET CMP0054 OLD ) 35 | endif() 36 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 37 | set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT" ) 38 | set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" ) 39 | endif() 40 | add_executable ( ${PROJECT_NAME} ${project_dir}.cpp ) 41 | target_link_libraries ( ${PROJECT_NAME} ${OpenVX_LIBS} ${OpenCV_LIBRARIES} ) 42 | -------------------------------------------------------------------------------- /tutorial_exercises/solution_exercise3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # Assumes that there is only one .cpp file with same name as project folder name 24 | 25 | cmake_minimum_required ( VERSION 2.8 ) 26 | get_filename_component ( project_dir ${CMAKE_CURRENT_LIST_DIR} NAME ) 27 | project ( ${project_dir} ) 28 | find_package ( OpenCV REQUIRED ) 29 | include_directories ( ${OpenCV_INCLUDE_DIRS} ) 30 | include_directories ( ${OpenVX_INCLUDE_DIRS} ) 31 | include_directories ( ${CMAKE_SOURCE_DIR}/include ) 32 | link_directories ( ${OpenVX_LIBS_DIR} ) 33 | if( POLICY CMP0054 ) 34 | cmake_policy( SET CMP0054 OLD ) 35 | endif() 36 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 37 | set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT" ) 38 | set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" ) 39 | endif() 40 | add_executable ( ${PROJECT_NAME} ${project_dir}.cpp ) 41 | target_link_libraries ( ${PROJECT_NAME} ${OpenVX_LIBS} ${OpenCV_LIBRARIES} ) 42 | -------------------------------------------------------------------------------- /tutorial_exercises/solution_exercise4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # Assumes that there is only one .cpp file with same name as project folder name 24 | 25 | cmake_minimum_required ( VERSION 2.8 ) 26 | get_filename_component ( project_dir ${CMAKE_CURRENT_LIST_DIR} NAME ) 27 | project ( ${project_dir} ) 28 | find_package ( OpenCV REQUIRED ) 29 | include_directories ( ${OpenCV_INCLUDE_DIRS} ) 30 | include_directories ( ${OpenVX_INCLUDE_DIRS} ) 31 | include_directories ( ${CMAKE_SOURCE_DIR}/include ) 32 | link_directories ( ${OpenVX_LIBS_DIR} ) 33 | if( POLICY CMP0054 ) 34 | cmake_policy( SET CMP0054 OLD ) 35 | endif() 36 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 37 | set ( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT" ) 38 | set ( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd" ) 39 | endif() 40 | add_executable ( ${PROJECT_NAME} ${project_dir}.cpp ) 41 | target_link_libraries ( ${PROJECT_NAME} ${OpenVX_LIBS} ${OpenCV_LIBRARIES} ) 42 | -------------------------------------------------------------------------------- /tutorial_exercises/include/VX/vx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2015 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | 24 | #ifndef _OPENVX_H_ 25 | #define _OPENVX_H_ 26 | 27 | /*! 28 | * \file 29 | * \brief The top level OpenVX Header. 30 | */ 31 | 32 | /*! \brief Defines the maximum number of characters in a implementation string. 33 | * \ingroup group_context 34 | */ 35 | #define VX_MAX_IMPLEMENTATION_NAME (64) 36 | 37 | /*! \brief Defines the maximum string length of a kernel name to be added to OpenVX. 38 | * \ingroup group_kernel 39 | */ 40 | #define VX_MAX_KERNEL_NAME (256) 41 | 42 | /*! \brief Defines the maximum length of a message buffer to copy from the log. 43 | * \ingroup group_basic_features 44 | */ 45 | #define VX_MAX_LOG_MESSAGE_LEN (1024) 46 | 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | 53 | /*! Defines the major version number macro. 54 | * \ingroup group_basic_features 55 | */ 56 | #define VX_VERSION_MAJOR(x) ((x & 0xFF) << 8) 57 | 58 | /*! Defines the minor version number macro. 59 | * \ingroup group_basic_features 60 | */ 61 | #define VX_VERSION_MINOR(x) ((x & 0xFF) << 0) 62 | 63 | /*! \brief Defines the predefined version number for 1.0. 64 | * \ingroup group_basic_features 65 | */ 66 | #define VX_VERSION_1_0 (VX_VERSION_MAJOR(1) | VX_VERSION_MINOR(0)) 67 | 68 | /*! Defines the OpenVX Version Number. 69 | * \ingroup group_basic_features 70 | */ 71 | #define VX_VERSION VX_VERSION_1_0 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /tutorial_exercises/include/VX/vx_vendors.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2015 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY,\todo FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | 24 | #ifndef _OPENVX_VENDORS_H_ 25 | #define _OPENVX_VENDORS_H_ 26 | 27 | /*! 28 | * \file 29 | * \brief The Vendor ID list for OpenVX. 30 | */ 31 | 32 | /*! \brief The Vendor ID of the Implementation. As new vendors submit their 33 | * implementations, this enumeration will grow. 34 | * \ingroup group_basic_features 35 | */ 36 | enum vx_vendor_id_e { 37 | VX_ID_KHRONOS = 0x000, /*!< \brief The Khronos Group */ 38 | VX_ID_TI = 0x001, /*!< \brief Texas Instruments, Inc. */ 39 | VX_ID_QUALCOMM = 0x002, /*!< \brief Qualcomm, Inc. */ 40 | VX_ID_NVIDIA = 0x003, /*!< \brief NVIDIA Corporation */ 41 | VX_ID_ARM = 0x004, /*!< \brief ARM Ltd. */ 42 | VX_ID_BDTI = 0x005, /*!< \brief Berkley Design Technology, Inc. */ 43 | VX_ID_RENESAS = 0x006, /*!< \brief Renasas Electronics */ 44 | VX_ID_VIVANTE = 0x007, /*!< \brief Vivante Corporation */ 45 | VX_ID_XILINX = 0x008, /*!< \brief Xilinx Inc. */ 46 | VX_ID_AXIS = 0x009, /*!< \brief Axis Communications */ 47 | VX_ID_MOVIDIUS = 0x00A, /*!< \brief Movidius Ltd. */ 48 | VX_ID_SAMSUNG = 0x00B, /*!< \brief Samsung Electronics */ 49 | VX_ID_FREESCALE = 0x00C, /*!< \brief Freescale Semiconductor */ 50 | VX_ID_AMD = 0x00D, /*!< \brief Advanced Micro Devices */ 51 | VX_ID_BROADCOM = 0x00E, /*!< \brief Broadcom Corporation */ 52 | VX_ID_INTEL = 0x00F, /*!< \brief Intel Corporation */ 53 | VX_ID_MARVELL = 0x010, /*!< \brief Marvell Technology Group Ltd. */ 54 | VX_ID_MEDIATEK = 0x011, /*!< \brief MediaTek, Inc. */ 55 | VX_ID_ST = 0x012, /*!< \brief STMicroelectronics */ 56 | VX_ID_CEVA = 0x013, /*!< \brief CEVA DSP */ 57 | VX_ID_ITSEEZ = 0x014, /*!< \brief Itseez, Inc. */ 58 | VX_ID_IMAGINATION=0x015, /*!< \brief Imagination Technologies */ 59 | VX_ID_COGNIVUE = 0x016, /*!< \brief CogniVue Corporation */ 60 | VX_ID_VIDEANTIS = 0x017, /*!< \brief Videantis */ 61 | VX_ID_SYNOPSYS = 0x018, /*!< \brief Synopsys */ 62 | /* Add new vendor code above this line */ 63 | 64 | VX_ID_MAX = 0xFFF, 65 | /*! \brief For use by all Kernel authors until they can obtain an assigned ID. */ 66 | VX_ID_DEFAULT = VX_ID_MAX, 67 | }; 68 | 69 | #endif 70 | 71 | -------------------------------------------------------------------------------- /tutorial_exercises/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 The Khronos Group Inc. 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a 4 | # copy of this software and/or associated documentation files (the 5 | # "Materials"), to deal in the Materials without restriction, including 6 | # without limitation the rights to use, copy, modify, merge, publish, 7 | # distribute, sublicense, and/or sell copies of the Materials, and to 8 | # permit persons to whom the Materials are furnished to do so, subject to 9 | # the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included 12 | # in all copies or substantial portions of the Materials. 13 | # 14 | # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 21 | 22 | # Author: Radhakrishna Giduthuri (radha.giduthuri@ieee.org) 23 | # 24 | # Supported cmake variables and CACHE entries: 25 | # OpenVX_SOURCE_DIR -- OpenVX open source folder with CMakeLists.txt 26 | # OpenVX_LIBS -- list of OpenVX libraries 27 | # OpenVX_LIBS_DIR -- path to OpenVX libraries 28 | # OpenVX_INCLUDE_DIRS -- path to non-khronos OpenVX header files (optional) 29 | # 30 | # Here are few examples: 31 | # * Build exerciese using an open source implementation without using OpenCL 32 | # % pushd .../openvx_tutorial/tutorial_exercises 33 | # % git clone https://github.com/GPUOpen-ProfessionalCompute-Libraries/amdovx-core 34 | # % popd 35 | # % cmake -DOpenVX_SOURCE_DIR=amdovx-core/openvx \ 36 | # -DCMAKE_DISABLE_FIND_PACKAGE_OpenCL=TRUE \ 37 | # .../openvx_tutorial/tutorial_exercises 38 | # * Build exerciese using a 3rd-party OpenVX library 39 | # % cmake -DOpenVX_LIBS_DIR= \ 40 | # -DOpenVX_LIBS= \ 41 | # .../openvx_tutorial/tutorial_exercises 42 | 43 | cmake_minimum_required ( VERSION 2.8 ) 44 | project ( tutorial_exercises ) 45 | 46 | if( POLICY CMP0054 ) 47 | cmake_policy( SET CMP0054 OLD ) 48 | endif() 49 | if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" ) 50 | set ( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE} ) 51 | else() 52 | set ( CMAKE_MACOSX_RPATH ON ) 53 | endif() 54 | 55 | # by default, use open-source OpenVX without OpenCL 56 | if( NOT OpenVX_LIBS_DIR ) 57 | if( ${CMAKE_SYSTEM_NAME} MATCHES "Linux" ) 58 | EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO) 59 | if( ${CPUINFO} MATCHES "sse4_2" ) 60 | set(SSE4_2_FOUND true CACHE BOOL "SSE4.2 available on host") 61 | else() 62 | set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host") 63 | endif() 64 | elseif( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" ) 65 | EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.features" OUTPUT_VARIABLE CPUINFO) 66 | if( ${CPUINFO} MATCHES "SSE4.2" ) 67 | set(SSE4_2_FOUND true CACHE BOOL "SSE4.2 available on host") 68 | else() 69 | set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host") 70 | endif() 71 | endif() 72 | if( SSE4_2_FOUND ) 73 | set ( OpenVX_SOURCE_DIR amdovx-core/openvx CACHE INTERNAL OpenVX_SOURCE_DIR ) 74 | if( EXISTS ${CMAKE_SOURCE_DIR}/${OpenVX_SOURCE_DIR} ) 75 | set ( OpenVX_LIBS openvx CACHE INTERNAL OpenVX_LIBS ) 76 | set ( CMAKE_DISABLE_FIND_PACKAGE_OpenCL TRUE CACHE INTERNAL CMAKE_DISABLE_FIND_PACKAGE_OpenCL ) 77 | endif() 78 | endif( SSE4_2_FOUND ) 79 | endif() 80 | 81 | if( OpenVX_SOURCE_DIR AND EXISTS ${CMAKE_SOURCE_DIR}/${OpenVX_SOURCE_DIR} ) 82 | add_subdirectory ( ${OpenVX_SOURCE_DIR} ) 83 | if( NOT OpenVX_LIBS ) 84 | set ( OpenVX_LIBS openvx CACHE INTERNAL OpenVX_LIBS ) 85 | endif() 86 | elseif( NOT OpenVX_LIBS_DIR ) 87 | set ( OpenVX_SAMPLE /home/openvx/openvx_sample/install/Linux/x64 ) 88 | set ( OpenVX_LIBS openvx vxu CACHE INTERNAL OpenVX_LIBS ) 89 | if( CMAKE_BUILD_TYPE MATCHES ".*Deb.*" ) 90 | set ( OpenVX_LIBS_DIR ${OpenVX_SAMPLE}/Debug/bin CACHE INTERNAL OpenVX_LIBPATH ) 91 | else( CMAKE_BUILD_TYPE MATCHES ".*Deb.*" ) 92 | set ( OpenVX_LIBS_DIR ${OpenVX_SAMPLE}/Release/bin CACHE INTERNAL OpenVX_LIBPATH ) 93 | endif( CMAKE_BUILD_TYPE MATCHES ".*Deb.*" ) 94 | endif() 95 | 96 | add_subdirectory ( exercise1 ) 97 | add_subdirectory ( exercise2 ) 98 | add_subdirectory ( exercise2a ) 99 | add_subdirectory ( exercise3 ) 100 | add_subdirectory ( exercise4 ) 101 | add_subdirectory ( solution_exercise1 ) 102 | add_subdirectory ( solution_exercise2 ) 103 | add_subdirectory ( solution_exercise2a ) 104 | add_subdirectory ( solution_exercise3 ) 105 | add_subdirectory ( solution_exercise4 ) 106 | -------------------------------------------------------------------------------- /tutorial_exercises/include/opencv_camera_display.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | 24 | /*! 25 | * \file opencv_camera_display.h 26 | * \brief wrapper for OpenCV camera/file-input and display 27 | * \author Radhakrishna Giduthuri 28 | */ 29 | 30 | #ifndef __opencv_camera_display_h__ 31 | #define __opencv_camera_display_h__ 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #ifndef DEFAULT_VIDEO_SEQUENCE 38 | #define DEFAULT_VIDEO_SEQUENCE "../../tutorial_videos/PETS09-S1-L1-View001.avi" 39 | #endif 40 | 41 | #ifndef DEFAULT_WAITKEY_DELAY 42 | #define DEFAULT_WAITKEY_DELAY 1 /* waitKey delay time in milliseconds after each frame processing */ 43 | #endif 44 | 45 | class CGuiModule 46 | { 47 | public: 48 | CGuiModule( const char * captureFile ) 49 | : m_cap( captureFile ? captureFile : DEFAULT_VIDEO_SEQUENCE ) 50 | { 51 | captureFile = captureFile ? captureFile : DEFAULT_VIDEO_SEQUENCE; 52 | m_windowName = captureFile; 53 | if( !m_cap.isOpened()) 54 | { 55 | printf( "ERROR: unable to open: %s\n", captureFile ); 56 | exit( 1 ); 57 | } 58 | printf( "OK: FILE %s %dx%d\n", captureFile, GetWidth(), GetHeight()); 59 | cv::namedWindow(m_windowName); 60 | } 61 | 62 | CGuiModule( int captureDevice ) 63 | : m_cap( captureDevice ) 64 | { 65 | char name[64]; sprintf( name, "CAMERA#%d", captureDevice ); 66 | m_windowName = name; 67 | if( !m_cap.isOpened()) 68 | { 69 | printf( "ERROR: CAMERA#%d not available\n", captureDevice ); 70 | exit( 1 ); 71 | } 72 | printf( "OK: CAMERA#%d %dx%d\n", captureDevice, GetWidth(), GetHeight()); 73 | cv::namedWindow(m_windowName); 74 | } 75 | 76 | int GetWidth() 77 | { 78 | return (int) m_cap.get( CV_CAP_PROP_FRAME_WIDTH ); 79 | } 80 | 81 | int GetHeight() 82 | { 83 | return (int) m_cap.get( CV_CAP_PROP_FRAME_HEIGHT ); 84 | } 85 | 86 | int GetStride() 87 | { 88 | return (int) m_imgRGB.step; 89 | } 90 | 91 | unsigned char * GetBuffer() 92 | { 93 | return m_imgRGB.data; 94 | } 95 | 96 | bool Grab() 97 | { 98 | m_cap >> m_imgBGR; 99 | if( m_imgBGR.empty() ) 100 | { 101 | return false; 102 | } 103 | cv::cvtColor( m_imgBGR, m_imgRGB, cv::COLOR_BGR2RGB ); 104 | return true; 105 | } 106 | 107 | void DrawText( int x, int y, const char * text ) 108 | { 109 | cv::putText( m_imgBGR, text, cv::Point( x, y ), 110 | cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, cv::Scalar( 128, 0, 0 ), 1, CV_AA ); 111 | } 112 | 113 | void DrawPoint( int x, int y ) 114 | { 115 | cv::Point center( x, y ); 116 | cv::circle( m_imgBGR, center, 1, cv::Scalar( 0, 0, 255 ), 2 ); 117 | } 118 | 119 | void DrawArrow( int x0, int y0, int x1, int y1 ) 120 | { 121 | DrawPoint( x0, y0 ); 122 | float dx = (float) ( x1 - x0 ), dy = (float) ( y1 - y0 ), arrow_len = sqrtf( dx * dx + dy * dy ); 123 | if(( arrow_len >= 3.0f ) && ( arrow_len <= 50.0f ) ) 124 | { 125 | cv::Scalar color = cv::Scalar( 0, 255, 255 ); 126 | float tip_len = 5.0f + arrow_len * 0.1f, angle = atan2f( dy, dx ); 127 | cv::line( m_imgBGR, cv::Point( x0, y0 ), cv::Point( x1, y1 ), color, 1 ); 128 | cv::line( m_imgBGR, cv::Point( x1, y1 ), cv::Point( x1 - (int) ( tip_len * cosf( angle + (float) CV_PI / 6 )), y1 - (int) ( tip_len * sinf( angle + (float) CV_PI / 6 ))), color, 1 ); 129 | cv::line( m_imgBGR, cv::Point( x1, y1 ), cv::Point( x1 - (int) ( tip_len * cosf( angle - (float) CV_PI / 6 )), y1 - (int) ( tip_len * sinf( angle - (float) CV_PI / 6 ))), color, 1 ); 130 | } 131 | } 132 | 133 | void Show() 134 | { 135 | cv::imshow( m_windowName, m_imgBGR ); 136 | } 137 | 138 | bool AbortRequested() 139 | { 140 | char key = cv::waitKey( DEFAULT_WAITKEY_DELAY ); 141 | if( key == ' ' ) 142 | { 143 | key = cv::waitKey( 0 ); 144 | } 145 | if(( key == 'q' ) || ( key == 'Q' ) || ( key == 27 ) /*ESC*/ ) 146 | { 147 | return true; 148 | } 149 | return false; 150 | } 151 | 152 | void WaitForKey() 153 | { 154 | cv::waitKey( 0 ); 155 | } 156 | 157 | protected: 158 | std::string m_windowName; 159 | cv::VideoCapture m_cap; 160 | cv::Mat m_imgBGR; 161 | cv::Mat m_imgRGB; 162 | }; 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /tutorial_exercises/include/VX/vx_kernels.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2015 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | 24 | #ifndef _OPENVX_KERNELS_H_ 25 | #define _OPENVX_KERNELS_H_ 26 | 27 | /*! 28 | * \file 29 | * \brief The list of supported kernels in the OpenVX standard. 30 | */ 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | /*! \brief The standard list of available libraries */ 37 | enum vx_library_e { 38 | /*! \brief The base set of kernels as defined by Khronos. */ 39 | VX_LIBRARY_KHR_BASE = 0x0, 40 | }; 41 | 42 | /*! 43 | * \brief The standard list of available vision kernels. 44 | * 45 | * Each kernel listed here can be used with the \ref vxGetKernelByEnum call. 46 | * When programming the parameters, use 47 | * \arg \ref VX_INPUT for [in] 48 | * \arg \ref VX_OUTPUT for [out] 49 | * \arg \ref VX_BIDIRECTIONAL for [in,out] 50 | * 51 | * When programming the parameters, use 52 | * \arg \ref VX_TYPE_IMAGE for a \ref vx_image in the size field of \ref vxGetParameterByIndex or \ref vxSetParameterByIndex * \arg \ref VX_TYPE_ARRAY for a \ref vx_array in the size field of \ref vxGetParameterByIndex or \ref vxSetParameterByIndex * \arg or other appropriate types in \ref vx_type_e. 53 | * \ingroup group_kernel 54 | */ 55 | enum vx_kernel_e { 56 | 57 | /*! 58 | * \brief The invalid kernel is used to for conformance failure in relation to 59 | * some kernel operation (Get/Release). 60 | * \details If the kernel is executed it shall always return an error. 61 | * The kernel has no parameters. To address by name use "org.khronos.openvx.invalid". 62 | */ 63 | VX_KERNEL_INVALID = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x0, 64 | 65 | /*! 66 | * \brief The Color Space conversion kernel. 67 | * \details The conversions are based on the \ref vx_df_image_e code in the images. 68 | * \see group_vision_function_colorconvert 69 | */ 70 | VX_KERNEL_COLOR_CONVERT = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x1, 71 | 72 | /*! 73 | * \brief The Generic Channel Extraction Kernel. 74 | * \details This kernel can remove individual color channels from an interleaved 75 | * or semi-planar, planar, sub-sampled planar image. A client could extract 76 | * a red channel from an interleaved RGB image or do a Luma extract from a 77 | * YUV format. 78 | * \see group_vision_function_channelextract 79 | */ 80 | VX_KERNEL_CHANNEL_EXTRACT = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x2, 81 | 82 | /*! 83 | * \brief The Generic Channel Combine Kernel. 84 | * \details This kernel combine multiple individual planes into a single 85 | * multiplanar image of the type specified in the output image. 86 | * \see group_vision_function_channelcombine 87 | */ 88 | VX_KERNEL_CHANNEL_COMBINE = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x3, 89 | 90 | /*! \brief The Sobel 3x3 Filter Kernel. 91 | * \see group_vision_function_sobel3x3 92 | */ 93 | VX_KERNEL_SOBEL_3x3 = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x4, 94 | 95 | /*! 96 | * \brief The Magnitude Kernel. 97 | * \details This kernel produces a magnitude plane from two input gradients. 98 | * \see group_vision_function_magnitude 99 | */ 100 | VX_KERNEL_MAGNITUDE = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x5, 101 | 102 | /*! 103 | * \brief The Phase Kernel. 104 | * \details This kernel produces a phase plane from two input gradients. 105 | * \see group_vision_function_phase 106 | */ 107 | VX_KERNEL_PHASE = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x6, 108 | 109 | /*! 110 | * \brief The Scale Image Kernel. 111 | * \details This kernel provides resizing of an input image to an output image. 112 | * The scaling factor is determined but the relative sizes of the input and 113 | * output. 114 | * \see group_vision_function_scale_image 115 | */ 116 | VX_KERNEL_SCALE_IMAGE = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x7, 117 | 118 | /*! \brief The Table Lookup kernel 119 | * \see group_vision_function_lut 120 | */ 121 | VX_KERNEL_TABLE_LOOKUP = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x8, 122 | 123 | /*! \brief The Histogram Kernel. 124 | * \see group_vision_function_histogram 125 | */ 126 | VX_KERNEL_HISTOGRAM = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x9, 127 | 128 | /*! \brief The Histogram Equalization Kernel. 129 | * \see group_vision_function_equalize_hist 130 | */ 131 | VX_KERNEL_EQUALIZE_HISTOGRAM = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0xA, 132 | 133 | /*! \brief The Absolute Difference Kernel. 134 | * \see group_vision_function_absdiff 135 | */ 136 | VX_KERNEL_ABSDIFF = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0xB, 137 | 138 | /*! \brief The Mean and Standard Deviation Kernel. 139 | * \see group_vision_function_meanstddev 140 | */ 141 | VX_KERNEL_MEAN_STDDEV = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0xC, 142 | 143 | /*! \brief The Threshold Kernel. 144 | * \see group_vision_function_threshold 145 | */ 146 | VX_KERNEL_THRESHOLD = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0xD, 147 | 148 | /*! \brief The Integral Image Kernel. 149 | * \see group_vision_function_integral_image 150 | */ 151 | VX_KERNEL_INTEGRAL_IMAGE = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0xE, 152 | 153 | /*! \brief The dilate kernel. 154 | * \see group_vision_function_dilate_image 155 | */ 156 | VX_KERNEL_DILATE_3x3 = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0xF, 157 | 158 | /*! \brief The erode kernel. 159 | * \see group_vision_function_erode_image 160 | */ 161 | VX_KERNEL_ERODE_3x3 = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x10, 162 | 163 | /*! \brief The median image filter. 164 | * \see group_vision_function_median_image 165 | */ 166 | VX_KERNEL_MEDIAN_3x3 = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x11, 167 | 168 | /*! \brief The box filter kernel. 169 | * \see group_vision_function_box_image 170 | */ 171 | VX_KERNEL_BOX_3x3 = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x12, 172 | 173 | /*! \brief The gaussian filter kernel. 174 | * \see group_vision_function_gaussian_image 175 | */ 176 | VX_KERNEL_GAUSSIAN_3x3 = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x13, 177 | 178 | /*! \brief The custom convolution kernel. 179 | * \see group_vision_function_custom_convolution 180 | */ 181 | VX_KERNEL_CUSTOM_CONVOLUTION = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x14, 182 | 183 | /*! \brief The gaussian image pyramid kernel. 184 | * \see group_vision_function_gaussian_pyramid 185 | */ 186 | VX_KERNEL_GAUSSIAN_PYRAMID = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x15, 187 | 188 | /*! \brief The accumulation kernel. 189 | * \see group_vision_function_accumulate 190 | */ 191 | VX_KERNEL_ACCUMULATE = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x16, 192 | 193 | /*! \brief The weigthed accumulation kernel. 194 | * \see group_vision_function_accumulate_weighted 195 | */ 196 | VX_KERNEL_ACCUMULATE_WEIGHTED = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x17, 197 | 198 | /*! \brief The squared accumulation kernel. 199 | * \see group_vision_function_accumulate_square 200 | */ 201 | VX_KERNEL_ACCUMULATE_SQUARE = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x18, 202 | 203 | /*! \brief The min and max location kernel. 204 | * \see group_vision_function_minmaxloc 205 | */ 206 | VX_KERNEL_MINMAXLOC = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x19, 207 | 208 | /*! \brief The bit-depth conversion kernel. 209 | * \see group_vision_function_convertdepth 210 | */ 211 | VX_KERNEL_CONVERTDEPTH = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x1A, 212 | 213 | /*! \brief The Canny Edge Detector. 214 | * \see group_vision_function_canny 215 | */ 216 | VX_KERNEL_CANNY_EDGE_DETECTOR = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x1B, 217 | 218 | /*! \brief The Bitwise And Kernel. 219 | * \see group_vision_function_and 220 | */ 221 | VX_KERNEL_AND = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x1C, 222 | 223 | /*! \brief The Bitwise Inclusive Or Kernel. 224 | * \see group_vision_function_or 225 | */ 226 | VX_KERNEL_OR = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x1D, 227 | 228 | /*! \brief The Bitwise Exclusive Or Kernel. 229 | * \see group_vision_function_xor 230 | */ 231 | VX_KERNEL_XOR = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x1E, 232 | 233 | /*! \brief The Bitwise Not Kernel. 234 | * \see group_vision_function_not 235 | */ 236 | VX_KERNEL_NOT = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x1F, 237 | 238 | /*! \brief The Pixelwise Multiplication Kernel. 239 | * \see group_vision_function_mult 240 | */ 241 | VX_KERNEL_MULTIPLY = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x20, 242 | 243 | /*! \brief The Addition Kernel. 244 | * \see group_vision_function_add 245 | */ 246 | VX_KERNEL_ADD = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x21, 247 | 248 | /*! \brief The Subtraction Kernel. 249 | * \see group_vision_function_sub 250 | */ 251 | VX_KERNEL_SUBTRACT = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x22, 252 | 253 | /*! \brief The Warp Affine Kernel. 254 | * \see group_vision_function_warp_affine 255 | */ 256 | VX_KERNEL_WARP_AFFINE = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x23, 257 | 258 | /*! \brief The Warp Perspective Kernel. 259 | * \see group_vision_function_warp_perspective 260 | */ 261 | VX_KERNEL_WARP_PERSPECTIVE = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x24, 262 | 263 | /*! \brief The Harris Corners Kernel. 264 | * \see group_vision_function_harris 265 | */ 266 | VX_KERNEL_HARRIS_CORNERS = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x25, 267 | 268 | /*! \brief The FAST Corners Kernel. 269 | * \see group_vision_function_fast 270 | */ 271 | VX_KERNEL_FAST_CORNERS = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x26, 272 | 273 | /*! \brief The Optical Flow Pyramid (LK) Kernel. 274 | * \see group_vision_function_opticalflowpyrlk 275 | */ 276 | VX_KERNEL_OPTICAL_FLOW_PYR_LK = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x27, 277 | 278 | /*! \brief The Remap Kernel. 279 | * \see group_vision_function_remap 280 | */ 281 | VX_KERNEL_REMAP = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x28, 282 | 283 | 284 | /*! \brief The Half Scale Gaussian Kernel. 285 | * \see group_vision_function_scale_image 286 | */ 287 | VX_KERNEL_HALFSCALE_GAUSSIAN = VX_KERNEL_BASE(VX_ID_KHRONOS, VX_LIBRARY_KHR_BASE) + 0x29, 288 | 289 | /* insert new kernels here */ 290 | VX_KERNEL_MAX_1_0, /*!< \internal Used for bounds checking in the conformance test. */ 291 | }; 292 | 293 | #ifdef __cplusplus 294 | } 295 | #endif 296 | 297 | #endif /* _OPEN_VISION_LIBRARY_KERNELS_H_ */ 298 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Khronos OpenVX Tutorial Material 2 | [OpenVX](https://www.khronos.org/registry/vx/) 3 | is a royalty-free open standard API released by the Khronos Group 4 | in 2014. OpenVX enables performance and power-optimized computer vision 5 | functionality, especially important in embedded and real-time use cases. 6 | This course covers both the function-based API and the graph API that 7 | enable OpenVX developers to efficiently run computer vision algorithms 8 | on heterogeneous computing architectures. A set of example algorithms 9 | from computational photography and advanced driver assistance mapped to 10 | the graph API will be discussed. Also covered is the relationship between 11 | OpenVX and OpenCV, as well as OpenCL. The tutorial includes hands-on practice 12 | sessions that get the participants started on solving real computer vision 13 | problems using OpenVX. 14 | 15 | This tutorial material is based on OpenVX 1.0.1 and it can be used on a PC with recent 64-bit OS (Windows, OS X, or Linux). 16 | Tutorial exercises and build procedures on various platforms are explained in this document. 17 | An additional section explains tutorial exercises with a VirtualBox VM. 18 | 1. [Tutorial Exercises Overview](#1-tutorial-exercises-overview) 19 | 2. [Build on any PC using VirtualBox software and a pre-built VM](#2-build-on-any-pc-using-virtualbox-software-and-a-pre-built-vm) (recommended) 20 | 3. [Build on Mac or Linux PC](#3-build-on-mac-or-linux-pc) 21 | 4. [Build on Windows PC using Visual Studio 2015 (Free)](#4-build-on-windows-pc-using-visual-studio-2015-free) 22 | 23 | NOTE: The directory ``~`` in the text below refers to directory containing the ``openvx_tutorial`` sub-directory. 24 | 25 | ## 1. Tutorial Exercises Overview 26 | It is best to start doing these exercises after going through the tutorial presentations below. 27 | 1. [OpenVX_Ecosystem.pdf](https://www.khronos.org/assets/uploads/developers/library/2016-embedded-vision-summit/T1_OpenVX_Ecosystem.pdf) 28 | 2. [OpenVX_Step1_Introduction.pdf](https://www.khronos.org/assets/uploads/developers/library/2016-embedded-vision-summit/T2_OpenVX_Step1_Introduction.pdf) 29 | 3. [OpenVX_Step2_Graphs.pdf](https://www.khronos.org/assets/uploads/developers/library/2016-embedded-vision-summit/T3_OpenVX_Step2_Graphs.pdf) 30 | 4. [OpenVX_Step3_Efficient_IO.pdf](https://www.khronos.org/assets/uploads/developers/library/2016-embedded-vision-summit/T4_OpenVX_Step3_Efficient_IO.pdf) 31 | 5. [OpenVX_Step4_User_Kernels.pdf](https://www.khronos.org/assets/uploads/developers/library/2016-embedded-vision-summit/T5_OpenVX_Step4_User_Kernels.pdf) 32 | 6. [OpenVX_Spec1.1_Changes.pdf](https://www.khronos.org/assets/uploads/developers/library/2016-embedded-vision-summit/T6_OpenVX_Spec1.1_Changes.pdf) 33 | 34 | All the tutorial exercises are kept in ``~/openvx_tutorial/tutorial_exercises``. 35 | The ``tutorial_exercises/CMakeLists.txt`` includes all the exercises as separate 36 | projects. All of the exercise folders contain only one .cpp file with main() 37 | as the entry point. All the include files are kept in the 38 | ``tutorial_exercises/include`` directory. 39 | 40 | The ``tutorial_exercises`` sub-directory contains four exercises: 41 | * ``exercise1``: framework basics, import media, run a keypoint detector 42 | * ``exercise2``: graph concepts, keypoint tracking 43 | * ``exercise2a``: framework basics, graph concepts, keypoint tracking (exercise1+exercise2) 44 | * ``exercise3``: user kernels, build a wrapper kernel to OpenCV function 45 | * ``exercise4``: user kernels, build a keypoint tracker 46 | 47 | There are additional folders with full solutions: 48 | * ``solution_exerciseN``: complete solution of ``exerciseN``. Just for reference. 49 | 50 | Each exercise requires you to modify ``exerciseN/exerciseN.cpp`` file. 51 | Here are few helpful instructions: 52 | * Look for ``TODO`` keyword in ``exerciseN/exerciseN.cpp`` comments for instructions 53 | for code snippets that you need to create. 54 | * The steps are numbered, do them in that order. 55 | * All header files are kept in ``tutorial_exercises/include``. 56 | To open a header file, move the cursor to corresponding ``#include`` statement 57 | in ``exerciseN/exerciseN.cpp`` and press *F2*. 58 | - The ``"opencv_camera_display.h"`` is a wrapper that imports media and 59 | displays results using OpenCV library. 60 | * ``#define DEFAULT_WAITKEY_DELAY 1`` is used to specify wait time in milliseconds after each frame processing; to slowdown use larger numbers; or use 0 to wait for a key after each frame. 61 | - The ``"VX/vx.h"`` & ``"VX/vxu.h"`` files are part of OpenVX header files 62 | downloaded from https://www.khronos.org/registry/vx/ 63 | * To view the definition of any OpenVX API or data type, simply move the 64 | cursor to the name and press *F2*. 65 | * The video sequence [PETS09-S1-L1-View001.avi](http://ewh.ieee.org/r6/scv/sps/openvx-material/PETS09-S1-L1-View001.avi) will be in ``~/openvx_tutorial/tutorial_videos`` folder. 66 | - All the exercises in this tutorial use this video sequence as input. 67 | - Optionally, you can also specify you own video sequence on command-line as an argument to exercises. 68 | * Once you finish all the exercises, try using Release Build to see better performance. 69 | 70 | ## 2. Build on any PC using VirtualBox software and a pre-built VM 71 | We have prepared a VirtualBox VM with this new course material. Make sure to setup your computer before starting the tutorial. 72 | * Choose a laptop with a recent 64-bit OS. 73 | * Download and install a recent VirtualBox from https://www.virtualbox.org/wiki/Downloads. 74 | * Download virtual machine "Ubuntu-64-OpenVX.zip" (2 GB) from https://goo.gl/iH7Rte and extract files into a local folder (~6 GB extracted). 75 | - This VM image includes all the necessary tools and packages required to run the tutorial, including the following two OpenVX implementations options: 76 | * [Open-source OpenVX on GitHub](https://github.com/GPUOpen-ProfessionalCompute-Libraries/amdovx-core/tree/OpenVX-1.0.1) from AMD (default) 77 | * Khronos OpenVX sample implementation from [khronos.org/registry/vx](https://www.khronos.org/registry/vx/) 78 | * Run VirtualBox and add "Ubuntu-64-OpenVX" virtual machine [Machine -> Add] from the local folder. 79 | - If you cannot install 64-bit VM, even though you have a 64-bit Windows, you need to enable virtualization in the BIOS. 80 | - In the Security section, enable Virtualization Technology and VT-d Feature. 81 | - On Windows 8.1, you also need to turn Hyper-V off (search for Turn Windows features on or off). 82 | * Start the "Ubuntu-64-OpenVX" virtual machine ([username: openvx][password: openvx]). 83 | * Run "Qt Creator" (click Qt icon on left) and open exercises project. 84 | - Open Project: ``CMakeLists.txt`` in ``/home/openvx/openvx_tutorial/tutorial_exercises`` 85 | - click *"Configure Project"* to open CMake Wizard 86 | - click *"Run CMake"* and *"Finish"* 87 | * Select exercise1 as active sub-project. 88 | - click *"Open Build and Run Kit Selector"* under the *"Build"* menu 89 | - select Run *"exercise1"* under the Build *"Default"* and press ESCAPE 90 | - expand *"exercise1"* folder and click *"exercise1.cpp"* 91 | - you are going to modify this file during the first practice session 92 | * Build the project and run. 93 | - click *"Run"* under the *"Build"* menu (or use keyboard shortcut Ctrl+R) 94 | - you should see video in a window (you can move the window for better view) 95 | - press ESCAPE or 'q' to exit the app 96 | 97 | Please note that the VirtualBox VM might not have the latest version of tutorial exercises. You can copy files from this GitHub project into ``/home/openvx/openvx_tutorial`` directory when new updates are available. 98 | 99 | ## 3. Build on Mac or Linux PC 100 | In order to build these tutorial exercises, you need the following: 101 | * Laptop with a recent 64-bit OS (OS X or Linux) 102 | * Download and install [OpenCV 3.1](http://opencv.org/downloads.html) 103 | * Download and install [Qt Creator](http://www.qt.io/download-open-source/) (optional) 104 | * Download and install an OpenVX implementation: 105 | - [Open-source OpenVX on GitHub](https://github.com/GPUOpen-ProfessionalCompute-Libraries/amdovx-core/tree/OpenVX-1.0.1) from AMD 106 | * Copy the source code into ``~/openvx_tutorial/tutorial_exercises/amdovx-core`` directory. 107 | * *CPU only build will be used for this tutorial*. 108 | - Khronos OpenVX sample implementation from [khronos.org/registry/vx](https://www.khronos.org/registry/vx/). 109 | * Follow the instructions in openvx_sample/README to create pre-built OpenVX libraries 110 | - See [Khronos OpenVX Resources](https://www.khronos.org/openvx/resources) for available commertial implementations. 111 | * Download [PETS09-S1-L1-View001.avi](http://ewh.ieee.org/r6/scv/sps/openvx-material/PETS09-S1-L1-View001.avi) and keep it in ``~/openvx_tutorial/tutorial_videos`` folder. 112 | 113 | ### 3.1 Build using open-source OpenVX 114 | Create an empty folder ``~/openvx_tutorial/build-open-source``. The directory structure should be like: 115 | ``` 116 | ~/openvx_tutorial/ 117 | ├── LICENSE 118 | ├── README.md 119 | ├── build-open-source/ 120 | ├── scripts/ 121 | ├── tutorial_exercises/ 122 | │ ├── amdovx-core/ 123 | │ ├── CMakeLists.txt 124 | │ ├── exercise1/ 125 | │ ├── exercise2/ 126 | │ ├── exercise2a/ 127 | │ ├── exercise3/ 128 | │ ├── exercise4/ 129 | │ ├── include/ 130 | │ ├── solution_exercise1/ 131 | │ ├── solution_exercise2/ 132 | │ ├── solution_exercise2a/ 133 | │ ├── solution_exercise3/ 134 | │ └── solution_exercise4/ 135 | └── tutorial_videos/ 136 | └── PETS09-S1-L1-View001.avi 137 | ``` 138 | * To prepare for build: ``% cd ~/openvx_tutorial/build-open-source; cmake ../tutorial_exercises; make`` 139 | * To build and run an example: ``% cd ~/openvx_tutorial/build-open-source/exercise1; make; ./exercise1`` 140 | * You should see video in a window. Press ESCAPE or 'q' to exit the app. 141 | 142 | ### 3.2 Build using open-source OpenVX in Qt Creator 143 | * Open Project ``~/openvx_tutorial/tutorial_exercises/CMakeLists.txt``. 144 | * Click *"Configure Project"* to open CMake Wizard 145 | * Click *"Run CMake"* and *"Done"* 146 | * Compile and run the project by clicking the higher of the green triangles at left bottom, or with *CTRL-R*. 147 | * You should see video in a window. Press ESCAPE or 'q' to exit the app. 148 | 149 | ### 3.3 Build using pre-built OpenVX library in Qt Creator 150 | * Open Project ``~/openvx_tutorial/tutorial_exercises/CMakeLists.txt``. 151 | * Click *"Configure Project"* to open CMake Wizard 152 | - Specify arguments: ``-DOpenVX_LIBS_DIR= -DOpenVX_LIBS=`` 153 | - Click *"Run CMake"* and *"Done"* 154 | * Compile and run the project by clicking the higher of the green triangles at left bottom, or with *CTRL-R*. 155 | * You should see video in a window. Press ESCAPE or 'q' to exit the app. 156 | 157 | ## 4. Build on Windows PC using Visual Studio 2015 (Free) 158 | In order to build these tutorial exercises, you need the following: 159 | * Laptop with a recent Windows 64-bit OS 160 | * Download and install [OpenCV 3.1](http://opencv.org/downloads.html) and set ``OpenCV_DIR`` environment variable to ``\opencv\build`` folder. 161 | * Download and install latest [CMake](https://cmake.org/download/) 162 | * Download and install [Visual Studio Community (Free)](https://www.visualstudio.com/downloads/download-visual-studio-vs) 163 | * Download and install an OpenVX implementation: 164 | - [Open-source OpenVX on GitHub](https://github.com/GPUOpen-ProfessionalCompute-Libraries/amdovx-core) from AMD 165 | * Copy the source code into ``~/openvx_tutorial/tutorial_exercises/amdovx-core`` directory. 166 | * *CPU only build will be used for this tutorial*. 167 | - Khronos OpenVX sample implementation from [khronos.org/registry/vx](https://www.khronos.org/registry/vx/). 168 | * Follow the instructions in openvx_sample/README to create pre-built OpenVX libraries 169 | - See [Khronos OpenVX Resources](https://www.khronos.org/openvx/resources) for available commertial implementations. 170 | * Download [PETS09-S1-L1-View001.avi](http://ewh.ieee.org/r6/scv/sps/openvx-material/PETS09-S1-L1-View001.avi) and keep it in ``~/openvx_tutorial/tutorial_videos`` folder. 171 | 172 | ### 4.1 Build using open-source OpenVX in Visual Studio 2015 173 | * Run CMake (cmake-gui) 174 | - Click *Browse Source* button and select ``~/openvx_tutorial/tutorial_exercises`` 175 | - Click *Browse Build* button and select ``~/openvx_tutorial/build-open-source`` 176 | - Click *Configure* button; you get a window asking for compilers to use: select *"Visual Studio 14 2015 Win64"* 177 | - Click *Generate* button 178 | * Run Visual Studio 2015 and open solution ``~/openvx_tutorial/build-open-source/tutorial_exercises.sln`` 179 | * Set *exercise1* as startup project 180 | * Build and run the project. 181 | * You should see video in a window. Press ESCAPE or 'q' to exit the app. 182 | 183 | ### 4.2 Build using pre-built OpenVX library in Visual Studio 2015 184 | * Run CMake (cmake-gui) 185 | - Click *Browse Source* button and select ``~/openvx_tutorial/tutorial_exercises`` 186 | - Click *Browse Build* button and select ``~/openvx_tutorial/build-open-source`` 187 | - Click *Add Entry* button 188 | * Set *Name* to ``OpenVX_LIBS_DIR`` 189 | * Set *Type* to *STRING* 190 | * Set *Value* to ```` 191 | * Click *OK* 192 | - Click *Add Entry* button 193 | * Set *Name* to ``OpenVX_LIBS`` 194 | * Set *Type* to *STRING* 195 | * Set *Value* to ```` 196 | * Click *OK* 197 | - Click *Configure* button; you get a window asking for compilers to use: select *"Visual Studio 14 2015 Win64"* 198 | - Click *Generate* button 199 | * Run Visual Studio 2015 and open solution ``~/openvx_tutorial/build-open-source/tutorial_exercises.sln`` 200 | * Set *exercise1* as startup project 201 | * Build and run the project. 202 | * You should see video in a window. Press ESCAPE or 'q' to exit the app. 203 | -------------------------------------------------------------------------------- /tutorial_exercises/exercise1/exercise1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | 24 | /*! 25 | * \file exercise1.cpp 26 | * \example exercise1 27 | * \brief Harris corners example. 28 | * Look for TODO STEP keyword in comments for the code snippets that you need to write. 29 | * \author Radhakrishna Giduthuri 30 | * Kari Pulli 31 | */ 32 | 33 | //////// 34 | // Include OpenCV wrapper for image capture and display. 35 | #include "opencv_camera_display.h" 36 | 37 | ////////******** 38 | // The most important top-level OpenVX header files are "VX/vx.h" and "VX/vxu.h". 39 | // The "VX/vx.h" includes all headers needed to support functionality of the 40 | // OpenVX specification, except for immediate mode functions, and it includes: 41 | // VX/vx_types.h -- type definitions required by the OpenVX standard 42 | // VX/vx_api.h -- all framework API definitions 43 | // VX/vx_kernels.h -- list of supported kernels in the OpenVX standard 44 | // VX/vx_nodes.h -- easier-to-use functions for the kernels 45 | // VX/vx_vendors.h 46 | // The "VX/vxu.h" defines immediate mode utility functions. 47 | // 48 | // TODO STEP 01:******** 49 | // 1. Uncomment the lines below to include OpenVX header files. 50 | #include 51 | //#include 52 | 53 | //////// 54 | // Useful macros for OpenVX error checking: 55 | // ERROR_CHECK_STATUS - check status is VX_SUCCESS 56 | // ERROR_CHECK_OBJECT - check if the object creation is successful 57 | #define ERROR_CHECK_STATUS( status ) { \ 58 | vx_status status_ = (status); \ 59 | if(status_ != VX_SUCCESS) { \ 60 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 61 | exit(1); \ 62 | } \ 63 | } 64 | 65 | #define ERROR_CHECK_OBJECT( obj ) { \ 66 | vx_status status_ = vxGetStatus((vx_reference)(obj)); \ 67 | if(status_ != VX_SUCCESS) { \ 68 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 69 | exit(1); \ 70 | } \ 71 | } 72 | 73 | ////////******** 74 | // log_callback function implements a mechanism to print log messages 75 | // from OpenVX framework onto console. 76 | // 77 | // TODO STEP 03b (see 03a below):******** 78 | // 1. Find the function signature for the log_callback. 79 | // First, go to definition of vxRegisterLogCallback. 80 | // Find the type of its second argument (it matches vx_log_*_f). 81 | // Follow that type into its definition. 82 | // You'll see the function takes in four arguments, add them here. 83 | // 2. Uncomment the body of the log callback function. 84 | // LOG: [] 85 | // 3. Move to STEP 03c. 86 | // Hint: use the Find functionality, CTRL-F or CMD-F, type 02c, hit ENTER. 87 | void VX_CALLBACK log_callback( /* add the function arguments and their types here */ ) 88 | { 89 | // printf( "LOG: [ status = %d ] %s\n", status, string ); 90 | // fflush( stdout ); 91 | } 92 | 93 | //////// 94 | // main() has all the OpenVX application code for this exercise. 95 | // Command-line usage: 96 | // % solution_exercise1 [|] 97 | // When neither video sequence nor camera device number is specified, 98 | // it defaults to the video sequence in "PETS09-S1-L1-View001.avi". 99 | int main( int argc, char * argv[] ) 100 | { 101 | // Get default video sequence when nothing is specified on command-line and 102 | // instantiate OpenCV GUI module for reading input RGB images and displaying 103 | // the image with OpenVX results. 104 | const char * video_sequence = argv[1]; 105 | CGuiModule gui( video_sequence ); 106 | 107 | // Try to grab the first video frame from the sequence using cv::VideoCapture 108 | // and check if a video frame is available. 109 | if( !gui.Grab() ) 110 | { 111 | printf( "ERROR: input has no video\n" ); 112 | return 1; 113 | } 114 | 115 | //////// 116 | // Set the application configuration parameters. Note that input video 117 | // sequence is an 8-bit RGB image with dimensions given by gui.GetWidth() 118 | // and gui.GetHeight(). The parameters for the Harris corners algorithm are: 119 | // harris_strength_thresh - minimum threshold score to keep a corner 120 | // (computed using the normalized Sobel kernel) 121 | // harris_min_distance - radial L2 distance for non-max suppression 122 | // harris_k_sensitivity - sensitivity threshold k from the Harris-Stephens 123 | // harris_gradient_size - window size for gradient computation 124 | // harris_block_size - block window size used to compute the 125 | // Harris corner score 126 | vx_uint32 width = gui.GetWidth(); 127 | vx_uint32 height = gui.GetHeight(); 128 | vx_float32 harris_strength_thresh = 0.0005f; 129 | vx_float32 harris_min_distance = 5.0f; 130 | vx_float32 harris_k_sensitivity = 0.04f; 131 | vx_int32 harris_gradient_size = 3; 132 | vx_int32 harris_block_size = 3; 133 | 134 | ////////******** 135 | // Create the OpenVX context and make sure the returned context is valid. 136 | // 137 | // TODO STEP 02:******** 138 | // 1. Create an OpenVX context. 139 | // First, set cursor on vx_context type, 140 | // and right-click -> Follow Symbol Under Cursor (or hit F2). 141 | // Read the documentation. See the reference to function vxCreate... 142 | // Start typing the function instead of the NULL in the context assignment below. 143 | // Move cursor over the function name, hit F2 again to read its documentation. 144 | // Finish creating the context. 145 | // 146 | // 2. Use ERROR_CHECK_OBJECT macro to check if context creation was successful. 147 | // Start typing ERROR_CHECK_OBJECT, then with cursor on top, hit F2 to see the definition. 148 | // Finish calling the error check by passing it context as an argument. 149 | vx_context context = NULL; 150 | 151 | ////////******** 152 | // Register the log_callback that you implemented to be able to receive 153 | // any log messages from the OpenVX framework. 154 | // 155 | // TODO STEP 03a:******** 156 | // 1. Uncomment the line below. 157 | // Fill in the first argument for vxRegisterLogCallback to register a log callback function. 158 | // See the documentation (use F2). 159 | // The second argument is a function pointer to log_callback, move next to STEP 03b. 160 | // An easy way to find that is to put cursor on top of log_callback and hit F2. 161 | // vxRegisterLogCallback( /* Fill in this argument */, log_callback, vx_false_e ); 162 | 163 | // TODO STEP 03c:******** 164 | // 1. Uncomment the line below, run and see that you get a log output 165 | // (in the Application Output tab below in the IDE). 166 | // vxAddLogEntry( ( vx_reference ) context, VX_FAILURE, "Hello there!\n" ); 167 | 168 | ////////******** 169 | // Create OpenVX image object for input and OpenVX array object for output. 170 | // 171 | // TODO STEP 04:******** 172 | // 1. See from vx_image type documentation with which function to create an image. 173 | // Start typing the function name to replace NULL below, use autocomplete. 174 | // Look into documentation (F2). 175 | // The first argument should be obvious. 176 | // For the second and third use local variables defined above, one of them is called width. 177 | // For the last one use VX_DF_IMAGE_RGB. 178 | // 2. Use vxCreateArray API to create an array object with keypoint data type. 179 | // See the documentation what should be the second argument (it's a type enum for keypoints). 180 | // 3. Use ERROR_CHECK_OBJECT to check proper creation of objects. 181 | // We gave the one for the array, do a similar check for the image. 182 | vx_image input_rgb_image = NULL; 183 | vx_array output_keypoint_array = NULL; //vxCreateArray( context, /* Fill this in */, 10000 ); 184 | // ERROR_CHECK_OBJECT( output_keypoint_array ); 185 | 186 | ////////******** 187 | // The Harris corner detector algorithm expects input to be an 8-bit image. 188 | // Given that the input is an RGB image, it is best to extract a gray scale 189 | // from RGB image, which requires two steps: 190 | // - perform RGB to IYUV color conversion 191 | // - extract Y channel from IYUV image 192 | // This requires two intermediate OpenVX image objects. Since you're 193 | // going to use immediate mode functions, you need to use vxCreateImage 194 | // to create the image objects, but not the vxCreateVirtualImage API. 195 | // 196 | // TODO STEP 05:******** 197 | // 1. Create an IYUV image and a U8 image (for Y channel) with the same 198 | // dimensions as the input RGB image. The image formats for 199 | // IYUV and U8 images are VX_DF_IMAGE_IYUV and VX_DF_IMAGE_U8. 200 | // 2. Use ERROR_CHECK_OBJECT to check that the objects are valid. 201 | vx_image yuv_image = NULL; 202 | vx_image gray_scale_image = NULL; 203 | 204 | ////////******** 205 | // The immediate mode Harris corner detector function takes the 206 | // strength_thresh, min_distance, and sensitivity parameters as scalar 207 | // data objects. So, you need to create three scalar objects with 208 | // corresponding configuration parameters. 209 | // 210 | // TODO STEP 06:******** 211 | // 1. Create scalar data objects of VX_TYPE_FLOAT32 for strength_thresh, 212 | // min_distance, and sensitivity, with initial values as harris_strength_thresh, 213 | // harris_min_distance, and harris_k_sensitivity. 214 | // The first one is given below. 215 | // 2. Use ERROR_CHECK_OBJECT to check the objects. 216 | vx_scalar strength_thresh = vxCreateScalar( context, VX_TYPE_FLOAT32, &harris_strength_thresh ); 217 | vx_scalar min_distance = NULL; // vxCreateScalar( /* Fill this in */ ); 218 | vx_scalar sensitivity = NULL; // vxCreateScalar( /* Fill this in */ ); 219 | 220 | //////// 221 | // Process the video sequence frame by frame until the end of sequence or aborted. 222 | for( int frame_index = 0; !gui.AbortRequested(); frame_index++ ) 223 | { 224 | ////////******** 225 | // Copy the input RGB frame from OpenCV to OpenVX. 226 | // In order to do this, you need to use vxAccessImagePatch and vxCommitImagePatch APIs. 227 | // See "VX/vx_api.h" for the description of these APIs. 228 | // 229 | // TODO STEP 07:******** 230 | // 1. Specify the coordinates of image patch by declaring the patch 231 | // as a vx_rectangle_t data type. It has four fields, we've given you the first one. 232 | // See for the documentation what are the others. The start values should be zeros, 233 | // end values should be width (for x) and height (for y). 234 | // 2. Specify the memory layout of the OpenCV RGB image buffer by 235 | // declaring the layout as a vx_imagepatch_addressing_t type. 236 | // Remember that you need to specify stride_x and stride_y fields 237 | // of vx_imagepatch_addressing_t for the image buffer layout. 238 | // The stride_x should be 3 and stride_y should be gui.GetStride(). 239 | // We've given you the stride_y, add the stride_x. 240 | // 3. Get the pointer to buffer using gui.GetBuffer() and call 241 | // vxAccessImagePatch for VX_WRITE_ONLY usage mode with a pointer 242 | // to pointer returned by gui.GetBuffer() so COPY mode is used. 243 | // Then immediately call vxCommitImagePatch for the actual copy. 244 | // Use the image patch and memory layout in the above two steps. 245 | // We've given you the access function, please fill in the commit function. 246 | // 4. Compare the return status with VX_SUCCESS to check if access/ 247 | // commit are successful. Or use the ERROR_CHECK_STATUS macro. 248 | vx_rectangle_t cv_rgb_image_region; 249 | cv_rgb_image_region.start_x = 0; 250 | vx_imagepatch_addressing_t cv_rgb_image_layout; 251 | cv_rgb_image_layout.stride_y = gui.GetStride(); 252 | vx_uint8 * cv_rgb_image_buffer = gui.GetBuffer(); 253 | // ERROR_CHECK_STATUS( vxAccessImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 254 | // &cv_rgb_image_layout, ( void ** )&cv_rgb_image_buffer, 255 | // VX_WRITE_ONLY ) ); 256 | // ERROR_CHECK_STATUS( vxCommitImagePatch( /* Fill in the parameters */ ) ); 257 | 258 | ////////******** 259 | // In order to compute Harris corners from input RGB image, first you 260 | // need to convert the input RGB image into a gray scale image, followed by 261 | // running the Harris corner detector function. All the immediate mode 262 | // functions you need are declared in "VX/vxu.h". 263 | // 264 | // TODO STEP 08:******** 265 | // 1. Convert the input RGB image to IYUV image using vxuColorConvert API. 266 | // 2. Extract Y channel from IYUV image into a gray scale image using 267 | // vxuChannelExtract API with VX_CHANNEL_Y as the channel. 268 | // 3. Compute Harris corner detector using vxuHarrisCorners API. 269 | // The num_corners parameter to vxuHarrisCorners is optional, 270 | // you need to set it to NULL in this exercise. 271 | // 4. Use ERROR_CHECK_STATUS for error checking. 272 | // ERROR_CHECK_STATUS( vxuColorConvert( context, input_rgb_image, yuv_image ) ); 273 | // ERROR_CHECK_STATUS( vxuChannelExtract( /* Fill in the parameters */ ) ); 274 | // ERROR_CHECK_STATUS( vxuHarrisCorners( context, gray_scale_image, strength_thresh, 275 | // min_distance, sensitivity, harris_gradient_size, 276 | // harris_block_size, output_keypoint_array, NULL ) ); 277 | 278 | ////////******** 279 | // To mark the keypoints in display, you need to access the output 280 | // keypoint array and draw each item on the output window using 281 | // gui.DrawPoint(). 282 | // 283 | // TODO STEP 09:******** 284 | // 1. OpenVX array object has an attribute that stores the current number of items. 285 | // The name of the attribute is VX_ARRAY_ATTRIBUTE_NUMITEMS and its value is of type vx_size. 286 | // Use vxQueryArray API to get the number of keypoints in the output_keypoint_array 287 | // data object, representing number of corners detected in the input RGB image. 288 | // IMPORTANT: read the number of items into "num_corners" 289 | // because this variable is displayed by code segment below. 290 | // 2. The data items in output keypoint array are of type vx_keypoint_t (see "VX/vx_types.h"). 291 | // To access the array buffer, use vxAccessArrayRange with start index = 0, 292 | // end index = number of items in the array, and usage mode = VX_READ_ONLY. 293 | // Note that the stride returned by this access call is not guaranteed to be sizeof(vx_keypoint_t). 294 | // Also make sure that num_corners is > 0, because vxAccessArrayRange expects an end index > 0. 295 | // We've given you this code. 296 | // 3. For each item in the keypoint buffer, use vxArrayItem to access individual keypoint 297 | // and draw a marker at (x,y) using gui.DrawPoint(). The vx_keypoint_t has x & y data fields. 298 | // 4. Handover the control of output keypoint buffer back to 299 | // OpenVX framework by calling vxCommitArrayRange API. 300 | // 5. Use ERROR_CHECK_STATUS for error checking. 301 | vx_size num_corners = 0; 302 | // ERROR_CHECK_STATUS( vxQueryArray( output_keypoint_array, 303 | // VX_ARRAY_ATTRIBUTE_NUMITEMS, 304 | // &num_corners, 305 | // sizeof( num_corners ) ) ); 306 | if( num_corners > 0 ) 307 | { 308 | vx_size kp_stride; 309 | vx_keypoint_t * kp_buf = NULL; 310 | ERROR_CHECK_STATUS( vxAccessArrayRange( output_keypoint_array, 0, num_corners, 311 | &kp_stride, ( void ** ) &kp_buf, VX_READ_ONLY ) ); 312 | for( vx_size i = 0; i < num_corners; i++ ) 313 | { 314 | // vx_keypoint_t * kp = /* Get the array item */ 315 | // gui.DrawPoint( kp->x, kp->y ); 316 | } 317 | ERROR_CHECK_STATUS( vxCommitArrayRange( output_keypoint_array, 0, num_corners, kp_buf ) ); 318 | } 319 | 320 | //////// 321 | // Display the results and grab the next input RGB frame for the next iteration. 322 | char text[128]; 323 | sprintf( text, "Keyboard ESC/Q-Quit SPACE-Pause [FRAME %d]", frame_index ); 324 | gui.DrawText( 0, 16, text ); 325 | sprintf( text, "Number of Corners: %d", ( int )num_corners ); 326 | gui.DrawText( 0, 36, text ); 327 | gui.Show(); 328 | if( !gui.Grab() ) 329 | { 330 | // Terminate the processing loop if the end of sequence is detected. 331 | gui.WaitForKey(); 332 | break; 333 | } 334 | } 335 | 336 | ////////******** 337 | // Release all the OpenVX objects created in this exercise, and make the context as the last one to release. 338 | // To release an OpenVX object, you need to call vxRelease API which takes a pointer to the object. 339 | // If the release operation is successful, the OpenVX framework will reset the object to NULL. 340 | // 341 | // TODO STEP 10:******** 342 | // 1. Release all the image objects using vxReleaseImage API. 343 | // 2. Release all other objects using vxRelease APIs. 344 | // 3. Use ERROR_CHECK_STATUS for error checking. 345 | // Release three images. 346 | // Release one array. 347 | // Release three Scalars. 348 | // ERROR_CHECK_STATUS( vxReleaseContext( &context ) ); 349 | 350 | return 0; 351 | } 352 | -------------------------------------------------------------------------------- /tutorial_exercises/solution_exercise1/solution_exercise1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | 24 | /*! 25 | * \file solution_exercise1.cpp 26 | * \example solution_exercise1 27 | * \brief Harris corners example. 28 | * Look for TODO keyword in comments for the code snippets that you need to write. 29 | * \author Radhakrishna Giduthuri 30 | * Kari Pulli 31 | */ 32 | 33 | //////// 34 | // Include OpenCV wrapper for image capture and display. 35 | #include "opencv_camera_display.h" 36 | 37 | ////////******** 38 | // The most important top-level OpenVX header files are "VX/vx.h" and "VX/vxu.h". 39 | // The "VX/vx.h" includes all headers needed to support functionality of the 40 | // OpenVX specification, except for immediate mode functions, and it includes: 41 | // VX/vx_types.h -- type definitions required by the OpenVX standard 42 | // VX/vx_api.h -- all framework API definitions 43 | // VX/vx_kernels.h -- list of supported kernels in the OpenVX standard 44 | // VX/vx_nodes.h -- easier-to-use functions for the kernels 45 | // VX/vx_vendors.h 46 | // The "VX/vxu.h" defines immediate mode utility functions. 47 | // 48 | // TODO STEP 01:******** 49 | // 1. Uncomment the lines below to include OpenVX header files. 50 | #include 51 | #include 52 | 53 | //////// 54 | // Useful macros for OpenVX error checking: 55 | // ERROR_CHECK_STATUS - check status is VX_SUCCESS 56 | // ERROR_CHECK_OBJECT - check if the object creation is successful 57 | #define ERROR_CHECK_STATUS( status ) { \ 58 | vx_status status_ = (status); \ 59 | if(status_ != VX_SUCCESS) { \ 60 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 61 | exit(1); \ 62 | } \ 63 | } 64 | 65 | #define ERROR_CHECK_OBJECT( obj ) { \ 66 | vx_status status_ = vxGetStatus((vx_reference)(obj)); \ 67 | if(status_ != VX_SUCCESS) { \ 68 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 69 | exit(1); \ 70 | } \ 71 | } 72 | 73 | ////////******** 74 | // log_callback function implements a mechanism to print log messages 75 | // from OpenVX framework onto console. 76 | // 77 | // TODO STEP 03b (see 03a below):******** 78 | // 1. Find the function signature for the log_callback. 79 | // First, go to definition of vxRegisterLogCallback. 80 | // Find the type of its second argument (it matches vx_log_*_f). 81 | // Follow that type into its definition. 82 | // You'll see the function takes in four arguments, add them here. 83 | // 2. Uncomment the body of the log callback function. 84 | // LOG: [] 85 | // 3. Move to STEP 03c. 86 | // Hint: use the Find functionality, CTRL-F or CMD-F, type 02c, hit ENTER. 87 | void VX_CALLBACK log_callback( vx_context context, 88 | vx_reference ref, 89 | vx_status status, 90 | const vx_char string[] ) 91 | { 92 | printf( "LOG: [ status = %d ] %s\n", status, string ); 93 | fflush( stdout ); 94 | } 95 | 96 | //////// 97 | // main() has all the OpenVX application code for this exercise. 98 | // Command-line usage: 99 | // % solution_exercise1 [|] 100 | // When neither video sequence nor camera device number is specified, 101 | // it defaults to the video sequence in "PETS09-S1-L1-View001.avi". 102 | int main( int argc, char * argv[] ) 103 | { 104 | // Get default video sequence when nothing is specified on command-line and 105 | // instantiate OpenCV GUI module for reading input RGB images and displaying 106 | // the image with OpenVX results. 107 | const char * video_sequence = argv[1]; 108 | CGuiModule gui( video_sequence ); 109 | 110 | // Try to grab the first video frame from the sequence using cv::VideoCapture 111 | // and check if a video frame is available. 112 | if( !gui.Grab() ) 113 | { 114 | printf( "ERROR: input has no video\n" ); 115 | return 1; 116 | } 117 | 118 | //////// 119 | // Set the application configuration parameters. Note that input video 120 | // sequence is an 8-bit RGB image with dimensions given by gui.GetWidth() 121 | // and gui.GetHeight(). The parameters for the Harris corners algorithm are: 122 | // harris_strength_thresh - minimum threshold score to keep a corner 123 | // (computed using the normalized Sobel kernel) 124 | // harris_min_distance - radial L2 distance for non-max suppression 125 | // harris_k_sensitivity - sensitivity threshold k from the Harris-Stephens 126 | // harris_gradient_size - window size for gradient computation 127 | // harris_block_size - block window size used to compute the 128 | // Harris corner score 129 | vx_uint32 width = gui.GetWidth(); 130 | vx_uint32 height = gui.GetHeight(); 131 | vx_float32 harris_strength_thresh = 0.0005f; 132 | vx_float32 harris_min_distance = 5.0f; 133 | vx_float32 harris_k_sensitivity = 0.04f; 134 | vx_int32 harris_gradient_size = 3; 135 | vx_int32 harris_block_size = 3; 136 | 137 | ////////******** 138 | // Create the OpenVX context and make sure the returned context is valid. 139 | // 140 | // TODO STEP 02:******** 141 | // 1. Create an OpenVX context. 142 | // First, set cursor on vx_context type, 143 | // and right-click -> Follow Symbol Under Cursor (or hit F2). 144 | // Read the documentation. See the reference to function vxCreate... 145 | // Start typing the function instead of the NULL in the context assignment below. 146 | // Move cursor over the function name, hit F2 again to read its documentation. 147 | // Finish creating the context. 148 | // 149 | // 2. Use ERROR_CHECK_OBJECT macro to check if context creation was successful. 150 | // Start typing ERROR_CHECK_OBJECT, then with cursor on top, hit F2 to see the definition. 151 | // Finish calling the error check by passing it context as an argument. 152 | vx_context context = vxCreateContext(); 153 | ERROR_CHECK_OBJECT( context ); 154 | 155 | ////////******** 156 | // Register the log_callback that you implemented to be able to receive 157 | // any log messages from the OpenVX framework. 158 | // 159 | // TODO STEP 03a:******** 160 | // 1. Uncomment the line below. 161 | // Fill in the first argument for vxRegisterLogCallback to register a log callback function. 162 | // See the documentation (use F2). 163 | // The second argument is a function pointer to log_callback, move next to STEP 03b. 164 | // An easy way to find that is to put cursor on top of log_callback and hit F2. 165 | vxRegisterLogCallback( context, log_callback, vx_false_e ); 166 | 167 | // TODO STEP 03c:******** 168 | // 1. Uncomment the line below, run and see that you get a log output 169 | // (in the Application Output tab below in the IDE). 170 | vxAddLogEntry( ( vx_reference ) context, VX_FAILURE, "Hello there!\n" ); 171 | 172 | ////////******** 173 | // Create OpenVX image object for input and OpenVX array object for output. 174 | // 175 | // TODO STEP 04:******** 176 | // 1. See from vx_image type documentation with which function to create an image. 177 | // Start typing the function name to replace NULL below, use autocomplete. 178 | // Look into documentation (F2). 179 | // The first argument should be obvious. 180 | // For the second and third use local variables defined above, one of them is called width. 181 | // For the last one use VX_DF_IMAGE_RGB. 182 | // 2. Use vxCreateArray API to create an array object with keypoint data type. 183 | // See the documentation what should be the second argument (it's a type enum for keypoints). 184 | // 3. Use ERROR_CHECK_OBJECT to check proper creation of objects. 185 | // We gave the one for the array, do a similar check for the image. 186 | vx_image input_rgb_image = vxCreateImage( context, width, height, VX_DF_IMAGE_RGB ); 187 | vx_array output_keypoint_array = vxCreateArray( context, VX_TYPE_KEYPOINT, 10000 ); 188 | ERROR_CHECK_OBJECT( input_rgb_image ); 189 | ERROR_CHECK_OBJECT( output_keypoint_array ); 190 | 191 | ////////******** 192 | // The Harris corner detector algorithm expects input to be an 8-bit image. 193 | // Given that the input is an RGB image, it is best to extract a gray scale 194 | // from RGB image, which requires two steps: 195 | // - perform RGB to IYUV color conversion 196 | // - extract Y channel from IYUV image 197 | // This requires two intermediate OpenVX image objects. Since you're 198 | // going to use immediate mode functions, you need to use vxCreateImage 199 | // to create the image objects, but not the vxCreateVirtualImage API. 200 | // 201 | // TODO STEP 05:******** 202 | // 1. Create an IYUV image and a U8 image (for Y channel) with the same 203 | // dimensions as the input RGB image. The image formats for 204 | // IYUV and U8 images are VX_DF_IMAGE_IYUV and VX_DF_IMAGE_U8. 205 | // 2. Use ERROR_CHECK_OBJECT to check that the objects are valid. 206 | vx_image yuv_image = vxCreateImage( context, width, height, VX_DF_IMAGE_IYUV ); 207 | vx_image gray_scale_image = vxCreateImage( context, width, height, VX_DF_IMAGE_U8 ); 208 | ERROR_CHECK_OBJECT( yuv_image ); 209 | ERROR_CHECK_OBJECT( gray_scale_image ); 210 | 211 | ////////******** 212 | // The immediate mode Harris corner detector function takes the 213 | // strength_thresh, min_distance, and sensitivity parameters as scalar 214 | // data objects. So, you need to create three scalar objects with 215 | // corresponding configuration parameters. 216 | // 217 | // TODO STEP 06:******** 218 | // 1. Create scalar data objects of VX_TYPE_FLOAT32 for strength_thresh, 219 | // min_distance, and sensitivity, with initial values as harris_strength_thresh, 220 | // harris_min_distance, and harris_k_sensitivity. 221 | // The first one is given below. 222 | // 2. Use ERROR_CHECK_OBJECT to check the objects. 223 | vx_scalar strength_thresh = vxCreateScalar( context, VX_TYPE_FLOAT32, &harris_strength_thresh ); 224 | vx_scalar min_distance = vxCreateScalar( context, VX_TYPE_FLOAT32, &harris_min_distance ); 225 | vx_scalar sensitivity = vxCreateScalar( context, VX_TYPE_FLOAT32, &harris_k_sensitivity ); 226 | ERROR_CHECK_OBJECT( strength_thresh ); 227 | ERROR_CHECK_OBJECT( min_distance ); 228 | ERROR_CHECK_OBJECT( sensitivity ); 229 | 230 | //////// 231 | // Process the video sequence frame by frame until the end of sequence or aborted. 232 | for( int frame_index = 0; !gui.AbortRequested(); frame_index++ ) 233 | { 234 | ////////******** 235 | // Copy the input RGB frame from OpenCV to OpenVX. 236 | // In order to do this, you need to use vxAccessImagePatch and vxCommitImagePatch APIs. 237 | // See "VX/vx_api.h" for the description of these APIs. 238 | // 239 | // TODO STEP 07:******** 240 | // 1. Specify the coordinates of image patch by declaring the patch 241 | // as a vx_rectangle_t data type. It has four fields, we've given you the first one. 242 | // See for the documentation what are the others. The start values should be zeros, 243 | // end values should be width (for x) and height (for y). 244 | // 2. Specify the memory layout of the OpenCV RGB image buffer by 245 | // declaring the layout as a vx_imagepatch_addressing_t type. 246 | // Remember that you need to specify stride_x and stride_y fields 247 | // of vx_imagepatch_addressing_t for the image buffer layout. 248 | // The stride_x should be 3 and stride_y should be gui.GetStride(). 249 | // We've given you the stride_y, add the stride_x. 250 | // 3. Get the pointer to buffer using gui.GetBuffer() and call 251 | // vxAccessImagePatch for VX_WRITE_ONLY usage mode with a pointer 252 | // to pointer returned by gui.GetBuffer() so COPY mode is used. 253 | // Then immediately call vxCommitImagePatch for the actual copy. 254 | // Use the image patch and memory layout in the above two steps. 255 | // We've given you the access function, please fill in the commit function. 256 | // 4. Compare the return status with VX_SUCCESS to check if access/ 257 | // commit are successful. Or use the ERROR_CHECK_STATUS macro. 258 | vx_rectangle_t cv_rgb_image_region; 259 | cv_rgb_image_region.start_x = 0; 260 | cv_rgb_image_region.start_y = 0; 261 | cv_rgb_image_region.end_x = width; 262 | cv_rgb_image_region.end_y = height; 263 | vx_imagepatch_addressing_t cv_rgb_image_layout; 264 | cv_rgb_image_layout.stride_x = 3; 265 | cv_rgb_image_layout.stride_y = gui.GetStride(); 266 | vx_uint8 * cv_rgb_image_buffer = gui.GetBuffer(); 267 | ERROR_CHECK_STATUS( vxAccessImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 268 | &cv_rgb_image_layout, ( void ** )&cv_rgb_image_buffer, 269 | VX_WRITE_ONLY ) ); 270 | ERROR_CHECK_STATUS( vxCommitImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 271 | &cv_rgb_image_layout, cv_rgb_image_buffer ) ); 272 | 273 | ////////******** 274 | // In order to compute Harris corners from input RGB image, first you 275 | // need to convert the input RGB image into a gray scale image, followed by 276 | // running the Harris corner detector function. All the immediate mode 277 | // functions you need are declared in "VX/vxu.h". 278 | // 279 | // TODO STEP 08:******** 280 | // 1. Convert the input RGB image to IYUV image using vxuColorConvert API. 281 | // 2. Extract Y channel from IYUV image into a gray scale image using 282 | // vxuChannelExtract API with VX_CHANNEL_Y as the channel. 283 | // 3. Compute Harris corner detector using vxuHarrisCorners API. 284 | // The num_corners parameter to vxuHarrisCorners is optional, 285 | // you need to set it to NULL in this exercise. 286 | // 4. Use ERROR_CHECK_STATUS for error checking. 287 | ERROR_CHECK_STATUS( vxuColorConvert( context, input_rgb_image, yuv_image ) ); 288 | ERROR_CHECK_STATUS( vxuChannelExtract( context, yuv_image, VX_CHANNEL_Y, gray_scale_image ) ); 289 | ERROR_CHECK_STATUS( vxuHarrisCorners( context, gray_scale_image, strength_thresh, 290 | min_distance, sensitivity, harris_gradient_size, 291 | harris_block_size, output_keypoint_array, NULL ) ); 292 | 293 | ////////******** 294 | // To mark the keypoints in display, you need to access the output 295 | // keypoint array and draw each item on the output window using 296 | // gui.DrawPoint(). 297 | // 298 | // TODO STEP 09:******** 299 | // 1. OpenVX array object has an attribute that stores the current number of items. 300 | // The name of the attribute is VX_ARRAY_ATTRIBUTE_NUMITEMS and its value is of type vx_size. 301 | // Use vxQueryArray API to get the number of keypoints in the output_keypoint_array 302 | // data object, representing number of corners detected in the input RGB image. 303 | // IMPORTANT: read the number of items into "num_corners" 304 | // because this variable is displayed by code segment below. 305 | // 2. The data items in output keypoint array are of type vx_keypoint_t (see "VX/vx_types.h"). 306 | // To access the array buffer, use vxAccessArrayRange with start index = 0, 307 | // end index = number of items in the array, and usage mode = VX_READ_ONLY. 308 | // Note that the stride returned by this access call is not guaranteed to be sizeof(vx_keypoint_t). 309 | // Also make sure that num_corners is > 0, because vxAccessArrayRange expects an end index > 0. 310 | // We've given you this code. 311 | // 3. For each item in the keypoint buffer, use vxArrayItem to access individual keypoint 312 | // and draw a marker at (x,y) using gui.DrawPoint(). The vx_keypoint_t has x & y data fields. 313 | // 4. Handover the control of output keypoint buffer back to 314 | // OpenVX framework by calling vxCommitArrayRange API. 315 | // 5. Use ERROR_CHECK_STATUS for error checking. 316 | vx_size num_corners = 0; 317 | ERROR_CHECK_STATUS( vxQueryArray( output_keypoint_array, 318 | VX_ARRAY_ATTRIBUTE_NUMITEMS, 319 | &num_corners, 320 | sizeof( num_corners ) ) ); 321 | if( num_corners > 0 ) 322 | { 323 | vx_size kp_stride; 324 | vx_keypoint_t * kp_buf = NULL; 325 | ERROR_CHECK_STATUS( vxAccessArrayRange( output_keypoint_array, 0, num_corners, 326 | &kp_stride, ( void ** ) &kp_buf, VX_READ_ONLY ) ); 327 | for( vx_size i = 0; i < num_corners; i++ ) 328 | { 329 | vx_keypoint_t * kp = &vxArrayItem( vx_keypoint_t, kp_buf, i, kp_stride ); 330 | gui.DrawPoint( kp->x, kp->y ); 331 | } 332 | ERROR_CHECK_STATUS( vxCommitArrayRange( output_keypoint_array, 0, num_corners, kp_buf ) ); 333 | } 334 | 335 | //////// 336 | // Display the results and grab the next input RGB frame for the next iteration. 337 | char text[128]; 338 | sprintf( text, "Keyboard ESC/Q-Quit SPACE-Pause [FRAME %d]", frame_index ); 339 | gui.DrawText( 0, 16, text ); 340 | sprintf( text, "Number of Corners: %d", ( int )num_corners ); 341 | gui.DrawText( 0, 36, text ); 342 | gui.Show(); 343 | if( !gui.Grab() ) 344 | { 345 | // Terminate the processing loop if the end of sequence is detected. 346 | gui.WaitForKey(); 347 | break; 348 | } 349 | } 350 | 351 | ////////******** 352 | // Release all the OpenVX objects created in this exercise, and make the context as the last one to release. 353 | // To release an OpenVX object, you need to call vxRelease API which takes a pointer to the object. 354 | // If the release operation is successful, the OpenVX framework will reset the object to NULL. 355 | // 356 | // TODO STEP 10:******** 357 | // 1. Release all the image objects using vxReleaseImage API. 358 | // 2. Release all other objects using vxRelease APIs. 359 | // 3. Use ERROR_CHECK_STATUS for error checking. 360 | // Release three images. 361 | // Release one array. 362 | // Release three Scalars. 363 | ERROR_CHECK_STATUS( vxReleaseImage( &input_rgb_image ) ); 364 | ERROR_CHECK_STATUS( vxReleaseImage( &yuv_image ) ); 365 | ERROR_CHECK_STATUS( vxReleaseImage( &gray_scale_image ) ); 366 | ERROR_CHECK_STATUS( vxReleaseArray( &output_keypoint_array ) ); 367 | ERROR_CHECK_STATUS( vxReleaseScalar( &strength_thresh ) ); 368 | ERROR_CHECK_STATUS( vxReleaseScalar( &min_distance ) ); 369 | ERROR_CHECK_STATUS( vxReleaseScalar( &sensitivity ) ); 370 | ERROR_CHECK_STATUS( vxReleaseContext( &context ) ); 371 | 372 | return 0; 373 | } 374 | -------------------------------------------------------------------------------- /tutorial_exercises/solution_exercise3/solution_exercise3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | 24 | /*! 25 | * \file solution_exercise3.cpp 26 | * \example solution_exercise3 27 | * \brief Access to OpenCV medianBlur function as an OpenVX user kernel. 28 | * Look for TODO keyword in comments for the code snippets that you need to write. 29 | * \author Radhakrishna Giduthuri 30 | */ 31 | 32 | //////// 33 | // Include OpenCV wrapper for image capture and display. 34 | #include "opencv_camera_display.h" 35 | 36 | //////// 37 | // The most important top-level OpenVX header files are "VX/vx.h" and "VX/vxu.h". 38 | // The "VX/vx.h" includes all headers needed to support functionality of the 39 | // OpenVX specification, except for immediate mode functions, and it includes: 40 | // VX/vx_types.h -- type definitions required by the OpenVX standard 41 | // VX/vx_api.h -- all framework API definitions 42 | // VX/vx_kernels.h -- list of supported kernels in the OpenVX standard 43 | // VX/vx_nodes.h -- easier-to-use functions for the kernels 44 | // VX/vx_vendors.h 45 | // The "VX/vxu.h" defines the immediate mode utility functions (not needed here). 46 | #include 47 | 48 | 49 | //////// 50 | // Useful macros for OpenVX error checking: 51 | // ERROR_CHECK_STATUS - check status is VX_SUCCESS 52 | // ERROR_CHECK_OBJECT - check if the object creation is successful 53 | #define ERROR_CHECK_STATUS( status ) { \ 54 | vx_status status_ = (status); \ 55 | if(status_ != VX_SUCCESS) { \ 56 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 57 | exit(1); \ 58 | } \ 59 | } 60 | 61 | #define ERROR_CHECK_OBJECT( obj ) { \ 62 | vx_status status_ = vxGetStatus((vx_reference)(obj)); \ 63 | if(status_ != VX_SUCCESS) { \ 64 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 65 | exit(1); \ 66 | } \ 67 | } 68 | 69 | //////// 70 | // User kernel should have a unique enumerations and name for user kernel: 71 | // USER_LIBRARY_EXAMPLE - library ID for user kernels in this example 72 | // USER_KERNEL_MEDIAN_BLUR - enumeration for "app.userkernels.median_blur" kernel 73 | // 74 | // TODO:******** 75 | // 1. Define USER_LIBRARY_EXAMPLE 76 | // 2. Define USER_KERNEL_MEDIAN_BLUR using VX_KERNEL_BASE() macro 77 | enum user_library_e 78 | { 79 | USER_LIBRARY_EXAMPLE = 1, 80 | }; 81 | enum user_kernel_e 82 | { 83 | USER_KERNEL_MEDIAN_BLUR = VX_KERNEL_BASE( VX_ID_DEFAULT, USER_LIBRARY_EXAMPLE ) + 0x001, 84 | }; 85 | 86 | //////// 87 | // The node creation interface for the "app.userkernels.median_blur" kernel. 88 | // This user kernel example expects parameters in the following order: 89 | // parameter #0 -- input image of format VX_DF_IMAGE_U8 90 | // parameter #1 -- output image of format VX_DF_IMAGE_U8 91 | // parameter #2 -- scalar ksize of type VX_TYPE_INT32 92 | // 93 | // TODO:******** 94 | // 1. Use vxGetKernelByEnum API to get a kernel object from USER_KERNEL_MEDIAN_BLUR. 95 | // Note that you need to use vxGetContext API to get the context from a graph object. 96 | // 2. Use vxCreateGenericNode API to create a node from the kernel object. 97 | // 3. Create scalar objects for ksize parameter. 98 | // 4. Use vxSetParameterByIndex API to set node arguments. 99 | // 5. Release the kernel and scalar objects that are not needed any more. 100 | // 6. Use ERROR_CHECK_OBJECT and ERROR_CHECK_STATUS macros for error detection. 101 | vx_node userMedianBlurNode( vx_graph graph, 102 | vx_image input, 103 | vx_image output, 104 | vx_int32 ksize ) 105 | { 106 | vx_context context = vxGetContext( ( vx_reference ) graph ); 107 | vx_kernel kernel = vxGetKernelByEnum( context, USER_KERNEL_MEDIAN_BLUR ); 108 | ERROR_CHECK_OBJECT( kernel ); 109 | vx_node node = vxCreateGenericNode( graph, kernel ); 110 | ERROR_CHECK_OBJECT( node ); 111 | 112 | vx_scalar s_ksize = vxCreateScalar( context, VX_TYPE_INT32, &ksize ); 113 | ERROR_CHECK_OBJECT( s_ksize ); 114 | 115 | ERROR_CHECK_STATUS( vxSetParameterByIndex( node, 0, ( vx_reference ) input ) ); 116 | ERROR_CHECK_STATUS( vxSetParameterByIndex( node, 1, ( vx_reference ) output ) ); 117 | ERROR_CHECK_STATUS( vxSetParameterByIndex( node, 2, ( vx_reference ) s_ksize ) ); 118 | 119 | ERROR_CHECK_STATUS( vxReleaseScalar( &s_ksize ) ); 120 | ERROR_CHECK_STATUS( vxReleaseKernel( &kernel ) ); 121 | 122 | return node; 123 | } 124 | 125 | //////// 126 | // The user kernel input validator callback should check to make sure that all the input 127 | // parameters have correct data types. This user kernel example expects the inputs 128 | // to be valid in the following order: 129 | // parameter #0 -- input image of format VX_DF_IMAGE_U8 130 | // parameter #2 -- scalar ksize of type VX_TYPE_INT32 131 | // TODO:******** 132 | // 1. Use vxGetParameterByIndex API to get access to the requested parameter. 133 | // 2. Use vxQueryParameter API with VX_PARAMETER_ATTRIBUTE_REF to access the input object. 134 | // 3. If the index is 0, check to make sure that image format is VX_DF_FORMAT_U8. 135 | // 4. If the index is 2, check to make sure that the scalar type is VX_TYPE_INT32. 136 | vx_status VX_CALLBACK median_blur_input_validator( vx_node node, 137 | vx_uint32 index ) 138 | { 139 | vx_reference ref = NULL; 140 | vx_parameter parameter = vxGetParameterByIndex( node, index ); 141 | ERROR_CHECK_STATUS( vxQueryParameter( parameter, VX_PARAMETER_ATTRIBUTE_REF, &ref, sizeof( ref ) ) ); 142 | ERROR_CHECK_STATUS( vxReleaseParameter( ¶meter ) ); 143 | ERROR_CHECK_OBJECT( ref ); 144 | 145 | if( index == 0 ) 146 | { 147 | // parameter #0 -- input image of format VX_DF_IMAGE_U8 148 | vx_df_image format = VX_DF_IMAGE_VIRT; 149 | ERROR_CHECK_STATUS( vxQueryImage( ( vx_image )ref, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof( format ) ) ); 150 | ERROR_CHECK_STATUS( vxReleaseImage( ( vx_image * )&ref ) ); 151 | if( format != VX_DF_IMAGE_U8 ) 152 | { 153 | return VX_ERROR_INVALID_FORMAT; 154 | } 155 | } 156 | else if( index == 2 ) 157 | { 158 | // parameters #2 -- scalar of type VX_TYPE_INT32 159 | vx_enum type = VX_TYPE_INVALID; 160 | ERROR_CHECK_STATUS( vxQueryScalar( ( vx_scalar )ref, VX_SCALAR_ATTRIBUTE_TYPE, &type, sizeof( type ) ) ); 161 | ERROR_CHECK_STATUS( vxReleaseScalar( ( vx_scalar * )&ref ) ); 162 | if( type != VX_TYPE_INT32 ) 163 | { 164 | return VX_ERROR_INVALID_TYPE; 165 | } 166 | } 167 | else 168 | { 169 | // invalid input parameter 170 | return VX_ERROR_INVALID_PARAMETERS; 171 | } 172 | 173 | return VX_SUCCESS; 174 | } 175 | 176 | //////// 177 | // User kernel output validator callback should set the output parameter meta data. 178 | // This user kernel example has only one output parameter with the same dimensions as parameter #0. 179 | // parameter #1 -- output image of format VX_DF_IMAGE_U8 with the same dimensions as input 180 | // 181 | // TODO:******** 182 | // 1. Get the input image dimensions from parameter #0. 183 | // 2. Set the output image meta data to have the same dimensions as input and VX_DF_FORMAT_U8. 184 | vx_status VX_CALLBACK median_blur_output_validator( vx_node node, 185 | vx_uint32 index, 186 | vx_meta_format meta ) 187 | { 188 | if( index == 1 ) 189 | { 190 | vx_uint32 width = 0, height = 0; 191 | vx_image input = NULL; 192 | vx_parameter parameter = vxGetParameterByIndex( node, 0 ); 193 | ERROR_CHECK_STATUS( vxQueryParameter( parameter, VX_PARAMETER_ATTRIBUTE_REF, &input, sizeof( input ) ) ); 194 | ERROR_CHECK_STATUS( vxReleaseParameter( ¶meter ) ); 195 | ERROR_CHECK_OBJECT( input ); 196 | ERROR_CHECK_STATUS( vxQueryImage( input, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof( width ) ) ); 197 | ERROR_CHECK_STATUS( vxQueryImage( input, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof( height ) ) ); 198 | ERROR_CHECK_STATUS( vxReleaseImage( &input ) ); 199 | 200 | vx_df_image format = VX_DF_IMAGE_U8; 201 | ERROR_CHECK_STATUS( vxSetMetaFormatAttribute( meta, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof( format ) ) ); 202 | ERROR_CHECK_STATUS( vxSetMetaFormatAttribute( meta, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof( width ) ) ); 203 | ERROR_CHECK_STATUS( vxSetMetaFormatAttribute( meta, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof( height ) ) ); 204 | } 205 | else 206 | { 207 | // invalid input parameter 208 | return VX_ERROR_INVALID_PARAMETERS; 209 | } 210 | 211 | return VX_SUCCESS; 212 | } 213 | 214 | //////// 215 | // User kernel host side function gets called to execute the user kernel node. 216 | // You need to wrap the OpenVX objects into OpenCV Mat objects and call cv::medianBlur. 217 | // 218 | // TODO:******** 219 | // 1. Get ksize value from scalar object in refs[2]. 220 | // 2. Access input and output image patches and wrap it in a cv::Mat object. 221 | // Use the cv::Mat mat(width, height, CV_U8, ptr, addr.stride_y) to wrap 222 | // an OpenVX image plane buffer in an OpenCV mat object. Note that 223 | // you need to access input image with VX_READ_ONLY and output image 224 | // with VX_WRITE_ONLY. 225 | // 3. Just call cv::medianBlur(input, output, ksize) 226 | // 4. Use vxCommitImagePatch API to give the image buffers control back to OpenVX framework 227 | vx_status VX_CALLBACK median_blur_host_side_function( vx_node node, const vx_reference * refs, vx_uint32 num ) 228 | { 229 | vx_image input = ( vx_image ) refs[0]; 230 | vx_image output = ( vx_image ) refs[1]; 231 | vx_scalar s_ksize = ( vx_scalar )refs[2]; 232 | 233 | vx_int32 ksize = 0; 234 | ERROR_CHECK_STATUS( vxReadScalarValue( s_ksize, &ksize ) ); 235 | 236 | vx_uint32 width = 0, height = 0; 237 | ERROR_CHECK_STATUS( vxQueryImage( input, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof( width ) ) ); 238 | ERROR_CHECK_STATUS( vxQueryImage( input, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof( height ) ) ); 239 | 240 | vx_rectangle_t rect = { 0, 0, width, height }; 241 | vx_imagepatch_addressing_t addr_input = { 0 }, addr_output = { 0 }; 242 | void * ptr_input = NULL, * ptr_output = NULL; 243 | ERROR_CHECK_STATUS( vxAccessImagePatch( input, &rect, 0, &addr_input, &ptr_input, VX_READ_ONLY ) ); 244 | ERROR_CHECK_STATUS( vxAccessImagePatch( output, &rect, 0, &addr_output, &ptr_output, VX_WRITE_ONLY ) ); 245 | 246 | cv::Mat mat_input( height, width, CV_8U, ptr_input, addr_input .stride_y ); 247 | cv::Mat mat_output( height, width, CV_8U, ptr_output, addr_output.stride_y ); 248 | cv::medianBlur( mat_input, mat_output, ksize ); 249 | 250 | ERROR_CHECK_STATUS( vxCommitImagePatch( input, &rect, 0, &addr_input, ptr_input ) ); 251 | ERROR_CHECK_STATUS( vxCommitImagePatch( output, &rect, 0, &addr_output, ptr_output ) ); 252 | 253 | return VX_SUCCESS; 254 | } 255 | 256 | //////// 257 | // User kernels needs to be registered with every OpenVX context before use in a graph. 258 | // 259 | // TODO:******** 260 | // 1. Use vxAddKernel API to register "app.userkernels.median_blur" with 261 | // kernel enumeration = USER_KERNEL_MEDIAN_BLUR, numParams = 3, and 262 | // all of the user kernel callback functions you implemented above. 263 | // 2. Use vxAddParameterToKernel API to specify direction, data_type, and 264 | // state of all 3 parameters to the kernel. Look into the comments of 265 | // userMedianBlurNode function (above) to details about the order of 266 | // kernel parameters and their types. 267 | // 3. Use vxFinalizeKernel API to make the kernel ready to use in a graph. 268 | // Note that the kernel object is still valid after this call. 269 | // So you need to call vxReleaseKernel before returning from this function. 270 | vx_status registerUserKernel( vx_context context ) 271 | { 272 | vx_kernel kernel = vxAddKernel( context, 273 | "app.userkernels.median_blur", 274 | USER_KERNEL_MEDIAN_BLUR, 275 | median_blur_host_side_function, 276 | 3, // numParams 277 | median_blur_input_validator, 278 | median_blur_output_validator, 279 | NULL, 280 | NULL ); 281 | ERROR_CHECK_OBJECT( kernel ); 282 | 283 | ERROR_CHECK_STATUS( vxAddParameterToKernel( kernel, 0, VX_INPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED ) ); // input 284 | ERROR_CHECK_STATUS( vxAddParameterToKernel( kernel, 1, VX_OUTPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED ) ); // output 285 | ERROR_CHECK_STATUS( vxAddParameterToKernel( kernel, 2, VX_INPUT, VX_TYPE_SCALAR, VX_PARAMETER_STATE_REQUIRED ) ); // ksize 286 | ERROR_CHECK_STATUS( vxFinalizeKernel( kernel ) ); 287 | ERROR_CHECK_STATUS( vxReleaseKernel( &kernel ) ); 288 | 289 | vxAddLogEntry( ( vx_reference ) context, VX_SUCCESS, "OK: registered user kernel app.userkernels.median_blur\n" ); 290 | return VX_SUCCESS; 291 | } 292 | 293 | //////// 294 | // log_callback function implements a mechanism to print log messages 295 | // from the OpenVX framework onto console. 296 | void VX_CALLBACK log_callback( vx_context context, 297 | vx_reference ref, 298 | vx_status status, 299 | const vx_char string[] ) 300 | { 301 | printf( "LOG: [ status = %d ] %s\n", status, string ); 302 | fflush( stdout ); 303 | } 304 | 305 | //////// 306 | // main() has all the OpenVX application code for this exercise. 307 | // Command-line usage: 308 | // % solution_exercise3 [|] 309 | // When neither video sequence nor camera device number is specified, 310 | // it defaults to the video sequence in "PETS09-S1-L1-View001.avi". 311 | int main( int argc, char * argv[] ) 312 | { 313 | // Get default video sequence when nothing is specified on command-line and 314 | // instantiate OpenCV GUI module for reading input RGB images and displaying 315 | // the image with OpenVX results 316 | const char * video_sequence = argv[1]; 317 | CGuiModule gui( video_sequence ); 318 | 319 | // Try grab first video frame from the sequence using cv::VideoCapture 320 | // and check if video frame is available 321 | if( !gui.Grab() ) 322 | { 323 | printf( "ERROR: input has no video\n" ); 324 | return 1; 325 | } 326 | 327 | //////// 328 | // Set the application configuration parameters. Note that input video 329 | // sequence is an 8-bit RGB image with dimensions given by gui.GetWidth() 330 | // and gui.GetHeight(). The parameters for the median filter are: 331 | // ksize - median filter kernel size 332 | vx_uint32 width = gui.GetWidth(); 333 | vx_uint32 height = gui.GetHeight(); 334 | vx_int32 ksize = 7; 335 | 336 | //////// 337 | // Create the OpenVX context and make sure returned context is valid and 338 | // register the log_callback to receive messages from OpenVX framework. 339 | vx_context context = vxCreateContext(); 340 | ERROR_CHECK_OBJECT( context ); 341 | vxRegisterLogCallback( context, log_callback, vx_false_e ); 342 | 343 | //////// 344 | // Register user kernels with the context. 345 | // 346 | // TODO:******** 347 | // 1. Register user kernel with context by calling your implementation of "registerUserKernel()". 348 | ERROR_CHECK_STATUS( registerUserKernel( context ) ); 349 | 350 | //////// 351 | // Create OpenVX image object for input RGB image and median filter output image. 352 | vx_image input_rgb_image = vxCreateImage( context, width, height, VX_DF_IMAGE_RGB ); 353 | vx_image output_filtered_image = vxCreateImage( context, width, height, VX_DF_IMAGE_U8 ); 354 | ERROR_CHECK_OBJECT( input_rgb_image ); 355 | ERROR_CHECK_OBJECT( output_filtered_image ); 356 | 357 | ////////******** 358 | // Create graph object and intermediate image objects. 359 | // Given that input is an RGB image, it is best to extract a gray image 360 | // from RGB image, which requires two steps: 361 | // - perform RGB to IYUV color conversion 362 | // - extract Y channel from IYUV image 363 | // This requires two intermediate OpenVX image objects. Since you don't 364 | // need to access these objects from the application, they can be virtual 365 | // objects that can be created using the vxCreateVirtualImage API. 366 | vx_graph graph = vxCreateGraph( context ); 367 | ERROR_CHECK_OBJECT( graph ); 368 | vx_image yuv_image = vxCreateVirtualImage( graph, width, height, VX_DF_IMAGE_IYUV ); 369 | vx_image luma_image = vxCreateVirtualImage( graph, width, height, VX_DF_IMAGE_U8 ); 370 | ERROR_CHECK_OBJECT( yuv_image ); 371 | ERROR_CHECK_OBJECT( luma_image ); 372 | 373 | ////////******** 374 | // Now all the objects have been created for building the graph 375 | // that converts RGB into luma image and then performs median blur 376 | // using user kernel USER_KERNEL_MEDIAN_BLUR. 377 | // Then use vxVerifyGraph API for initialization. 378 | // 379 | // TODO:******** 380 | // 1. Use userMedianBlurNode function to add "median_blur" node. 381 | vx_node nodes[] = 382 | { 383 | vxColorConvertNode( graph, input_rgb_image, yuv_image ), 384 | vxChannelExtractNode( graph, yuv_image, VX_CHANNEL_Y, luma_image ), 385 | userMedianBlurNode( graph, luma_image, output_filtered_image, ksize ) 386 | }; 387 | for( vx_size i = 0; i < sizeof( nodes ) / sizeof( nodes[0] ); i++ ) 388 | { 389 | ERROR_CHECK_OBJECT( nodes[i] ); 390 | ERROR_CHECK_STATUS( vxReleaseNode( &nodes[i] ) ); 391 | } 392 | ERROR_CHECK_STATUS( vxReleaseImage( &yuv_image ) ); 393 | ERROR_CHECK_STATUS( vxReleaseImage( &luma_image ) ); 394 | ERROR_CHECK_STATUS( vxVerifyGraph( graph ) ); 395 | 396 | //////// 397 | // Process the video sequence frame by frame until the end of sequence or aborted. 398 | for( int frame_index = 0; !gui.AbortRequested(); frame_index++ ) 399 | { 400 | //////// 401 | // Copy input RGB frame from OpenCV to OpenVX. In order to do this, 402 | // you need to use vxAccessImagePatch and vxCommitImagePatch APIs. 403 | // See "VX/vx_api.h" for the description of these APIs. 404 | vx_rectangle_t cv_rgb_image_region; 405 | cv_rgb_image_region.start_x = 0; 406 | cv_rgb_image_region.start_y = 0; 407 | cv_rgb_image_region.end_x = width; 408 | cv_rgb_image_region.end_y = height; 409 | vx_imagepatch_addressing_t cv_rgb_image_layout; 410 | cv_rgb_image_layout.stride_x = 3; 411 | cv_rgb_image_layout.stride_y = gui.GetStride(); 412 | vx_uint8 * cv_rgb_image_buffer = gui.GetBuffer(); 413 | ERROR_CHECK_STATUS( vxAccessImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 414 | &cv_rgb_image_layout, ( void ** )&cv_rgb_image_buffer, VX_WRITE_ONLY ) ); 415 | ERROR_CHECK_STATUS( vxCommitImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 416 | &cv_rgb_image_layout, cv_rgb_image_buffer ) ); 417 | 418 | ////////******** 419 | // Now that input RGB image is ready, just run the graph. 420 | ERROR_CHECK_STATUS( vxProcessGraph( graph ) ); 421 | 422 | //////// 423 | // Display the output filtered image. 424 | vx_rectangle_t rect = { 0, 0, width, height }; 425 | vx_imagepatch_addressing_t addr = { 0 }; 426 | void * ptr = NULL; 427 | ERROR_CHECK_STATUS( vxAccessImagePatch( output_filtered_image, &rect, 0, &addr, &ptr, VX_READ_ONLY ) ); 428 | cv::Mat mat( height, width, CV_8U, ptr, addr.stride_y ); 429 | cv::imshow( "MedianBlur", mat ); 430 | ERROR_CHECK_STATUS( vxCommitImagePatch( output_filtered_image, &rect, 0, &addr, ptr ) ); 431 | 432 | //////// 433 | // Display the results and grab the next input RGB frame for the next iteration. 434 | char text[128]; 435 | sprintf( text, "Keyboard ESC/Q-Quit SPACE-Pause [FRAME %d] [ksize %d]", frame_index, ksize ); 436 | gui.DrawText( 0, 16, text ); 437 | gui.Show(); 438 | if( !gui.Grab() ) 439 | { 440 | // Terminate the processing loop if the end of sequence is detected. 441 | gui.WaitForKey(); 442 | break; 443 | } 444 | } 445 | 446 | ////////******** 447 | // Query graph performance using VX_GRAPH_ATTRIBUTE_PERFORMANCE and print timing 448 | // in milliseconds. Note that time units of vx_perf_t fields are nanoseconds. 449 | vx_perf_t perf = { 0 }; 450 | ERROR_CHECK_STATUS( vxQueryGraph( graph, VX_GRAPH_ATTRIBUTE_PERFORMANCE, &perf, sizeof( perf ) ) ); 451 | printf( "GraphName NumFrames Avg(ms) Min(ms)\n" 452 | "Median %9d %7.3f %7.3f\n", 453 | ( int )perf.num, ( float )perf.avg * 1e-6f, ( float )perf.min * 1e-6f ); 454 | 455 | ////////******** 456 | // To release an OpenVX object, you need to call vxRelease API which takes a pointer to the object. 457 | // If the release operation is successful, the OpenVX framework will reset the object to NULL. 458 | ERROR_CHECK_STATUS( vxReleaseGraph( &graph ) ); 459 | ERROR_CHECK_STATUS( vxReleaseImage( &input_rgb_image ) ); 460 | ERROR_CHECK_STATUS( vxReleaseImage( &output_filtered_image ) ); 461 | ERROR_CHECK_STATUS( vxReleaseContext( &context ) ); 462 | 463 | return 0; 464 | } 465 | -------------------------------------------------------------------------------- /tutorial_exercises/exercise3/exercise3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | 24 | /*! 25 | * \file exercise3.cpp 26 | * \example exercise3 27 | * \brief Access to OpenCV medianBlur function as an OpenVX user kernel. 28 | * Look for TODO STEP keyword in comments for the code snippets that you need to write. 29 | * \author Radhakrishna Giduthuri 30 | */ 31 | 32 | //////// 33 | // Include OpenCV wrapper for image capture and display. 34 | #include "opencv_camera_display.h" 35 | 36 | //////// 37 | // The most important top-level OpenVX header files are "VX/vx.h" and "VX/vxu.h". 38 | // The "VX/vx.h" includes all headers needed to support functionality of the 39 | // OpenVX specification, except for immediate mode functions, and it includes: 40 | // VX/vx_types.h -- type definitions required by the OpenVX standard 41 | // VX/vx_api.h -- all framework API definitions 42 | // VX/vx_kernels.h -- list of supported kernels in the OpenVX standard 43 | // VX/vx_nodes.h -- easier-to-use functions for the kernels 44 | // VX/vx_vendors.h 45 | // The "VX/vxu.h" defines the immediate mode utility functions (not needed here). 46 | #include 47 | 48 | 49 | //////// 50 | // Useful macros for OpenVX error checking: 51 | // ERROR_CHECK_STATUS - check status is VX_SUCCESS 52 | // ERROR_CHECK_OBJECT - check if the object creation is successful 53 | #define ERROR_CHECK_STATUS( status ) { \ 54 | vx_status status_ = (status); \ 55 | if(status_ != VX_SUCCESS) { \ 56 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 57 | exit(1); \ 58 | } \ 59 | } 60 | 61 | #define ERROR_CHECK_OBJECT( obj ) { \ 62 | vx_status status_ = vxGetStatus((vx_reference)(obj)); \ 63 | if(status_ != VX_SUCCESS) { \ 64 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 65 | exit(1); \ 66 | } \ 67 | } 68 | 69 | //////// 70 | // User kernel should have a unique enumerations and name for user kernel: 71 | // USER_LIBRARY_EXAMPLE - library ID for user kernels in this example 72 | // USER_KERNEL_MEDIAN_BLUR - enumeration for "app.userkernels.median_blur" kernel 73 | // 74 | // TODO STEP 01:******** 75 | // 1. Define USER_LIBRARY_EXAMPLE. We gave the code in comments. 76 | // 2. Define USER_KERNEL_MEDIAN_BLUR using VX_KERNEL_BASE() macro 77 | // We gave the most of the code in comments; fill in the missing parts. 78 | enum user_library_e 79 | { 80 | // USER_LIBRARY_EXAMPLE = 1, 81 | }; 82 | enum user_kernel_e 83 | { 84 | // USER_KERNEL_MEDIAN_BLUR = VX_KERNEL_BASE( VX_ID_DEFAULT, /* Fill in user library ID */ ) + 0x001, 85 | }; 86 | 87 | //////// 88 | // The node creation interface for the "app.userkernels.median_blur" kernel. 89 | // This user kernel example expects parameters in the following order: 90 | // parameter #0 -- input image of format VX_DF_IMAGE_U8 91 | // parameter #1 -- output image of format VX_DF_IMAGE_U8 92 | // parameter #2 -- scalar ksize of type VX_TYPE_INT32 93 | // 94 | // TODO STEP 02:******** 95 | // 1. Use vxGetKernelByEnum API to get a kernel object from USER_KERNEL_MEDIAN_BLUR. 96 | // Note that you need to use vxGetContext API to get the context from a graph object. 97 | // We gave most of the code in comments; fill in missing pieces. 98 | // 2. Use vxCreateGenericNode API to create a node from the kernel object. 99 | // We gave code skeleton in comments; fill in missing pieces. 100 | // 3. Create scalar objects for ksize parameter. 101 | // We gave code skeleton in comments; fill in missing pieces. 102 | // 4. Use vxSetParameterByIndex API to set node arguments. 103 | // We gave code for one parameter; do similar for others. 104 | // 5. Release the kernel and scalar objects that are not needed any more. 105 | // We gave code for one; do similar for the other. 106 | // 6. Use ERROR_CHECK_OBJECT and ERROR_CHECK_STATUS macros for error detection. 107 | // We gave code for 3 error checks; do similar for remaining. 108 | vx_node userMedianBlurNode( vx_graph graph, 109 | vx_image input, 110 | vx_image output, 111 | vx_int32 ksize ) 112 | { 113 | // vx_context context = vxGetContext( ( vx_reference ) /* Fill in parameter */ ); 114 | // vx_kernel kernel = vxGetKernelByEnum( /* Fill in parameters */ ); 115 | // ERROR_CHECK_OBJECT( kernel ); 116 | 117 | vx_node node = NULL; // vxCreateGenericNode( /* Fill in parameters */ ); 118 | // ERROR_CHECK_OBJECT( node ); 119 | 120 | // vx_scalar s_ksize = vxCreateScalar( /* Fill in parameters */ ); 121 | 122 | // ERROR_CHECK_STATUS( vxSetParameterByIndex( node, 0, ( vx_reference ) input ) ); 123 | // ... 124 | 125 | // ERROR_CHECK_STATUS( vxReleaseKernel( &kernel ) ); 126 | 127 | 128 | return node; 129 | } 130 | 131 | //////// 132 | // The user kernel input validator callback should check to make sure that all the input 133 | // parameters have correct data types. This user kernel example expects the inputs 134 | // to be valid in the following order: 135 | // parameter #0 -- input image of format VX_DF_IMAGE_U8 136 | // parameter #2 -- scalar ksize of type VX_TYPE_INT32 137 | // TODO STEP 03:******** 138 | // 1. Use vxGetParameterByIndex API to get access to the requested parameter. 139 | // We gave in code skeleton for this part; fill in parameters. 140 | // 2. Use vxQueryParameter API with VX_PARAMETER_ATTRIBUTE_REF to access the input object. 141 | // We gave in code skeleton for this part too; fill in parameters. 142 | // 3. If the index is 0, check to make sure that image format is VX_DF_FORMAT_U8. 143 | // Given that you have is a reference of type vx_reference, you can safely 144 | // type cast the reference to vx_image to access the image attributes. 145 | // We gave in most of the code in comments; fill in missing pieces. 146 | // 4. If the index is 2, check to make sure that the scalar type is VX_TYPE_INT32. 147 | // We gave in most of the code in comments; fill in missing pieces. 148 | vx_status VX_CALLBACK median_blur_input_validator( vx_node node, 149 | vx_uint32 index ) 150 | { 151 | // vx_reference ref = NULL; 152 | // vx_parameter parameter = vxGetParameterByIndex( /* Fill in parameters */ ); 153 | 154 | // ERROR_CHECK_STATUS( vxQueryParameter( parameter, /* Fill in parameter */, &ref, sizeof( ref ) ) ); 155 | // ERROR_CHECK_STATUS( vxReleaseParameter( /* Fill in parameter */ ) ); 156 | // ERROR_CHECK_OBJECT( ref ); 157 | 158 | // if( index == 0 ) 159 | // { 160 | // vx_df_image format = VX_DF_IMAGE_VIRT; 161 | // ERROR_CHECK_STATUS( vxQueryImage( /* Fill in parameters */ ) ); 162 | // ERROR_CHECK_STATUS( vxReleaseImage( ( vx_image * )&ref ) ); 163 | // if( format != /* Fill in value */ ) 164 | // { 165 | // return VX_ERROR_INVALID_FORMAT; 166 | // } 167 | // } 168 | 169 | // else if( index == 2 ) 170 | // { 171 | // vx_enum type = VX_TYPE_INVALID; 172 | // ERROR_CHECK_STATUS( vxQueryScalar( /* Fill in parameters */ ) ); 173 | // ERROR_CHECK_STATUS( vxReleaseScalar( /* Fill in parameter */ ) ); 174 | // if( /* Fill in the condition */ ) 175 | // { 176 | // return VX_ERROR_INVALID_TYPE; 177 | // } 178 | // } 179 | // else 180 | // { 181 | // // invalid input parameter 182 | // return VX_ERROR_INVALID_PARAMETERS; 183 | // } 184 | 185 | 186 | return VX_SUCCESS; 187 | } 188 | 189 | //////// 190 | // User kernel output validator callback should set the output parameter meta data. 191 | // This user kernel example has only one output parameter with the same dimensions as parameter #0. 192 | // parameter #1 -- output image of format VX_DF_IMAGE_U8 with the same dimensions as input 193 | // 194 | // TODO STEP 04:******** 195 | // 1. Only need to process for output parameter index #1. 196 | // Get the input image dimensions from parameter at index = 0. 197 | // We gave the code skeleton; fill in missing parts. 198 | // 2. Set the output image meta data to have the same dimensions as input and VX_DF_FORMAT_U8. 199 | // We gave the code skeleton; fill in missing parts. 200 | vx_status VX_CALLBACK median_blur_output_validator( vx_node node, 201 | vx_uint32 index, 202 | vx_meta_format meta ) 203 | { 204 | if( index == 1 ) 205 | { 206 | // vx_uint32 width = 0, height = 0; 207 | // vx_image input = NULL; 208 | // vx_parameter parameter = vxGetParameterByIndex( /* Fill in parameters to access parameter at index = 0 */ ); 209 | // ERROR_CHECK_STATUS( vxQueryParameter( /* Fill in parameters */, &input, sizeof( input ) ) ); 210 | // ERROR_CHECK_STATUS( vxReleaseParameter( ¶meter ) ); 211 | // ERROR_CHECK_STATUS( vxQueryImage( input, /* Fill in parameter */, &width, sizeof( width ) ) ); 212 | // ERROR_CHECK_STATUS( vxQueryImage( /* Fill in parameters */ ) ); 213 | // ERROR_CHECK_STATUS( vxReleaseImage( &input ) ); 214 | 215 | // vx_df_image format = VX_DF_IMAGE_U8; 216 | // ERROR_CHECK_STATUS( vxSetMetaFormatAttribute( meta, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof( format ) ) ); 217 | // ERROR_CHECK_STATUS( vxSetMetaFormatAttribute( /* Fill in parameters */, &width, sizeof( width ) ) ); 218 | // ERROR_CHECK_STATUS( vxSetMetaFormatAttribute( /* Fill in parameters */ ) ); 219 | } 220 | else 221 | { 222 | // invalid input parameter 223 | return VX_ERROR_INVALID_PARAMETERS; 224 | } 225 | 226 | 227 | return VX_SUCCESS; 228 | } 229 | 230 | //////// 231 | // User kernel host side function gets called to execute the user kernel node. 232 | // You need to wrap the OpenVX objects into OpenCV Mat objects and call cv::medianBlur. 233 | // 234 | // TODO STEP 05:******** 235 | // 1. Get ksize value from scalar object in refs[2]. 236 | // We gave code skeleton; fill in parameters. 237 | // 2. Get the image dimensions from input image. 238 | // We gave code skeleton; fill in parameters. 239 | // 3. Access input and output image patches and wrap it in a cv::Mat object. 240 | // Use the cv::Mat mat(width, height, CV_U8, ptr, addr.stride_y) to wrap 241 | // an OpenVX image plane buffer in an OpenCV mat object. Note that 242 | // you need to access input image with VX_READ_ONLY and output image 243 | // with VX_WRITE_ONLY. 244 | // We gave code skeleton; fill in parameters. 245 | // 4. Just call cv::medianBlur(input, output, ksize) 246 | // We gave code in comments. 247 | // 5. Use vxCommitImagePatch API to give the image buffers control back to OpenVX framework 248 | // We gave code for one; do similar for the other. 249 | vx_status VX_CALLBACK median_blur_host_side_function( vx_node node, const vx_reference * refs, vx_uint32 num ) 250 | { 251 | vx_image input = ( vx_image ) refs[0]; 252 | vx_image output = ( vx_image ) refs[1]; 253 | vx_scalar s_ksize = ( vx_scalar )refs[2]; 254 | 255 | // vx_int32 ksize = 0; 256 | // ERROR_CHECK_STATUS( vxReadScalarValue( /* Fill in parameters */ ) ); 257 | 258 | // vx_uint32 width = 0, height = 0; 259 | // ERROR_CHECK_STATUS( vxQueryImage( /* Fill in parameters */ ) ); 260 | // ERROR_CHECK_STATUS( vxQueryImage( /* Fill in parameters */ ) ); 261 | 262 | // vx_rectangle_t rect = { 0, 0, width, height }; 263 | // vx_imagepatch_addressing_t addr_input = { 0 }, addr_output = { 0 }; 264 | // void * ptr_input = NULL, * ptr_output = NULL; 265 | // ERROR_CHECK_STATUS( vxAccessImagePatch( input, /* Fill in parameters */, VX_READ_ONLY ) ); 266 | // ERROR_CHECK_STATUS( vxAccessImagePatch( output, /* Fill in parameters */, VX_WRITE_ONLY ) ); 267 | // cv::Mat mat_input( height, width, CV_8U, ptr_input, addr_input .stride_y ); 268 | // cv::Mat mat_output( /* Fill in parameters */ ); 269 | 270 | // cv::medianBlur( mat_input, mat_output, ksize ); 271 | 272 | // ERROR_CHECK_STATUS( vxCommitImagePatch( input, &rect, 0, &addr_input, ptr_input ) ); 273 | 274 | 275 | return VX_SUCCESS; 276 | } 277 | 278 | //////// 279 | // User kernels needs to be registered with every OpenVX context before use in a graph. 280 | // 281 | // TODO STEP 06:******** 282 | // 1. Use vxAddKernel API to register "app.userkernels.median_blur" with 283 | // kernel enumeration = USER_KERNEL_MEDIAN_BLUR, numParams = 3, and 284 | // all of the user kernel callback functions you implemented above. 285 | // We gave the code skeleton; fill in parameters. 286 | // 2. Use vxAddParameterToKernel API to specify direction, data_type, and 287 | // state of all 3 parameters to the kernel. Look into the comments of 288 | // userMedianBlurNode function (above) to details about the order of 289 | // kernel parameters and their types. 290 | // We gave code for one parameter; do similar for other two. 291 | // 3. Use vxFinalizeKernel API to make the kernel ready to use in a graph. 292 | // Note that the kernel object is still valid after this call. 293 | // So you need to call vxReleaseKernel before returning from this function. 294 | // We gave the code skeleton; fill in parameters. 295 | vx_status registerUserKernel( vx_context context ) 296 | { 297 | // vx_kernel kernel = vxAddKernel( context, 298 | // "app.userkernels.median_blur", 299 | // USER_KERNEL_MEDIAN_BLUR, 300 | // /* Fill in parameters */ ); 301 | // ERROR_CHECK_OBJECT( kernel ); 302 | 303 | // ERROR_CHECK_STATUS( vxAddParameterToKernel( kernel, 0, VX_INPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED ) ); // input 304 | // ... 305 | 306 | // ERROR_CHECK_STATUS( vxFinalizeKernel( /* Fill in parameter */ ) ); 307 | // ERROR_CHECK_STATUS( vxReleaseKernel( /* Fill in parameter */ ) ); 308 | 309 | 310 | vxAddLogEntry( ( vx_reference ) context, VX_SUCCESS, "OK: registered user kernel app.userkernels.median_blur\n" ); 311 | return VX_SUCCESS; 312 | } 313 | 314 | //////// 315 | // log_callback function implements a mechanism to print log messages 316 | // from the OpenVX framework onto console. 317 | void VX_CALLBACK log_callback( vx_context context, 318 | vx_reference ref, 319 | vx_status status, 320 | const vx_char string[] ) 321 | { 322 | printf( "LOG: [ status = %d ] %s\n", status, string ); 323 | fflush( stdout ); 324 | } 325 | 326 | //////// 327 | // main() has all the OpenVX application code for this exercise. 328 | // Command-line usage: 329 | // % solution_exercise3 [|] 330 | // When neither video sequence nor camera device number is specified, 331 | // it defaults to the video sequence in "PETS09-S1-L1-View001.avi". 332 | int main( int argc, char * argv[] ) 333 | { 334 | // Get default video sequence when nothing is specified on command-line and 335 | // instantiate OpenCV GUI module for reading input RGB images and displaying 336 | // the image with OpenVX results 337 | const char * video_sequence = argv[1]; 338 | CGuiModule gui( video_sequence ); 339 | 340 | // Try grab first video frame from the sequence using cv::VideoCapture 341 | // and check if video frame is available 342 | if( !gui.Grab() ) 343 | { 344 | printf( "ERROR: input has no video\n" ); 345 | return 1; 346 | } 347 | 348 | //////// 349 | // Set the application configuration parameters. Note that input video 350 | // sequence is an 8-bit RGB image with dimensions given by gui.GetWidth() 351 | // and gui.GetHeight(). The parameters for the median filter are: 352 | // ksize - median filter kernel size 353 | vx_uint32 width = gui.GetWidth(); 354 | vx_uint32 height = gui.GetHeight(); 355 | vx_int32 ksize = 7; 356 | 357 | //////// 358 | // Create the OpenVX context and make sure returned context is valid and 359 | // register the log_callback to receive messages from OpenVX framework. 360 | vx_context context = vxCreateContext(); 361 | ERROR_CHECK_OBJECT( context ); 362 | vxRegisterLogCallback( context, log_callback, vx_false_e ); 363 | 364 | //////// 365 | // Register user kernels with the context. 366 | // 367 | // TODO STEP 07:******** 368 | // 1. Register user kernel with context by calling your implementation of "registerUserKernel()". 369 | 370 | 371 | 372 | //////// 373 | // Create OpenVX image object for input RGB image and median filter output image. 374 | vx_image input_rgb_image = vxCreateImage( context, width, height, VX_DF_IMAGE_RGB ); 375 | vx_image output_filtered_image = vxCreateImage( context, width, height, VX_DF_IMAGE_U8 ); 376 | ERROR_CHECK_OBJECT( input_rgb_image ); 377 | ERROR_CHECK_OBJECT( output_filtered_image ); 378 | 379 | ////////******** 380 | // Create graph object and intermediate image objects. 381 | // Given that input is an RGB image, it is best to extract a gray image 382 | // from RGB image, which requires two steps: 383 | // - perform RGB to IYUV color conversion 384 | // - extract Y channel from IYUV image 385 | // This requires two intermediate OpenVX image objects. Since you don't 386 | // need to access these objects from the application, they can be virtual 387 | // objects that can be created using the vxCreateVirtualImage API. 388 | vx_graph graph = vxCreateGraph( context ); 389 | ERROR_CHECK_OBJECT( graph ); 390 | vx_image yuv_image = vxCreateVirtualImage( graph, width, height, VX_DF_IMAGE_IYUV ); 391 | vx_image luma_image = vxCreateVirtualImage( graph, width, height, VX_DF_IMAGE_U8 ); 392 | ERROR_CHECK_OBJECT( yuv_image ); 393 | ERROR_CHECK_OBJECT( luma_image ); 394 | 395 | ////////******** 396 | // Now all the objects have been created for building the graph 397 | // that converts RGB into luma image and then performs median blur 398 | // using user kernel USER_KERNEL_MEDIAN_BLUR. 399 | // Then use vxVerifyGraph API for initialization. 400 | // 401 | // TODO STEP 08:******** 402 | // 1. Use userMedianBlurNode function to add "median_blur" node. 403 | // We gave most of the code in comments; fill in parameters for user kernel. 404 | // vx_node nodes[] = 405 | // { 406 | // vxColorConvertNode( graph, input_rgb_image, yuv_image ), 407 | // vxChannelExtractNode( graph, yuv_image, VX_CHANNEL_Y, luma_image ), 408 | // userMedianBlurNode( graph, /* Fill in parameters */ ) 409 | // }; 410 | // for( vx_size i = 0; i < sizeof( nodes ) / sizeof( nodes[0] ); i++ ) 411 | // { 412 | // ERROR_CHECK_OBJECT( nodes[i] ); 413 | // ERROR_CHECK_STATUS( vxReleaseNode( &nodes[i] ) ); 414 | // } 415 | // ERROR_CHECK_STATUS( vxReleaseImage( &yuv_image ) ); 416 | // ERROR_CHECK_STATUS( vxReleaseImage( &luma_image ) ); 417 | // ERROR_CHECK_STATUS( vxVerifyGraph( graph ) ); 418 | 419 | 420 | //////// 421 | // Process the video sequence frame by frame until the end of sequence or aborted. 422 | for( int frame_index = 0; !gui.AbortRequested(); frame_index++ ) 423 | { 424 | //////// 425 | // Copy input RGB frame from OpenCV to OpenVX. In order to do this, 426 | // you need to use vxAccessImagePatch and vxCommitImagePatch APIs. 427 | // See "VX/vx_api.h" for the description of these APIs. 428 | vx_rectangle_t cv_rgb_image_region; 429 | cv_rgb_image_region.start_x = 0; 430 | cv_rgb_image_region.start_y = 0; 431 | cv_rgb_image_region.end_x = width; 432 | cv_rgb_image_region.end_y = height; 433 | vx_imagepatch_addressing_t cv_rgb_image_layout; 434 | cv_rgb_image_layout.stride_x = 3; 435 | cv_rgb_image_layout.stride_y = gui.GetStride(); 436 | vx_uint8 * cv_rgb_image_buffer = gui.GetBuffer(); 437 | ERROR_CHECK_STATUS( vxAccessImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 438 | &cv_rgb_image_layout, ( void ** )&cv_rgb_image_buffer, VX_WRITE_ONLY ) ); 439 | ERROR_CHECK_STATUS( vxCommitImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 440 | &cv_rgb_image_layout, cv_rgb_image_buffer ) ); 441 | 442 | ////////******** 443 | // Now that input RGB image is ready, just run the graph. 444 | // TODO STEP 09:******** 445 | // 1. Use vxProcessGraph to run the graph. 446 | // We gave the code in comments; just uncomment. 447 | // ERROR_CHECK_STATUS( vxProcessGraph( graph ) ); 448 | 449 | 450 | //////// 451 | // Display the output filtered image. 452 | vx_rectangle_t rect = { 0, 0, width, height }; 453 | vx_imagepatch_addressing_t addr = { 0 }; 454 | void * ptr = NULL; 455 | ERROR_CHECK_STATUS( vxAccessImagePatch( output_filtered_image, &rect, 0, &addr, &ptr, VX_READ_ONLY ) ); 456 | cv::Mat mat( height, width, CV_8U, ptr, addr.stride_y ); 457 | cv::imshow( "MedianBlur", mat ); 458 | ERROR_CHECK_STATUS( vxCommitImagePatch( output_filtered_image, &rect, 0, &addr, ptr ) ); 459 | 460 | //////// 461 | // Display the results and grab the next input RGB frame for the next iteration. 462 | char text[128]; 463 | sprintf( text, "Keyboard ESC/Q-Quit SPACE-Pause [FRAME %d] [ksize %d]", frame_index, ksize ); 464 | gui.DrawText( 0, 16, text ); 465 | gui.Show(); 466 | if( !gui.Grab() ) 467 | { 468 | // Terminate the processing loop if the end of sequence is detected. 469 | gui.WaitForKey(); 470 | break; 471 | } 472 | } 473 | 474 | ////////******** 475 | // Query graph performance using VX_GRAPH_ATTRIBUTE_PERFORMANCE and print timing 476 | // in milliseconds. Note that time units of vx_perf_t fields are nanoseconds. 477 | vx_perf_t perf = { 0 }; 478 | ERROR_CHECK_STATUS( vxQueryGraph( graph, VX_GRAPH_ATTRIBUTE_PERFORMANCE, &perf, sizeof( perf ) ) ); 479 | printf( "GraphName NumFrames Avg(ms) Min(ms)\n" 480 | "Median %9d %7.3f %7.3f\n", 481 | ( int )perf.num, ( float )perf.avg * 1e-6f, ( float )perf.min * 1e-6f ); 482 | 483 | ////////******** 484 | // To release an OpenVX object, you need to call vxRelease API which takes a pointer to the object. 485 | // If the release operation is successful, the OpenVX framework will reset the object to NULL. 486 | ERROR_CHECK_STATUS( vxReleaseGraph( &graph ) ); 487 | ERROR_CHECK_STATUS( vxReleaseImage( &input_rgb_image ) ); 488 | ERROR_CHECK_STATUS( vxReleaseImage( &output_filtered_image ) ); 489 | ERROR_CHECK_STATUS( vxReleaseContext( &context ) ); 490 | 491 | return 0; 492 | } 493 | -------------------------------------------------------------------------------- /tutorial_exercises/solution_exercise2/solution_exercise2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | 24 | /*! 25 | * \file solution_exercise2.cpp 26 | * \example solution_exercise2 27 | * \brief Feature tracker example. 28 | * Look for TODO keyword in comments for the code snippets that you need to write. 29 | * \author Radhakrishna Giduthuri 30 | */ 31 | 32 | //////// 33 | // Include OpenCV wrapper for image capture and display. 34 | #include "opencv_camera_display.h" 35 | 36 | //////// 37 | // The most important top-level OpenVX header files are "VX/vx.h" and "VX/vxu.h". 38 | // The "VX/vx.h" includes all headers needed to support functionality of the 39 | // OpenVX specification, except for immediate mode functions, and it includes: 40 | // VX/vx_types.h -- type definitions required by the OpenVX standard 41 | // VX/vx_api.h -- all framework API definitions 42 | // VX/vx_kernels.h -- list of supported kernels in the OpenVX standard 43 | // VX/vx_nodes.h -- easier-to-use functions for the kernels 44 | // VX/vx_vendors.h 45 | // The "VX/vxu.h" defines the immediate mode utility functions (not needed here). 46 | #include 47 | 48 | //////// 49 | // Useful macros for OpenVX error checking: 50 | // ERROR_CHECK_STATUS - check status is VX_SUCCESS 51 | // ERROR_CHECK_OBJECT - check if the object creation is successful 52 | #define ERROR_CHECK_STATUS( status ) { \ 53 | vx_status status_ = (status); \ 54 | if(status_ != VX_SUCCESS) { \ 55 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 56 | exit(1); \ 57 | } \ 58 | } 59 | 60 | #define ERROR_CHECK_OBJECT( obj ) { \ 61 | vx_status status_ = vxGetStatus((vx_reference)(obj)); \ 62 | if(status_ != VX_SUCCESS) { \ 63 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 64 | exit(1); \ 65 | } \ 66 | } 67 | 68 | //////// 69 | // log_callback function implements a mechanism to print log messages 70 | // from OpenVX framework onto console. 71 | void VX_CALLBACK log_callback( vx_context context, 72 | vx_reference ref, 73 | vx_status status, 74 | const vx_char string[] ) 75 | { 76 | printf( "LOG: [ status = %d ] %s\n", status, string ); 77 | fflush( stdout ); 78 | } 79 | 80 | //////// 81 | // main() has all the OpenVX application code for this exercise. 82 | // Command-line usage: 83 | // % solution_exercise2 [|] 84 | // When neither video sequence nor camera device number is specified, 85 | // it defaults to the video sequence in "PETS09-S1-L1-View001.avi". 86 | int main( int argc, char * argv[] ) 87 | { 88 | // Get default video sequence when nothing is specified on command-line and 89 | // instantiate OpenCV GUI module for reading input RGB images and displaying 90 | // the image with OpenVX results. 91 | const char * video_sequence = argv[1]; 92 | CGuiModule gui( video_sequence ); 93 | 94 | // Try to grab the first video frame from the sequence using cv::VideoCapture 95 | // and check if a video frame is available. 96 | if( !gui.Grab() ) 97 | { 98 | printf( "ERROR: input has no video\n" ); 99 | return 1; 100 | } 101 | 102 | //////// 103 | // Set the application configuration parameters. Note that input video 104 | // sequence is an 8-bit RGB image with dimensions given by gui.GetWidth() 105 | // and gui.GetHeight(). The parameters for the Harris corners algorithm are: 106 | // max_keypoint_count - maximum number of keypoints to track 107 | // harris_strength_thresh - minimum threshold score to keep a corner 108 | // (computed using the normalized Sobel kernel) 109 | // harris_min_distance - radial L2 distance for non-max suppression 110 | // harris_k_sensitivity - sensitivity threshold k from the Harris-Stephens 111 | // harris_gradient_size - window size for gradient computation 112 | // harris_block_size - block window size used to compute the 113 | // Harris corner score 114 | // lk_pyramid_levels - number of pyramid levels for LK optical flow 115 | // lk_termination - can be VX_TERM_CRITERIA_ITERATIONS or 116 | // VX_TERM_CRITERIA_EPSILON or 117 | // VX_TERM_CRITERIA_BOTH 118 | // lk_epsilon - error for terminating the algorithm 119 | // lk_num_iterations - number of iterations 120 | // lk_use_initial_estimate - turn on/off use of initial estimates 121 | // lk_window_dimension - size of window on which to perform the algorithm 122 | vx_uint32 width = gui.GetWidth(); 123 | vx_uint32 height = gui.GetHeight(); 124 | vx_size max_keypoint_count = 10000; 125 | vx_float32 harris_strength_thresh = 0.0005f; 126 | vx_float32 harris_min_distance = 5.0f; 127 | vx_float32 harris_k_sensitivity = 0.04f; 128 | vx_int32 harris_gradient_size = 3; 129 | vx_int32 harris_block_size = 3; 130 | vx_uint32 lk_pyramid_levels = 6; 131 | vx_float32 lk_pyramid_scale = VX_SCALE_PYRAMID_HALF; 132 | vx_enum lk_termination = VX_TERM_CRITERIA_BOTH; 133 | vx_float32 lk_epsilon = 0.01f; 134 | vx_uint32 lk_num_iterations = 5; 135 | vx_bool lk_use_initial_estimate = vx_false_e; 136 | vx_uint32 lk_window_dimension = 6; 137 | 138 | //////// 139 | // Create the OpenVX context and make sure the returned context is valid and 140 | // register the log_callback to receive messages from OpenVX framework. 141 | vx_context context = vxCreateContext(); 142 | ERROR_CHECK_OBJECT( context ); 143 | vxRegisterLogCallback( context, log_callback, vx_false_e ); 144 | 145 | //////// 146 | // Create OpenVX image object for input RGB image. 147 | vx_image input_rgb_image = vxCreateImage( context, width, height, VX_DF_IMAGE_RGB ); 148 | ERROR_CHECK_OBJECT( input_rgb_image ); 149 | 150 | ////////******** 151 | // OpenVX optical flow functionality requires pyramids of the current input 152 | // image and the previous image. It also requires keypoints that correspond 153 | // to the previous pyramid and will output updated keypoints into 154 | // another keypoint array. To be able to toggle between the current and 155 | // the previous buffers, you need to use OpenVX delay objects and vxAgeDelay(). 156 | // Create OpenVX pyramid and array object exemplars and create OpenVX delay 157 | // objects for both to hold two of each. Note that the exemplar objects are not 158 | // needed once the delay objects are created. 159 | // 160 | // TODO:******** 161 | // 1. Use vxCreatePyramid API to create a pyramid exemplar with the 162 | // same dimensions as the input image, VX_DF_IMAGE_U8 as image format, 163 | // lk_pyramid_levels as levels, and lk_pyramid_scale as scale. 164 | // 2. Use vxCreateArray API to create an array exemplar with 165 | // keypoint data type with num_keypoint_count as capacity. 166 | // 3. Use vxCreateDelay API to create delay objects for pyramid and 167 | // keypoint array using the exemplars created using the two steps above. 168 | // Use 2 delay slots for both of the delay objects. 169 | // 4. Release the pyramid and keypoint array exemplar objects. 170 | // 5. Use ERROR_CHECK_OBJECT/STATUS macros for proper error checking. 171 | vx_pyramid pyramidExemplar = vxCreatePyramid( context, lk_pyramid_levels, 172 | lk_pyramid_scale, width, height, VX_DF_IMAGE_U8 ); 173 | vx_array keypointsExemplar = vxCreateArray( context, VX_TYPE_KEYPOINT, 174 | max_keypoint_count ); 175 | ERROR_CHECK_OBJECT( pyramidExemplar ); 176 | ERROR_CHECK_OBJECT( keypointsExemplar ); 177 | vx_delay pyramidDelay = vxCreateDelay( context, ( vx_reference )pyramidExemplar, 2 ); 178 | vx_delay keypointsDelay = vxCreateDelay( context, ( vx_reference )keypointsExemplar, 2 ); 179 | ERROR_CHECK_OBJECT( pyramidDelay ); 180 | ERROR_CHECK_OBJECT( keypointsDelay ); 181 | ERROR_CHECK_STATUS( vxReleasePyramid( &pyramidExemplar ) ); 182 | ERROR_CHECK_STATUS( vxReleaseArray( &keypointsExemplar ) ); 183 | 184 | ////////******** 185 | // An object from a delay slot can be accessed using vxGetReferenceFromDelay API. 186 | // You need to use index = 0 for the current object and index = -1 for the previous object. 187 | // 188 | // TODO:******** 189 | // 1. Use vxGetReferenceFromDelay API to get the current and previous 190 | // pyramid objects from pyramid delay object. Note that you need 191 | // to typecast the vx_reference object to vx_pyramid. 192 | // 2. Similarly, get the current and previous keypoint array objects from 193 | // the keypoint delay object. 194 | // 3. Use ERROR_CHECK_OBJECT for proper error checking. 195 | vx_pyramid currentPyramid = ( vx_pyramid ) vxGetReferenceFromDelay( pyramidDelay, 0 ); 196 | vx_pyramid previousPyramid = ( vx_pyramid ) vxGetReferenceFromDelay( pyramidDelay, -1 ); 197 | vx_array currentKeypoints = ( vx_array ) vxGetReferenceFromDelay( keypointsDelay, 0 ); 198 | vx_array previousKeypoints = ( vx_array ) vxGetReferenceFromDelay( keypointsDelay, -1 ); 199 | ERROR_CHECK_OBJECT( currentPyramid ); 200 | ERROR_CHECK_OBJECT( previousPyramid ); 201 | ERROR_CHECK_OBJECT( currentKeypoints ); 202 | ERROR_CHECK_OBJECT( previousKeypoints ); 203 | 204 | ////////******** 205 | // Harris and optical flow algorithms require their own graph objects. 206 | // The Harris graph needs to extract gray scale image out of input RGB, 207 | // compute an initial set of keypoints, and compute an initial pyramid for use 208 | // by the optical flow graph. 209 | // 210 | // TODO:******** 211 | // 1. Create two graph objects: one for the Harris corner detector and 212 | // the other for feature tracking using optical flow using the 213 | // vxCreateGraph API. 214 | // 2. Use ERROR_CHECK_OBJECT to check the objects. 215 | vx_graph graphHarris = vxCreateGraph( context ); 216 | vx_graph graphTrack = vxCreateGraph( context ); 217 | ERROR_CHECK_OBJECT( graphHarris ); 218 | ERROR_CHECK_OBJECT( graphTrack ); 219 | 220 | ////////******** 221 | // Harris and pyramid computation expect input to be an 8-bit image. 222 | // Given that input is an RGB image, it is best to extract a gray image 223 | // from RGB image, which requires two steps: 224 | // - perform RGB to IYUV color conversion 225 | // - extract Y channel from IYUV image 226 | // This requires two intermediate OpenVX image objects. Since you don't 227 | // need to access these objects from the application, they can be virtual 228 | // objects that can be created using the vxCreateVirtualImage API. 229 | // 230 | // TODO:******** 231 | // 1. Create an IYUV image and a U8 image (for Y channel) with the same 232 | // dimensions as the input RGB image. Note that the image formats for 233 | // IYUV and U8 images are VX_DF_IMAGE_IYUV and VX_DF_IMAGE_U8. 234 | // Note that virtual objects are specific to a graph, so you 235 | // need to create two sets, one for each graph. 236 | // 2. Use ERROR_CHECK_OBJECT to check the objects. 237 | vx_image harris_yuv_image = vxCreateVirtualImage( graphHarris, width, height, VX_DF_IMAGE_IYUV ); 238 | vx_image harris_luma_image = vxCreateVirtualImage( graphHarris, width, height, VX_DF_IMAGE_U8 ); 239 | vx_image opticalflow_yuv_image = vxCreateVirtualImage( graphTrack, width, height, VX_DF_IMAGE_IYUV ); 240 | vx_image opticalflow_luma_image = vxCreateVirtualImage( graphTrack, width, height, VX_DF_IMAGE_U8 ); 241 | ERROR_CHECK_OBJECT( harris_yuv_image ); 242 | ERROR_CHECK_OBJECT( harris_luma_image ); 243 | ERROR_CHECK_OBJECT( opticalflow_yuv_image ); 244 | ERROR_CHECK_OBJECT( opticalflow_luma_image ); 245 | 246 | ////////******** 247 | // The Harris corner detector and optical flow nodes (see "VX/vx_nodes.h") 248 | // take strength_thresh, min_distance, sensitivity, epsilon, 249 | // num_iterations, and use_initial_estimate parameters as scalar 250 | // data objects. So, you need to create scalar objects with the corresponding 251 | // configuration parameters. 252 | // 253 | // TODO:******** 254 | // 1. Create scalar data objects of VX_TYPE_FLOAT32 for strength_thresh, 255 | // min_distance, sensitivity, and epsilon. Set their 256 | // initial values to harris_strength_thresh, harris_min_distance, 257 | // harris_k_sensitivity, and lk_epsilon. 258 | // 2. Similarly, create scalar objects for num_iterations and 259 | // use_initial_estimate with initial values: lk_num_iterations and 260 | // lk_use_initial_estimate. Make sure to use proper data types for 261 | // these parameters. 262 | // 3. Use ERROR_CHECK_OBJECT to check proper creation of objects. 263 | vx_scalar strength_thresh = vxCreateScalar( context, VX_TYPE_FLOAT32, &harris_strength_thresh ); 264 | vx_scalar min_distance = vxCreateScalar( context, VX_TYPE_FLOAT32, &harris_min_distance ); 265 | vx_scalar sensitivity = vxCreateScalar( context, VX_TYPE_FLOAT32, &harris_k_sensitivity ); 266 | vx_scalar epsilon = vxCreateScalar( context, VX_TYPE_FLOAT32, &lk_epsilon ); 267 | vx_scalar num_iterations = vxCreateScalar( context, VX_TYPE_UINT32, &lk_num_iterations ); 268 | vx_scalar use_initial_estimate = vxCreateScalar( context, VX_TYPE_BOOL, &lk_use_initial_estimate ); 269 | ERROR_CHECK_OBJECT( strength_thresh ); 270 | ERROR_CHECK_OBJECT( min_distance ); 271 | ERROR_CHECK_OBJECT( sensitivity ); 272 | ERROR_CHECK_OBJECT( epsilon ); 273 | ERROR_CHECK_OBJECT( num_iterations ); 274 | ERROR_CHECK_OBJECT( use_initial_estimate ); 275 | 276 | ////////******** 277 | // Now all the objects have been created for building the graphs. 278 | // First, build a graph that performs Harris corner detection and initial pyramid computation. 279 | // See "VX/vx_nodes.h" for APIs how to add nodes into a graph. 280 | // 281 | // TODO:******** 282 | // 1. Use vxColorConvertNode and vxChannelExtractNode APIs to get gray 283 | // scale image for Harris and Pyramid computation from the input 284 | // RGB image. Add these nodes into Harris graph. 285 | // 2. Use vxGaussianPyramidNode API to add pyramid computation node. 286 | // You need to use the current pyramid from the pyramid delay object. 287 | // 3. Use vxHarrisCornersNode API to add a Harris corners node. 288 | // You need to use the current keypoints from keypoints delay object. 289 | // 4. Use ERROR_CHECK_OBJECT to check proper creation of objects. 290 | // 5. Release node and virtual objects immediately since the graph 291 | // retains references to them. 292 | // 6. Call vxVerifyGraph to check for any errors in the graph. 293 | vx_node nodesHarris[] = 294 | { 295 | vxColorConvertNode( graphHarris, input_rgb_image, harris_yuv_image ), 296 | vxChannelExtractNode( graphHarris, harris_yuv_image, VX_CHANNEL_Y, harris_luma_image ), 297 | vxGaussianPyramidNode( graphHarris, harris_luma_image, currentPyramid ), 298 | vxHarrisCornersNode( graphHarris, harris_luma_image, strength_thresh, min_distance, 299 | sensitivity, harris_gradient_size, harris_block_size, currentKeypoints, NULL ) 300 | }; 301 | for( vx_size i = 0; i < sizeof( nodesHarris ) / sizeof( nodesHarris[0] ); i++ ) 302 | { 303 | ERROR_CHECK_OBJECT( nodesHarris[i] ); 304 | ERROR_CHECK_STATUS( vxReleaseNode( &nodesHarris[i] ) ); 305 | } 306 | ERROR_CHECK_STATUS( vxReleaseImage( &harris_yuv_image ) ); 307 | ERROR_CHECK_STATUS( vxReleaseImage( &harris_luma_image ) ); 308 | ERROR_CHECK_STATUS( vxVerifyGraph( graphHarris ) ); 309 | 310 | ////////******** 311 | // Now, build a graph that performs pyramid computation and feature 312 | // tracking using optical flow. 313 | // 314 | // TODO:******** 315 | // 1. Use vxColorConvertNode and vxChannelExtractNode APIs to get a gray 316 | // scale image for Harris and Pyramid computation from the input 317 | // RGB image. Add these nodes into Harris graph. 318 | // 2. Use vxGaussianPyramidNode API to add pyramid computation node. 319 | // You need to use the current pyramid from the pyramid delay object. 320 | // 3. Use vxOpticalFlowPyrLKNode API to add an optical flow node. You need to 321 | // use the current and previous keypoints from the keypoints delay object. 322 | // 4. Use ERROR_CHECK_OBJECT to check proper creation of objects. 323 | // 5. Release node and virtual objects immediately since the graph 324 | // retains references to them. 325 | // 6. Call vxVerifyGraph to check for any errors in the graph. 326 | vx_node nodesTrack[] = 327 | { 328 | vxColorConvertNode( graphTrack, input_rgb_image, opticalflow_yuv_image ), 329 | vxChannelExtractNode( graphTrack, opticalflow_yuv_image, VX_CHANNEL_Y, opticalflow_luma_image ), 330 | vxGaussianPyramidNode( graphTrack, opticalflow_luma_image, currentPyramid ), 331 | vxOpticalFlowPyrLKNode( graphTrack, previousPyramid, currentPyramid, previousKeypoints, previousKeypoints, 332 | currentKeypoints, lk_termination, epsilon, num_iterations, use_initial_estimate, lk_window_dimension ) 333 | }; 334 | for( vx_size i = 0; i < sizeof( nodesTrack ) / sizeof( nodesTrack[0] ); i++ ) 335 | { 336 | ERROR_CHECK_OBJECT( nodesTrack[i] ); 337 | ERROR_CHECK_STATUS( vxReleaseNode( &nodesTrack[i] ) ); 338 | } 339 | ERROR_CHECK_STATUS( vxReleaseImage( &opticalflow_yuv_image ) ); 340 | ERROR_CHECK_STATUS( vxReleaseImage( &opticalflow_luma_image ) ); 341 | ERROR_CHECK_STATUS( vxVerifyGraph( graphTrack ) ); 342 | 343 | //////// 344 | // Process the video sequence frame by frame until the end of sequence or aborted. 345 | for( int frame_index = 0; !gui.AbortRequested(); frame_index++ ) 346 | { 347 | //////// 348 | // Copy the input RGB frame from OpenCV to OpenVX. 349 | // In order to do this, you need to use vxAccessImagePatch and vxCommitImagePatch APIs. 350 | // See "VX/vx_api.h" for the description of these APIs. 351 | vx_rectangle_t cv_rgb_image_region; 352 | cv_rgb_image_region.start_x = 0; 353 | cv_rgb_image_region.start_y = 0; 354 | cv_rgb_image_region.end_x = width; 355 | cv_rgb_image_region.end_y = height; 356 | vx_imagepatch_addressing_t cv_rgb_image_layout; 357 | cv_rgb_image_layout.stride_x = 3; 358 | cv_rgb_image_layout.stride_y = gui.GetStride(); 359 | vx_uint8 * cv_rgb_image_buffer = gui.GetBuffer(); 360 | ERROR_CHECK_STATUS( vxAccessImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 361 | &cv_rgb_image_layout, ( void ** )&cv_rgb_image_buffer, VX_WRITE_ONLY ) ); 362 | ERROR_CHECK_STATUS( vxCommitImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 363 | &cv_rgb_image_layout, cv_rgb_image_buffer ) ); 364 | ////////******** 365 | // Now that input RGB image is ready, just run a graph. 366 | // Run Harris at the beginning to initialize the previous keypoints. 367 | // 368 | // TODO:******** 369 | // 1. Run a graph using vxProcessGraph API. Select Harris graph 370 | // if the frame_index == 0 (i.e., the first frame of the video 371 | // sequence), otherwise, select the feature tracking graph. 372 | // 2. Use ERROR_CHECK_STATUS for error checking. 373 | ERROR_CHECK_STATUS( vxProcessGraph( frame_index == 0 ? graphHarris : graphTrack ) ); 374 | 375 | ////////******** 376 | // To mark the keypoints in display, you need to access the output 377 | // keypoint array and draw each item on the output window using gui.DrawArrow(). 378 | // 379 | // TODO:******** 380 | // 1. Use vxGetReferenceFromDelay API to get the current and previous 381 | // keypoints array objects from the keypoints delay object. 382 | // Make sure to typecast the vx_reference object to vx_array. 383 | // 2. OpenVX array object has an attribute that keeps the current 384 | // number of items in the array. The name of the attribute is 385 | // VX_ARRAY_ATTRIBUTE_NUMITEMS and its value is of type vx_size. 386 | // Use vxQueryArray API to get number of keypoints in the 387 | // current keypoint array data object, representing number of 388 | // corners detected in the input RGB image. 389 | // IMPORTANT: Read number of items into "num_corners" 390 | // because this variable is displayed by code segment below. 391 | // 3. The data items in output keypoint array are of type 392 | // vx_keypoint_t (see "VX/vx_types.h"). To access the array 393 | // buffer, use vxAccessArrayRange with start index = 0, 394 | // end index = number of items in the array, and usage mode = 395 | // VX_READ_ONLY. Note that the stride returned by this access 396 | // call is not guaranteed to be sizeof(vx_keypoint_t). 397 | // Also make sure that num_corners is > 0, because 398 | // vxAccessArrayRange expects end index > 0. 399 | // 4. For each item in the keypoint buffer, use vxArrayItem to 400 | // access an individual keypoint and draw a marker at (x,y) 401 | // using gui.DrawArrow() if tracking_status field of keypoint 402 | // is non-zero. Also count number of keypoints with 403 | // non-zero tracking_status into "num_tracking" variable. 404 | // 5. Hand the control of output keypoint buffer over back to 405 | // OpenVX framework by calling vxCommitArrayRange API. 406 | // 6. Use ERROR_CHECK_STATUS for error checking. 407 | vx_size num_corners = 0, num_tracking = 0; 408 | currentKeypoints = ( vx_array )vxGetReferenceFromDelay( keypointsDelay, 0 ); 409 | previousKeypoints = ( vx_array )vxGetReferenceFromDelay( keypointsDelay, -1 ); 410 | ERROR_CHECK_OBJECT( currentKeypoints ); 411 | ERROR_CHECK_OBJECT( previousKeypoints ); 412 | ERROR_CHECK_STATUS( vxQueryArray( previousKeypoints, 413 | VX_ARRAY_ATTRIBUTE_NUMITEMS, &num_corners, sizeof( num_corners ) ) ); 414 | if( num_corners > 0 ) 415 | { 416 | vx_size kp_old_stride, kp_new_stride; 417 | vx_keypoint_t * kp_old_buf = NULL, * kp_new_buf = NULL; 418 | ERROR_CHECK_STATUS( vxAccessArrayRange( previousKeypoints, 0, num_corners, 419 | &kp_old_stride, ( void ** ) &kp_old_buf, VX_READ_ONLY ) ); 420 | ERROR_CHECK_STATUS( vxAccessArrayRange( currentKeypoints, 0, num_corners, 421 | &kp_new_stride, ( void ** ) &kp_new_buf, VX_READ_ONLY ) ); 422 | for( vx_size i = 0; i < num_corners; i++ ) 423 | { 424 | vx_keypoint_t * kp_old = &vxArrayItem( vx_keypoint_t, kp_old_buf, i, kp_old_stride ); 425 | vx_keypoint_t * kp_new = &vxArrayItem( vx_keypoint_t, kp_new_buf, i, kp_new_stride ); 426 | if( kp_new->tracking_status ) 427 | { 428 | num_tracking++; 429 | gui.DrawArrow( kp_old->x, kp_old->y, kp_new->x, kp_new->y ); 430 | } 431 | } 432 | ERROR_CHECK_STATUS( vxCommitArrayRange( previousKeypoints, 0, num_corners, kp_old_buf ) ); 433 | ERROR_CHECK_STATUS( vxCommitArrayRange( currentKeypoints, 0, num_corners, kp_new_buf ) ); 434 | } 435 | 436 | ////////******** 437 | // Flip the current and previous pyramid and keypoints in the delay objects. 438 | // 439 | // TODO:******** 440 | // 1. Use vxAgeDelay API to flip the current and previous buffers in pyramid and keypoint delay objects. 441 | // 2. Use ERROR_CHECK_STATUS for error checking. 442 | ERROR_CHECK_STATUS( vxAgeDelay( pyramidDelay ) ); 443 | ERROR_CHECK_STATUS( vxAgeDelay( keypointsDelay ) ); 444 | 445 | //////// 446 | // Display the results and grab the next input RGB frame for the next iteration. 447 | char text[128]; 448 | sprintf( text, "Keyboard ESC/Q-Quit SPACE-Pause [FRAME %d]", frame_index ); 449 | gui.DrawText( 0, 16, text ); 450 | sprintf( text, "Number of Corners: %d [tracking %d]", ( int )num_corners, ( int )num_tracking ); 451 | gui.DrawText( 0, 36, text ); 452 | gui.Show(); 453 | if( !gui.Grab() ) 454 | { 455 | // Terminate the processing loop if the end of sequence is detected. 456 | gui.WaitForKey(); 457 | break; 458 | } 459 | } 460 | 461 | ////////******** 462 | // Query graph performance using VX_GRAPH_ATTRIBUTE_PERFORMANCE and print timing 463 | // in milliseconds. Note that time units of vx_perf_t fields are nanoseconds. 464 | // 465 | // TODO:******** 466 | // 1. Use vxQueryGraph API with VX_GRAPH_ATTRIBUTE_PERFORMANCE to query graph performance. 467 | // 2. Print the average and min execution times in milliseconds. 468 | vx_perf_t perfHarris = { 0 }, perfTrack = { 0 }; 469 | ERROR_CHECK_STATUS( vxQueryGraph( graphHarris, VX_GRAPH_ATTRIBUTE_PERFORMANCE, &perfHarris, sizeof( perfHarris ) ) ); 470 | ERROR_CHECK_STATUS( vxQueryGraph( graphTrack, VX_GRAPH_ATTRIBUTE_PERFORMANCE, &perfTrack, sizeof( perfTrack ) ) ); 471 | printf( "GraphName NumFrames Avg(ms) Min(ms)\n" 472 | "Harris %9d %7.3f %7.3f\n" 473 | "Track %9d %7.3f %7.3f\n", 474 | ( int )perfHarris.num, ( float )perfHarris.avg * 1e-6f, ( float )perfHarris.min * 1e-6f, 475 | ( int )perfTrack.num, ( float )perfTrack.avg * 1e-6f, ( float )perfTrack.min * 1e-6f ); 476 | 477 | ////////******** 478 | // Release all the OpenVX objects created in this exercise, and make the context as the last one to release. 479 | // To release an OpenVX object, you need to call vxRelease API which takes a pointer to the object. 480 | // If the release operation is successful, the OpenVX framework will reset the object to NULL. 481 | // 482 | // TODO:******** 483 | // 1. Release all the image objects using vxReleaseImage API. 484 | // 2. For releasing all other objects use vxRelease APIs. 485 | // 3. Use ERROR_CHECK_STATUS for error checking. 486 | ERROR_CHECK_STATUS( vxReleaseGraph( &graphHarris ) ); 487 | ERROR_CHECK_STATUS( vxReleaseGraph( &graphTrack ) ); 488 | ERROR_CHECK_STATUS( vxReleaseImage( &input_rgb_image ) ); 489 | ERROR_CHECK_STATUS( vxReleaseDelay( &pyramidDelay ) ); 490 | ERROR_CHECK_STATUS( vxReleaseDelay( &keypointsDelay ) ); 491 | ERROR_CHECK_STATUS( vxReleaseScalar( &strength_thresh ) ); 492 | ERROR_CHECK_STATUS( vxReleaseScalar( &min_distance ) ); 493 | ERROR_CHECK_STATUS( vxReleaseScalar( &sensitivity ) ); 494 | ERROR_CHECK_STATUS( vxReleaseScalar( &epsilon ) ); 495 | ERROR_CHECK_STATUS( vxReleaseScalar( &num_iterations ) ); 496 | ERROR_CHECK_STATUS( vxReleaseScalar( &use_initial_estimate ) ); 497 | ERROR_CHECK_STATUS( vxReleaseContext( &context ) ); 498 | 499 | return 0; 500 | } 501 | -------------------------------------------------------------------------------- /tutorial_exercises/exercise2/exercise2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The Khronos Group Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and/or associated documentation files (the 6 | * "Materials"), to deal in the Materials without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Materials, and to 9 | * permit persons to whom the Materials are furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Materials. 14 | * 15 | * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 22 | */ 23 | 24 | /*! 25 | * \file exercise2.cpp 26 | * \example exercise2 27 | * \brief Feature tracker example. 28 | * Look for TODO STEP keyword in comments for the code snippets that you need to write. 29 | * \author Radhakrishna Giduthuri 30 | */ 31 | 32 | //////// 33 | // Include OpenCV wrapper for image capture and display. 34 | #include "opencv_camera_display.h" 35 | 36 | //////// 37 | // The most important top-level OpenVX header files are "VX/vx.h" and "VX/vxu.h". 38 | // The "VX/vx.h" includes all headers needed to support functionality of the 39 | // OpenVX specification, except for immediate mode functions, and it includes: 40 | // VX/vx_types.h -- type definitions required by the OpenVX standard 41 | // VX/vx_api.h -- all framework API definitions 42 | // VX/vx_kernels.h -- list of supported kernels in the OpenVX standard 43 | // VX/vx_nodes.h -- easier-to-use functions for the kernels 44 | // VX/vx_vendors.h 45 | // The "VX/vxu.h" defines the immediate mode utility functions (not needed here). 46 | #include 47 | 48 | //////// 49 | // Useful macros for OpenVX error checking: 50 | // ERROR_CHECK_STATUS - check status is VX_SUCCESS 51 | // ERROR_CHECK_OBJECT - check if the object creation is successful 52 | #define ERROR_CHECK_STATUS( status ) { \ 53 | vx_status status_ = (status); \ 54 | if(status_ != VX_SUCCESS) { \ 55 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 56 | exit(1); \ 57 | } \ 58 | } 59 | 60 | #define ERROR_CHECK_OBJECT( obj ) { \ 61 | vx_status status_ = vxGetStatus((vx_reference)(obj)); \ 62 | if(status_ != VX_SUCCESS) { \ 63 | printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \ 64 | exit(1); \ 65 | } \ 66 | } 67 | 68 | //////// 69 | // log_callback function implements a mechanism to print log messages 70 | // from OpenVX framework onto console. 71 | void VX_CALLBACK log_callback( vx_context context, 72 | vx_reference ref, 73 | vx_status status, 74 | const vx_char string[] ) 75 | { 76 | printf( "LOG: [ status = %d ] %s\n", status, string ); 77 | fflush( stdout ); 78 | } 79 | 80 | //////// 81 | // main() has all the OpenVX application code for this exercise. 82 | // Command-line usage: 83 | // % solution_exercise2 [|] 84 | // When neither video sequence nor camera device number is specified, 85 | // it defaults to the video sequence in "PETS09-S1-L1-View001.avi". 86 | int main( int argc, char * argv[] ) 87 | { 88 | // Get default video sequence when nothing is specified on command-line and 89 | // instantiate OpenCV GUI module for reading input RGB images and displaying 90 | // the image with OpenVX results. 91 | const char * video_sequence = argv[1]; 92 | CGuiModule gui( video_sequence ); 93 | 94 | // Try to grab the first video frame from the sequence using cv::VideoCapture 95 | // and check if a video frame is available. 96 | if( !gui.Grab() ) 97 | { 98 | printf( "ERROR: input has no video\n" ); 99 | return 1; 100 | } 101 | 102 | //////// 103 | // Set the application configuration parameters. Note that input video 104 | // sequence is an 8-bit RGB image with dimensions given by gui.GetWidth() 105 | // and gui.GetHeight(). The parameters for the Harris corners algorithm are: 106 | // max_keypoint_count - maximum number of keypoints to track 107 | // harris_strength_thresh - minimum threshold score to keep a corner 108 | // (computed using the normalized Sobel kernel) 109 | // harris_min_distance - radial L2 distance for non-max suppression 110 | // harris_k_sensitivity - sensitivity threshold k from the Harris-Stephens 111 | // harris_gradient_size - window size for gradient computation 112 | // harris_block_size - block window size used to compute the 113 | // Harris corner score 114 | // lk_pyramid_levels - number of pyramid levels for LK optical flow 115 | // lk_termination - can be VX_TERM_CRITERIA_ITERATIONS or 116 | // VX_TERM_CRITERIA_EPSILON or 117 | // VX_TERM_CRITERIA_BOTH 118 | // lk_epsilon - error for terminating the algorithm 119 | // lk_num_iterations - number of iterations 120 | // lk_use_initial_estimate - turn on/off use of initial estimates 121 | // lk_window_dimension - size of window on which to perform the algorithm 122 | vx_uint32 width = gui.GetWidth(); 123 | vx_uint32 height = gui.GetHeight(); 124 | vx_size max_keypoint_count = 10000; 125 | vx_float32 harris_strength_thresh = 0.0005f; 126 | vx_float32 harris_min_distance = 5.0f; 127 | vx_float32 harris_k_sensitivity = 0.04f; 128 | vx_int32 harris_gradient_size = 3; 129 | vx_int32 harris_block_size = 3; 130 | vx_uint32 lk_pyramid_levels = 6; 131 | vx_float32 lk_pyramid_scale = VX_SCALE_PYRAMID_HALF; 132 | vx_enum lk_termination = VX_TERM_CRITERIA_BOTH; 133 | vx_float32 lk_epsilon = 0.01f; 134 | vx_uint32 lk_num_iterations = 5; 135 | vx_bool lk_use_initial_estimate = vx_false_e; 136 | vx_uint32 lk_window_dimension = 6; 137 | 138 | //////// 139 | // Create the OpenVX context and make sure the returned context is valid and 140 | // register the log_callback to receive messages from OpenVX framework. 141 | vx_context context = vxCreateContext(); 142 | ERROR_CHECK_OBJECT( context ); 143 | vxRegisterLogCallback( context, log_callback, vx_false_e ); 144 | 145 | //////// 146 | // Create OpenVX image object for input RGB image. 147 | vx_image input_rgb_image = vxCreateImage( context, width, height, VX_DF_IMAGE_RGB ); 148 | ERROR_CHECK_OBJECT( input_rgb_image ); 149 | 150 | ////////******** 151 | // OpenVX optical flow functionality requires pyramids of the current input 152 | // image and the previous image. It also requires keypoints that correspond 153 | // to the previous pyramid and will output updated keypoints into 154 | // another keypoint array. To be able to toggle between the current and 155 | // the previous buffers, you need to use OpenVX delay objects and vxAgeDelay(). 156 | // Create OpenVX pyramid and array object exemplars and create OpenVX delay 157 | // objects for both to hold two of each. Note that the exemplar objects are not 158 | // needed once the delay objects are created. 159 | // 160 | // TODO STEP 01:******** 161 | // 1. Use vxCreatePyramid API to create a pyramid exemplar with the 162 | // same dimensions as the input image, VX_DF_IMAGE_U8 as image format, 163 | // lk_pyramid_levels as levels, and lk_pyramid_scale as scale. 164 | // We gave code for this in comments. 165 | // 2. Use vxCreateArray API to create an array exemplar with 166 | // keypoint data type with num_keypoint_count as capacity. 167 | // You need to add missing parameters to code in comments. 168 | // 3. Use vxCreateDelay API to create delay objects for pyramid and 169 | // keypoint array using the exemplars created using the two steps above. 170 | // Use 2 delay slots for both of the delay objects. 171 | // We gave code for one in comments; do similar for the other. 172 | // 4. Release the pyramid and keypoint array exemplar objects. 173 | // We gave code for one in comments; do similar for the other. 174 | // 5. Use ERROR_CHECK_OBJECT/STATUS macros for proper error checking. 175 | // We gave few error checks; do similar for the others. 176 | // vx_pyramid pyramidExemplar = vxCreatePyramid( context, lk_pyramid_levels, 177 | // lk_pyramid_scale, width, height, VX_DF_IMAGE_U8 ); 178 | // ERROR_CHECK_OBJECT( pyramidExemplar ); 179 | // vx_delay pyramidDelay = vxCreateDelay( context, ( vx_reference )pyramidExemplar, 2 ); 180 | // ERROR_CHECK_OBJECT( pyramidDelay ); 181 | // ERROR_CHECK_STATUS( vxReleasePyramid( &pyramidExemplar ) ); 182 | // vx_array keypointsExemplar = vxCreateArray( /* Fill in parameters */ ); 183 | // vx_delay keypointsDelay = vxCreateDelay( /* Fill in parameters */ ); 184 | 185 | 186 | ////////******** 187 | // An object from a delay slot can be accessed using vxGetReferenceFromDelay API. 188 | // You need to use index = 0 for the current object and index = -1 for the previous object. 189 | // 190 | // TODO STEP 02:******** 191 | // 1. Use vxGetReferenceFromDelay API to get the current and previous 192 | // pyramid objects from pyramid delay object. Note that you need 193 | // to typecast the vx_reference object to vx_pyramid. 194 | // We gave code for one in comments; do similar for the other. 195 | // 2. Similarly, get the current and previous keypoint array objects from 196 | // the keypoint delay object. 197 | // We gave code for one in comments; do similar for the other. 198 | // 3. Use ERROR_CHECK_OBJECT for proper error checking. 199 | // We gave one error check; do similar for the others. 200 | // vx_pyramid currentPyramid = ( vx_pyramid ) vxGetReferenceFromDelay( pyramidDelay, 0 ); 201 | // vx_pyramid previousPyramid = ( vx_pyramid ) vxGetReferenceFromDelay( /* Fill in parameters */ ); 202 | // vx_array currentKeypoints = ( vx_array ) vxGetReferenceFromDelay( /* Fill in parameters */ ); 203 | // vx_array previousKeypoints = ( vx_array ) vxGetReferenceFromDelay( keypointsDelay, -1 ); 204 | // ERROR_CHECK_OBJECT( currentPyramid ); 205 | 206 | 207 | ////////******** 208 | // Harris and optical flow algorithms require their own graph objects. 209 | // The Harris graph needs to extract gray scale image out of input RGB, 210 | // compute an initial set of keypoints, and compute an initial pyramid for use 211 | // by the optical flow graph. 212 | // 213 | // TODO STEP 03:******** 214 | // 1. Create two graph objects: one for the Harris corner detector and 215 | // the other for feature tracking using optical flow using the 216 | // vxCreateGraph API. 217 | // We gave code for one graph; do similar for the other. 218 | // 2. Use ERROR_CHECK_OBJECT to check the objects. 219 | // We gave one error check; do similar for the other. 220 | // vx_graph graphHarris = vxCreateGraph( context ); 221 | // vx_graph graphTrack = /* Fill in here */; 222 | // ERROR_CHECK_OBJECT( graphHarris ); 223 | 224 | 225 | ////////******** 226 | // Harris and pyramid computation expect input to be an 8-bit image. 227 | // Given that input is an RGB image, it is best to extract a gray image 228 | // from RGB image, which requires two steps: 229 | // - perform RGB to IYUV color conversion 230 | // - extract Y channel from IYUV image 231 | // This requires two intermediate OpenVX image objects. Since you don't 232 | // need to access these objects from the application, they can be virtual 233 | // objects that can be created using the vxCreateVirtualImage API. 234 | // 235 | // TODO STEP 04:******** 236 | // 1. Create an IYUV image and a U8 image (for Y channel) with the same 237 | // dimensions as the input RGB image. Note that the image formats for 238 | // IYUV and U8 images are VX_DF_IMAGE_IYUV and VX_DF_IMAGE_U8. 239 | // Note that virtual objects are specific to a graph, so you 240 | // need to create two sets, one for each graph. 241 | // We gave one fully in comments and you need to fill in missing 242 | // parameters for the others. 243 | // 2. Use ERROR_CHECK_OBJECT to check the objects. 244 | // We gave one error check in comments; do similar for others. 245 | // vx_image harris_yuv_image = vxCreateVirtualImage( graphHarris, width, height, VX_DF_IMAGE_IYUV ); 246 | // vx_image harris_luma_image = vxCreateVirtualImage( graphHarris, /* Fill in parameters */ ); 247 | // vx_image opticalflow_yuv_image = vxCreateVirtualImage( graphTrack, /* Fill in parameters */ ); 248 | // vx_image opticalflow_luma_image = vxCreateVirtualImage( /* Fill in parameters */ ); 249 | // ERROR_CHECK_OBJECT( harris_yuv_image ); 250 | 251 | 252 | ////////******** 253 | // The Harris corner detector and optical flow nodes (see "VX/vx_nodes.h") 254 | // take strength_thresh, min_distance, sensitivity, epsilon, 255 | // num_iterations, and use_initial_estimate parameters as scalar 256 | // data objects. So, you need to create scalar objects with the corresponding 257 | // configuration parameters. 258 | // 259 | // TODO STEP 05:******** 260 | // 1. Create scalar data objects of VX_TYPE_FLOAT32 for strength_thresh, 261 | // min_distance, sensitivity, and epsilon. Set their 262 | // initial values to harris_strength_thresh, harris_min_distance, 263 | // harris_k_sensitivity, and lk_epsilon. 264 | // We gave code full code for one scalar in comments; fill in 265 | // missing arguments for other ones. 266 | // 2. Similarly, create scalar objects for num_iterations and 267 | // use_initial_estimate with initial values: lk_num_iterations and 268 | // lk_use_initial_estimate. Make sure to use proper data types for 269 | // these parameters. 270 | // We gave code full code for one scalar in comments; fill in 271 | // missing arguments for the other. 272 | // 3. Use ERROR_CHECK_OBJECT to check proper creation of objects. 273 | // We gave the error check for one scalar; do similar for other 5 scalars. 274 | // vx_scalar strength_thresh = NULL; // vxCreateScalar( context, VX_TYPE_FLOAT32, &harris_strength_thresh ); 275 | // vx_scalar min_distance = NULL; // vxCreateScalar( context, /* Fill in parameters */ ); 276 | // vx_scalar sensitivity = NULL; // vxCreateScalar( /* Fill in parameters */ ); 277 | // vx_scalar epsilon = NULL; // vxCreateScalar( /* Fill in parameters */ ); 278 | // vx_scalar num_iterations = NULL; // vxCreateScalar( context, VX_TYPE_UINT32, /* Fill in parameter */ ); 279 | // vx_scalar use_initial_estimate = NULL; // vxCreateScalar( context, VX_TYPE_BOOL, &lk_use_initial_estimate ); 280 | // ERROR_CHECK_OBJECT( strength_thresh ); 281 | 282 | 283 | ////////******** 284 | // Now all the objects have been created for building the graphs. 285 | // First, build a graph that performs Harris corner detection and initial pyramid computation. 286 | // See "VX/vx_nodes.h" for APIs how to add nodes into a graph. 287 | // 288 | // TODO STEP 06:******** 289 | // 1. Use vxColorConvertNode and vxChannelExtractNode APIs to get gray 290 | // scale image for Harris and Pyramid computation from the input 291 | // RGB image. Add these nodes into Harris graph. 292 | // We gave code in comments with a missing parameter for you to fill in. 293 | // 2. Use vxGaussianPyramidNode API to add pyramid computation node. 294 | // You need to use the current pyramid from the pyramid delay object. 295 | // We gave code in comments with a missing parameter for you to fill in. 296 | // 3. Use vxHarrisCornersNode API to add a Harris corners node. 297 | // You need to use the current keypoints from keypoints delay object. 298 | // We gave code in comments with few missing parameters for you to fill in. 299 | // 4. Use ERROR_CHECK_OBJECT to check proper creation of objects. 300 | // 5. Release node and virtual objects immediately since the graph 301 | // retains references to them. 302 | // 6. Call vxVerifyGraph to check for any errors in the graph. 303 | // Fill in missing parameter in commented code. 304 | // vx_node nodesHarris[] = 305 | // { 306 | // vxColorConvertNode( graphHarris, input_rgb_image, harris_yuv_image ), 307 | // vxChannelExtractNode( graphHarris, /* Fill in parameter */, VX_CHANNEL_Y, harris_luma_image ), 308 | // vxGaussianPyramidNode( graphHarris, /* Fill in parameter */, currentPyramid ), 309 | // vxHarrisCornersNode( graphHarris, /* Fill in missing parameters */, currentKeypoints, NULL ) 310 | // }; 311 | // for( vx_size i = 0; i < sizeof( nodesHarris ) / sizeof( nodesHarris[0] ); i++ ) 312 | // { 313 | // ERROR_CHECK_OBJECT( nodesHarris[i] ); 314 | // ERROR_CHECK_STATUS( vxReleaseNode( &nodesHarris[i] ) ); 315 | // } 316 | // ERROR_CHECK_STATUS( vxReleaseImage( &harris_yuv_image ) ); 317 | // ERROR_CHECK_STATUS( vxReleaseImage( &harris_luma_image ) ); 318 | // ERROR_CHECK_STATUS( vxVerifyGraph( /* Fill in parameter */ ) ); 319 | 320 | 321 | ////////******** 322 | // Now, build a graph that performs pyramid computation and feature 323 | // tracking using optical flow. 324 | // 325 | // TODO STEP 07:******** 326 | // 1. Use vxColorConvertNode and vxChannelExtractNode APIs to get a gray 327 | // scale image for Harris and Pyramid computation from the input 328 | // RGB image. Add these nodes into Harris graph. 329 | // We gave the code in comments for color convert node; do similar 330 | // one for the channel extract node. 331 | // 2. Use vxGaussianPyramidNode API to add pyramid computation node. 332 | // You need to use the current pyramid from the pyramid delay object. 333 | // Most of the code is given in the comments; fill in the missing parameter. 334 | // 3. Use vxOpticalFlowPyrLKNode API to add an optical flow node. You need to 335 | // use the current and previous keypoints from the keypoints delay object. 336 | // Fill in the missing parameters in commented code. 337 | // 4. Use ERROR_CHECK_OBJECT to check proper creation of objects. 338 | // 5. Release node and virtual objects immediately since the graph 339 | // retains references to them. 340 | // 6. Call vxVerifyGraph to check for any errors in the graph. 341 | // Fill in the missing parameter in commented code. 342 | // vx_node nodesTrack[] = 343 | // { 344 | // vxColorConvertNode( graphTrack, input_rgb_image, opticalflow_yuv_image ), 345 | // vxChannelExtractNode( graphTrack, /* Fill in parameters */ ), 346 | // vxGaussianPyramidNode( graphTrack, /* Fill in parameter */, currentPyramid ), 347 | // vxOpticalFlowPyrLKNode( graphTrack, /* Fill in parameters */ ) 348 | // }; 349 | // for( vx_size i = 0; i < sizeof( nodesTrack ) / sizeof( nodesTrack[0] ); i++ ) 350 | // { 351 | // ERROR_CHECK_OBJECT( nodesTrack[i] ); 352 | // ERROR_CHECK_STATUS( vxReleaseNode( &nodesTrack[i] ) ); 353 | // } 354 | // ERROR_CHECK_STATUS( vxReleaseImage( &opticalflow_yuv_image ) ); 355 | // ERROR_CHECK_STATUS( vxReleaseImage( &opticalflow_luma_image ) ); 356 | // ERROR_CHECK_STATUS( vxVerifyGraph( /* Fill in parameter */ ) ); 357 | 358 | 359 | //////// 360 | // Process the video sequence frame by frame until the end of sequence or aborted. 361 | for( int frame_index = 0; !gui.AbortRequested(); frame_index++ ) 362 | { 363 | //////// 364 | // Copy the input RGB frame from OpenCV to OpenVX. 365 | // In order to do this, you need to use vxAccessImagePatch and vxCommitImagePatch APIs. 366 | // See "VX/vx_api.h" for the description of these APIs. 367 | vx_rectangle_t cv_rgb_image_region; 368 | cv_rgb_image_region.start_x = 0; 369 | cv_rgb_image_region.start_y = 0; 370 | cv_rgb_image_region.end_x = width; 371 | cv_rgb_image_region.end_y = height; 372 | vx_imagepatch_addressing_t cv_rgb_image_layout; 373 | cv_rgb_image_layout.stride_x = 3; 374 | cv_rgb_image_layout.stride_y = gui.GetStride(); 375 | vx_uint8 * cv_rgb_image_buffer = gui.GetBuffer(); 376 | ERROR_CHECK_STATUS( vxAccessImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 377 | &cv_rgb_image_layout, ( void ** )&cv_rgb_image_buffer, VX_WRITE_ONLY ) ); 378 | ERROR_CHECK_STATUS( vxCommitImagePatch( input_rgb_image, &cv_rgb_image_region, 0, 379 | &cv_rgb_image_layout, cv_rgb_image_buffer ) ); 380 | 381 | ////////******** 382 | // Now that input RGB image is ready, just run a graph. 383 | // Run Harris at the beginning to initialize the previous keypoints. 384 | // 385 | // TODO STEP 08:******** 386 | // 1. Run a graph using vxProcessGraph API. Select Harris graph 387 | // if the frame_index == 0 (i.e., the first frame of the video 388 | // sequence), otherwise, select the feature tracking graph. 389 | // 2. Use ERROR_CHECK_STATUS for error checking. 390 | 391 | 392 | 393 | ////////******** 394 | // To mark the keypoints in display, you need to access the output 395 | // keypoint array and draw each item on the output window using gui.DrawArrow(). 396 | // 397 | // TODO STEP 09:******** 398 | // 1. Use vxGetReferenceFromDelay API to get the current and previous 399 | // keypoints array objects from the keypoints delay object. 400 | // Make sure to typecast the vx_reference object to vx_array. 401 | // We gave one for the previous previous keypoint array in comments; 402 | // do a similar one for the current keypoint array. 403 | // 2. OpenVX array object has an attribute that keeps the current 404 | // number of items in the array. The name of the attribute is 405 | // VX_ARRAY_ATTRIBUTE_NUMITEMS and its value is of type vx_size. 406 | // Use vxQueryArray API to get number of keypoints in the 407 | // current keypoint array data object, representing number of 408 | // corners detected in the input RGB image. 409 | // IMPORTANT: Read number of items into "num_corners" 410 | // because this variable is displayed by code segment below. 411 | // We gave most part of this statement in comment; just fill in the 412 | // missing parameter. 413 | // 3. The data items in output keypoint array are of type 414 | // vx_keypoint_t (see "VX/vx_types.h"). To access the array 415 | // buffer, use vxAccessArrayRange with start index = 0, 416 | // end index = number of items in the array, and usage mode = 417 | // VX_READ_ONLY. Note that the stride returned by this access 418 | // call is not guaranteed to be sizeof(vx_keypoint_t). 419 | // Also make sure that num_corners is > 0, because 420 | // vxAccessArrayRange expects end index > 0. 421 | // We gave the code for previous keypoint array in comment; 422 | // do similar one for the current keypoint array. 423 | // 4. For each item in the keypoint buffer, use vxArrayItem to 424 | // access an individual keypoint and draw a marker at (x,y) 425 | // using gui.DrawArrow() if tracking_status field of keypoint 426 | // is non-zero. Also count number of keypoints with 427 | // non-zero tracking_status into "num_tracking" variable. 428 | // We gave most of the code; fill in the missing parameters and uncomment. 429 | // 5. Hand the control of output keypoint buffer over back to 430 | // OpenVX framework by calling vxCommitArrayRange API. 431 | // We gave the code for previous keypoint array in comment; 432 | // do similar one for the current keypoint array. 433 | // 6. Use ERROR_CHECK_STATUS for error checking. 434 | vx_size num_corners = 0, num_tracking = 0; 435 | // previousKeypoints = ( vx_array )vxGetReferenceFromDelay( keypointsDelay, -1 ); 436 | // currentKeypoints = ( vx_array )vxGetReferenceFromDelay( /* Fill in parameters */ ); 437 | // ERROR_CHECK_OBJECT( currentKeypoints ); 438 | // ERROR_CHECK_OBJECT( previousKeypoints ); 439 | // ERROR_CHECK_STATUS( vxQueryArray( previousKeypoints, /* Fill in parameter */, &num_corners, sizeof( num_corners ) ) ); 440 | if( num_corners > 0 ) 441 | { 442 | vx_size kp_old_stride, kp_new_stride; 443 | vx_keypoint_t * kp_old_buf = NULL, * kp_new_buf = NULL; 444 | // ERROR_CHECK_STATUS( vxAccessArrayRange( previousKeypoints, 0, num_corners, 445 | // &kp_old_stride, ( void ** ) &kp_old_buf, VX_READ_ONLY ) ); 446 | // ERROR_CHECK_STATUS( vxAccessArrayRange( /* Fill in parameters */ ); 447 | for( vx_size i = 0; i < num_corners; i++ ) 448 | { 449 | // vx_keypoint_t * kp_old = &vxArrayItem( vx_keypoint_t, kp_old_buf, i, kp_old_stride ); 450 | // vx_keypoint_t * kp_new = &vxArrayItem( /* Fill in parameters */ ); 451 | // if( kp_new->tracking_status ) 452 | // { 453 | // num_tracking++; 454 | // gui.DrawArrow( kp_old->x, kp_old->y, kp_new->x, kp_new->y ); 455 | // } 456 | } 457 | // ERROR_CHECK_STATUS( vxCommitArrayRange( previousKeypoints, 0, num_corners, kp_old_buf ) ); 458 | // ERROR_CHECK_STATUS( vxCommitArrayRange( /* Fill in parameters */ ) ); 459 | } 460 | 461 | 462 | ////////******** 463 | // Flip the current and previous pyramid and keypoints in the delay objects. 464 | // 465 | // TODO STEP 10:******** 466 | // 1. Use vxAgeDelay API to flip the current and previous buffers in delay objects. 467 | // You need to call vxAgeDelay for both two delay objects. 468 | // 2. Use ERROR_CHECK_STATUS for error checking. 469 | // ERROR_CHECK_STATUS( vxAgeDelay( /* Fill in parameter */ ) ); 470 | // ERROR_CHECK_STATUS( vxAgeDelay( /* Fill in parameter */ ) ); 471 | 472 | 473 | //////// 474 | // Display the results and grab the next input RGB frame for the next iteration. 475 | char text[128]; 476 | sprintf( text, "Keyboard ESC/Q-Quit SPACE-Pause [FRAME %d]", frame_index ); 477 | gui.DrawText( 0, 16, text ); 478 | sprintf( text, "Number of Corners: %d [tracking %d]", ( int )num_corners, ( int )num_tracking ); 479 | gui.DrawText( 0, 36, text ); 480 | gui.Show(); 481 | if( !gui.Grab() ) 482 | { 483 | // Terminate the processing loop if the end of sequence is detected. 484 | gui.WaitForKey(); 485 | break; 486 | } 487 | } 488 | 489 | ////////******** 490 | // Query graph performance using VX_GRAPH_ATTRIBUTE_PERFORMANCE and print timing 491 | // in milliseconds. Note that time units of vx_perf_t fields are nanoseconds. 492 | // 493 | // TODO STEP 11:******** 494 | // 1. Use vxQueryGraph API with VX_GRAPH_ATTRIBUTE_PERFORMANCE to query graph performance. 495 | // We gave the attribute query for one graph in comments. Do the same for the second graph. 496 | // 2. Print the average and min execution times in milliseconds. Use the printf in comments. 497 | // vx_perf_t perfHarris = { 0 }, perfTrack = { 0 }; 498 | // ERROR_CHECK_STATUS( vxQueryGraph( graphHarris, VX_GRAPH_ATTRIBUTE_PERFORMANCE, &perfHarris, sizeof( perfHarris ) ) ); 499 | // ERROR_CHECK_STATUS( vxQueryGraph( /* Fill in parameters here for get performance of the other graph */ ); 500 | // printf( "GraphName NumFrames Avg(ms) Min(ms)\n" 501 | // "Harris %9d %7.3f %7.3f\n" 502 | // "Track %9d %7.3f %7.3f\n", 503 | // ( int )perfHarris.num, ( float )perfHarris.avg * 1e-6f, ( float )perfHarris.min * 1e-6f, 504 | // ( int )perfTrack.num, ( float )perfTrack.avg * 1e-6f, ( float )perfTrack.min * 1e-6f ); 505 | 506 | 507 | ////////******** 508 | // Release all the OpenVX objects created in this exercise, and make the context as the last one to release. 509 | // To release an OpenVX object, you need to call vxRelease API which takes a pointer to the object. 510 | // If the release operation is successful, the OpenVX framework will reset the object to NULL. 511 | // 512 | // TODO STEP 12:******** 513 | // 1. For releasing all other objects use vxRelease APIs. 514 | // You have to release 2 graph objects, 1 image object, 2 delay objects, 515 | // 6 scalar objects, and 1 context object. 516 | // 2. Use ERROR_CHECK_STATUS for error checking. 517 | // ERROR_CHECK_STATUS( vxReleaseContext( &context ) ); 518 | 519 | 520 | return 0; 521 | } 522 | --------------------------------------------------------------------------------