diff --git a/3rdparty/ippicv/downloader.cmake b/3rdparty/ippicv/downloader.cmake index debb6070d..0a3a4119c 100644 --- a/3rdparty/ippicv/downloader.cmake +++ b/3rdparty/ippicv/downloader.cmake @@ -6,6 +6,8 @@ # function(_icv_downloader) + # Commit SHA in the opencv_3rdparty repo + set(IPPICV_BINARIES_COMMIT "3d41df448b589aa076d9d27ace344d3ef709e4b9") # Define actual ICV versions if(APPLE) set(OPENCV_ICV_PACKAGE_NAME "ippicv_macosx_20141027.tgz") @@ -62,7 +64,7 @@ function(_icv_downloader) if(DEFINED ENV{OPENCV_ICV_URL}) set(OPENCV_ICV_URL $ENV{OPENCV_ICV_URL}) else() - set(OPENCV_ICV_URL "http://sourceforge.net/projects/opencvlibrary/files/3rdparty/ippicv") + set(OPENCV_ICV_URL "https://raw.githubusercontent.com/Itseez/opencv_3rdparty/${IPPICV_BINARIES_COMMIT}/ippicv") endif() endif() diff --git a/3rdparty/libtiff/CMakeLists.txt b/3rdparty/libtiff/CMakeLists.txt index a06296e41..13971f16a 100644 --- a/3rdparty/libtiff/CMakeLists.txt +++ b/3rdparty/libtiff/CMakeLists.txt @@ -93,6 +93,7 @@ ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4018 /wd4100 /wd4127 /wd4311 /wd4701 /wd ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4244) # vs2008 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4267 /wd4305 /wd4306) # vs2008 Win64 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4703) # vs2012 +ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4456 /wd4457 /wd4312) # vs2015 ocv_warnings_disable(CMAKE_C_FLAGS /wd4267 /wd4244 /wd4018) diff --git a/3rdparty/openexr/CMakeLists.txt b/3rdparty/openexr/CMakeLists.txt index e01d8f500..4efab827e 100644 --- a/3rdparty/openexr/CMakeLists.txt +++ b/3rdparty/openexr/CMakeLists.txt @@ -44,6 +44,7 @@ ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4018 /wd4099 /wd4100 /wd4101 /wd4127 /wd ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4334) # vs2005 Win64 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4244) # vs2008 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4267) # vs2008 Win64 +ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4456) # vs2015 if(UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR CV_ICC)) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") diff --git a/3rdparty/tbb/CMakeLists.txt b/3rdparty/tbb/CMakeLists.txt index 24b6f6b79..93d943523 100644 --- a/3rdparty/tbb/CMakeLists.txt +++ b/3rdparty/tbb/CMakeLists.txt @@ -212,7 +212,13 @@ else() endif() ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wmissing-declarations) -string(REPLACE "-Werror=non-virtual-dtor" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +# filter out flags that are not handled well by the TBB code +foreach(var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG) + string(REPLACE "-Werror=non-virtual-dtor" "" ${var} "${${var}}") + string(REPLACE "-fvisibility=hidden" "" ${var} "${${var}}") + string(REPLACE "-fvisibility-inlines-hidden" "" ${var} "${${var}}") +endforeach() if (WIN32) set(tbb_debug_postfix "_debug") # to fit pragmas in _windef.h inside TBB diff --git a/CMakeLists.txt b/CMakeLists.txt index 72b1f478f..ec3d17928 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,8 @@ if(DEFINED CMAKE_BUILD_TYPE) set_property( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CMAKE_CONFIGURATION_TYPES} ) endif() +enable_testing() + project(OpenCV CXX C) if(MSVC) @@ -188,7 +190,7 @@ OCV_OPTION(WITH_QUICKTIME "Use QuickTime for Video I/O insted of QTKit" OFF OCV_OPTION(WITH_TBB "Include Intel TBB support" OFF IF (NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_OPENMP "Include OpenMP support" OFF) OCV_OPTION(WITH_CSTRIPES "Include C= support" OFF IF (WIN32 AND NOT WINRT) ) -OCV_OPTION(WITH_PTHREADS_PF "Use pthreads-based parallel_for" ON IF (NOT WIN32) ) +OCV_OPTION(WITH_PTHREADS_PF "Use pthreads-based parallel_for" ON IF (NOT WIN32 OR MINGW) ) OCV_OPTION(WITH_TIFF "Include TIFF support" ON IF (NOT IOS) ) OCV_OPTION(WITH_UNICAP "Include Unicap support (GPL)" OFF IF (UNIX AND NOT APPLE AND NOT ANDROID) ) OCV_OPTION(WITH_V4L "Include Video 4 Linux support" ON IF (UNIX AND NOT ANDROID) ) @@ -205,7 +207,8 @@ OCV_OPTION(WITH_OPENCLAMDBLAS "Include AMD OpenCL BLAS library support" ON OCV_OPTION(WITH_DIRECTX "Include DirectX support" ON IF (WIN32 AND NOT WINRT) ) OCV_OPTION(WITH_INTELPERC "Include Intel Perceptual Computing support" OFF IF (WIN32 AND NOT WINRT) ) OCV_OPTION(WITH_IPP_A "Include Intel IPP_A support" OFF IF (MSVC OR X86 OR X86_64) ) -OCV_OPTION(WITH_VAAPI "Include VA-API support" OFF IF (UNIX AND NOT ANDROID) ) +OCV_OPTION(WITH_VA "Include VA support" OFF IF (UNIX AND NOT ANDROID) ) +OCV_OPTION(WITH_VA_INTEL "Include Intel VA-API/OpenCL support" OFF IF (UNIX AND NOT ANDROID) ) OCV_OPTION(WITH_GDAL "Include GDAL Support" OFF IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) OCV_OPTION(WITH_GPHOTO2 "Include gPhoto2 library support" ON IF (UNIX AND NOT ANDROID) ) @@ -1066,9 +1069,13 @@ if(DEFINED WITH_IPP_A) status(" Use IPP Async:" HAVE_IPP_A THEN "YES" ELSE NO) endif(DEFINED WITH_IPP_A) -if(DEFINED WITH_VAAPI) -status(" Use Intel VA-API:" HAVE_VAAPI THEN "YES (MSDK: ${VAAPI_MSDK_ROOT} OpenCL: ${VAAPI_IOCL_ROOT})" ELSE NO) -endif(DEFINED WITH_VAAPI) +if(DEFINED WITH_VA) +status(" Use VA:" HAVE_VA THEN "YES" ELSE NO) +endif(DEFINED WITH_VA) + +if(DEFINED WITH_VA_INTEL) +status(" Use Intel VA-API/OpenCL:" HAVE_VA_INTEL THEN "YES (MSDK: ${VA_INTEL_MSDK_ROOT} OpenCL: ${VA_INTEL_IOCL_ROOT})" ELSE NO) +endif(DEFINED WITH_VA_INTEL) status(" Use Eigen:" HAVE_EIGEN THEN "YES (ver ${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION})" ELSE NO) status(" Use Cuda:" HAVE_CUDA THEN "YES (ver ${CUDA_VERSION_STRING})" ELSE NO) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..1e13c8996 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +## Contributing guidelines + +All guidelines for contributing to the OpenCV repository can be found at [`How to contribute guideline`](https://github.com/Itseez/opencv/wiki/How_to_contribute). diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index fe3de3fed..0dcf7ed26 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -362,5 +362,7 @@ if(MSVC) if(NOT ENABLE_NOISY_WARNINGS) ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4251) # class 'std::XXX' needs to have dll-interface to be used by clients of YYY ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4324) # 'struct_name' : structure was padded due to __declspec(align()) + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4275) # non dll-interface class 'std::exception' used as base for dll-interface class 'cv::Exception' + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4589) # Constructor of abstract class 'cv::ORB' ignores initializer for virtual base class 'cv::Algorithm' endif() endif() diff --git a/cmake/OpenCVDetectAndroidSDK.cmake b/cmake/OpenCVDetectAndroidSDK.cmake index 3bfb10e2d..bc9dcd042 100644 --- a/cmake/OpenCVDetectAndroidSDK.cmake +++ b/cmake/OpenCVDetectAndroidSDK.cmake @@ -240,7 +240,7 @@ macro(add_android_project target path) foreach(f ${android_proj_files}) add_custom_command( OUTPUT "${android_proj_bin_dir}/${f}" - COMMAND ${CMAKE_COMMAND} -E copy "${path}/${f}" "${android_proj_bin_dir}/${f}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${path}/${f}" "${android_proj_bin_dir}/${f}" MAIN_DEPENDENCY "${path}/${f}" COMMENT "Copying ${f}") list(APPEND android_proj_file_deps "${path}/${f}" "${android_proj_bin_dir}/${f}") @@ -353,7 +353,7 @@ macro(add_android_project target path) set(__android_project_chain ${target} CACHE INTERNAL "auxiliary variable used for Android progects chaining") # put the final .apk to the OpenCV's bin folder - add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${android_proj_bin_dir}/bin/${target}-debug.apk" "${OpenCV_BINARY_DIR}/bin/${target}.apk") + add_custom_command(TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${android_proj_bin_dir}/bin/${target}-debug.apk" "${OpenCV_BINARY_DIR}/bin/${target}.apk") if(INSTALL_ANDROID_EXAMPLES AND "${target}" MATCHES "^example-") #apk install(FILES "${OpenCV_BINARY_DIR}/bin/${target}.apk" DESTINATION "samples" COMPONENT samples) diff --git a/cmake/OpenCVDetectCXXCompiler.cmake b/cmake/OpenCVDetectCXXCompiler.cmake index 360a08fec..5cf4c856b 100644 --- a/cmake/OpenCVDetectCXXCompiler.cmake +++ b/cmake/OpenCVDetectCXXCompiler.cmake @@ -76,17 +76,27 @@ elseif(CMAKE_COMPILER_IS_GNUCXX) OUTPUT_STRIP_TRAILING_WHITESPACE) # Typical output in CMAKE_OPENCV_GCC_VERSION_FULL: "c+//0 (whatever) 4.2.3 (...)" - # Look for the version number + # Look for the version number, major.minor.build string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}") - if(NOT CMAKE_GCC_REGEX_VERSION) + if(NOT CMAKE_GCC_REGEX_VERSION)#major.minor string(REGEX MATCH "[0-9]+\\.[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}") endif() - # Split the three parts: - string(REGEX MATCHALL "[0-9]+" CMAKE_OPENCV_GCC_VERSIONS "${CMAKE_GCC_REGEX_VERSION}") + if(CMAKE_GCC_REGEX_VERSION) + # Split the parts: + string(REGEX MATCHALL "[0-9]+" CMAKE_OPENCV_GCC_VERSIONS "${CMAKE_GCC_REGEX_VERSION}") - list(GET CMAKE_OPENCV_GCC_VERSIONS 0 CMAKE_OPENCV_GCC_VERSION_MAJOR) - list(GET CMAKE_OPENCV_GCC_VERSIONS 1 CMAKE_OPENCV_GCC_VERSION_MINOR) + list(GET CMAKE_OPENCV_GCC_VERSIONS 0 CMAKE_OPENCV_GCC_VERSION_MAJOR) + list(GET CMAKE_OPENCV_GCC_VERSIONS 1 CMAKE_OPENCV_GCC_VERSION_MINOR) + else()#compiler returned just the major version number + string(REGEX MATCH "[0-9]+" CMAKE_GCC_REGEX_VERSION "${CMAKE_OPENCV_GCC_VERSION_FULL}") + if(NOT CMAKE_GCC_REGEX_VERSION)#compiler did not return anything reasonable + set(CMAKE_GCC_REGEX_VERSION "0") + message(WARNING "GCC version not detected!") + endif() + set(CMAKE_OPENCV_GCC_VERSION_MAJOR ${CMAKE_GCC_REGEX_VERSION}) + set(CMAKE_OPENCV_GCC_VERSION_MINOR 0) + endif() set(CMAKE_OPENCV_GCC_VERSION ${CMAKE_OPENCV_GCC_VERSION_MAJOR}${CMAKE_OPENCV_GCC_VERSION_MINOR}) math(EXPR CMAKE_OPENCV_GCC_VERSION_NUM "${CMAKE_OPENCV_GCC_VERSION_MAJOR}*100 + ${CMAKE_OPENCV_GCC_VERSION_MINOR}") @@ -116,6 +126,12 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64.*|AARCH64.*)") set(AARCH64 1) endif() +# Workaround for 32-bit operating systems on 64-bit x86_64 processor +if(X86_64 AND CMAKE_SIZEOF_VOID_P EQUAL 4 AND NOT FORCE_X86_64) + message(STATUS "sizeof(void) = 4 on x86 / x86_64 processor. Assume 32-bit compilation mode (X86=1)") + unset(X86_64) + set(X86 1) +endif() # Similar code exists in OpenCVConfig.cmake if(NOT DEFINED OpenCV_STATIC) diff --git a/cmake/OpenCVFindLibsVideo.cmake b/cmake/OpenCVFindLibsVideo.cmake index 4c4081d37..cce583b5d 100644 --- a/cmake/OpenCVFindLibsVideo.cmake +++ b/cmake/OpenCVFindLibsVideo.cmake @@ -318,10 +318,18 @@ if(WITH_GPHOTO2) CHECK_MODULE(libgphoto2 HAVE_GPHOTO2) endif(WITH_GPHOTO2) -# --- VA-API --- -if(WITH_VAAPI) - include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindVAAPI.cmake") - if(VAAPI_IOCL_INCLUDE_DIR) - ocv_include_directories(${VAAPI_IOCL_INCLUDE_DIR}) +# --- VA & VA_INTEL --- +if(WITH_VA_INTEL) + include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindVA_INTEL.cmake") + if(VA_INTEL_IOCL_INCLUDE_DIR) + ocv_include_directories(${VA_INTEL_IOCL_INCLUDE_DIR}) endif() -endif(WITH_VAAPI) + set(WITH_VA YES) +endif(WITH_VA_INTEL) + +if(WITH_VA) + include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindVA.cmake") + if(VA_INCLUDE_DIR) + ocv_include_directories(${VA_INCLUDE_DIR}) + endif() +endif(WITH_VA) diff --git a/cmake/OpenCVFindVA.cmake b/cmake/OpenCVFindVA.cmake new file mode 100644 index 000000000..5079e5631 --- /dev/null +++ b/cmake/OpenCVFindVA.cmake @@ -0,0 +1,19 @@ +# Main variables: +# HAVE_VA for conditional compilation OpenCV with/without libva + +if(UNIX AND NOT ANDROID) + find_path( + VA_INCLUDE_DIR + NAMES va/va.h + PATHS "/usr/include" + PATH_SUFFIXES include + DOC "Path to libva headers") +endif() + +if(VA_INCLUDE_DIR) + set(HAVE_VA TRUE) + set(VA_LIBRARIES "-lva" "-lva-drm") +else() + set(HAVE_VA FALSE) + message(WARNING "libva installation is not found.") +endif() diff --git a/cmake/OpenCVFindVAAPI.cmake b/cmake/OpenCVFindVAAPI.cmake deleted file mode 100644 index 2cb56219e..000000000 --- a/cmake/OpenCVFindVAAPI.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# Main variables: -# VAAPI_MSDK_INCLUDE_DIR and VAAPI_IOCL_INCLUDE_DIR to use VAAPI -# HAVE_VAAPI for conditional compilation OpenCV with/without VAAPI - -# VAAPI_MSDK_ROOT - root of Intel MSDK installation -# VAAPI_IOCL_ROOT - root of Intel OCL installation - -if(UNIX AND NOT ANDROID) - if($ENV{VAAPI_MSDK_ROOT}) - set(VAAPI_MSDK_ROOT $ENV{VAAPI_MSDK_ROOT}) - else() - set(VAAPI_MSDK_ROOT "/opt/intel/mediasdk") - endif() - - if($ENV{VAAPI_IOCL_ROOT}) - set(VAAPI_IOCL_ROOT $ENV{VAAPI_IOCL_ROOT}) - else() - set(VAAPI_IOCL_ROOT "/opt/intel/opencl") - endif() - - find_path( - VAAPI_MSDK_INCLUDE_DIR - NAMES mfxdefs.h - PATHS ${VAAPI_MSDK_ROOT} - PATH_SUFFIXES include - DOC "Path to Intel MSDK headers") - - find_path( - VAAPI_IOCL_INCLUDE_DIR - NAMES CL/va_ext.h - PATHS ${VAAPI_IOCL_ROOT} - PATH_SUFFIXES include - DOC "Path to Intel OpenCL headers") -endif() - -if(VAAPI_MSDK_INCLUDE_DIR AND VAAPI_IOCL_INCLUDE_DIR) - set(HAVE_VAAPI TRUE) - set(VAAPI_EXTRA_LIBS "-lva" "-lva-drm") -else() - set(HAVE_VAAPI FALSE) - message(WARNING "Intel MSDK & OpenCL installation is not found.") -endif() - -mark_as_advanced(FORCE VAAPI_MSDK_INCLUDE_DIR VAAPI_IOCL_INCLUDE_DIR) diff --git a/cmake/OpenCVFindVA_INTEL.cmake b/cmake/OpenCVFindVA_INTEL.cmake new file mode 100644 index 000000000..8cb6c2594 --- /dev/null +++ b/cmake/OpenCVFindVA_INTEL.cmake @@ -0,0 +1,44 @@ +# Main variables: +# VA_INTEL_MSDK_INCLUDE_DIR and VA_INTEL_IOCL_INCLUDE_DIR to use VA_INTEL +# HAVE_VA_INTEL for conditional compilation OpenCV with/without VA_INTEL + +# VA_INTEL_MSDK_ROOT - root of Intel MSDK installation +# VA_INTEL_IOCL_ROOT - root of Intel OCL installation + +if(UNIX AND NOT ANDROID) + if($ENV{VA_INTEL_MSDK_ROOT}) + set(VA_INTEL_MSDK_ROOT $ENV{VA_INTEL_MSDK_ROOT}) + else() + set(VA_INTEL_MSDK_ROOT "/opt/intel/mediasdk") + endif() + + if($ENV{VA_INTEL_IOCL_ROOT}) + set(VA_INTEL_IOCL_ROOT $ENV{VA_INTEL_IOCL_ROOT}) + else() + set(VA_INTEL_IOCL_ROOT "/opt/intel/opencl") + endif() + + find_path( + VA_INTEL_MSDK_INCLUDE_DIR + NAMES mfxdefs.h + PATHS ${VA_INTEL_MSDK_ROOT} + PATH_SUFFIXES include + DOC "Path to Intel MSDK headers") + + find_path( + VA_INTEL_IOCL_INCLUDE_DIR + NAMES CL/va_ext.h + PATHS ${VA_INTEL_IOCL_ROOT} + PATH_SUFFIXES include + DOC "Path to Intel OpenCL headers") +endif() + +if(VA_INTEL_MSDK_INCLUDE_DIR AND VA_INTEL_IOCL_INCLUDE_DIR) + set(HAVE_VA_INTEL TRUE) + set(VA_INTEL_LIBRARIES "-lva" "-lva-drm") +else() + set(HAVE_VA_INTEL FALSE) + message(WARNING "Intel MSDK & OpenCL installation is not found.") +endif() + +mark_as_advanced(FORCE VA_INTEL_MSDK_INCLUDE_DIR VA_INTEL_IOCL_INCLUDE_DIR) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 30325eb30..92894b8b8 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -26,6 +26,7 @@ # To control the setup of the module you could also set: # the_description - text to be used as current module description +# the_label - label for current module # OPENCV_MODULE_TYPE - STATIC|SHARED - set to force override global settings for current module # OPENCV_MODULE_IS_PART_OF_WORLD - ON|OFF (default ON) - should the module be added to the opencv_world? # BUILD_${the_module}_INIT - ON|OFF (default ON) - initial value for BUILD_${the_module} @@ -56,6 +57,8 @@ foreach(mod ${OPENCV_MODULES_BUILD} ${OPENCV_MODULES_DISABLED_USER} ${OPENCV_MOD if(HAVE_${mod}) unset(HAVE_${mod} CACHE) endif() + unset(OPENCV_MODULE_${mod}_DEPS CACHE) + unset(OPENCV_MODULE_${mod}_DEPS_EXT CACHE) unset(OPENCV_MODULE_${mod}_REQ_DEPS CACHE) unset(OPENCV_MODULE_${mod}_OPT_DEPS CACHE) unset(OPENCV_MODULE_${mod}_PRIVATE_REQ_DEPS CACHE) @@ -189,6 +192,15 @@ macro(ocv_add_module _name) set(OPENCV_MODULE_${the_module}_IS_PART_OF_WORLD OFF CACHE INTERNAL "") endif() + if(NOT DEFINED the_label) + if(OPENCV_PROCESSING_EXTRA_MODULES) + set(the_label "Extra") + else() + set(the_label "Main") + endif() + endif() + set(OPENCV_MODULE_${the_module}_LABEL "${the_label};${the_module}" CACHE INTERNAL "") + if(BUILD_${the_module}) set(OPENCV_MODULES_BUILD ${OPENCV_MODULES_BUILD} "${the_module}" CACHE INTERNAL "List of OpenCV modules included into the build") else() @@ -471,7 +483,6 @@ function(__ocv_resolve_dependencies) # reorder dependencies foreach(m ${OPENCV_MODULES_BUILD}) __ocv_sort_modules_by_deps(OPENCV_MODULE_${m}_DEPS) - ocv_list_sort(OPENCV_MODULE_${m}_DEPS_EXT) set(LINK_DEPS ${OPENCV_MODULE_${m}_DEPS}) @@ -762,6 +773,10 @@ macro(_ocv_create_module) unset(sub_links) unset(cuda_objs) + set_target_properties(${the_module} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};Module") + set_source_files_properties(${OPENCV_MODULE_${the_module}_HEADERS} ${OPENCV_MODULE_${the_module}_SOURCES} ${${the_module}_pch} + PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};Module") + ocv_target_link_libraries(${the_module} ${OPENCV_MODULE_${the_module}_DEPS_TO_LINK}) ocv_target_link_libraries(${the_module} LINK_INTERFACE_LIBRARIES ${OPENCV_MODULE_${the_module}_DEPS_TO_LINK}) ocv_target_link_libraries(${the_module} ${OPENCV_MODULE_${the_module}_DEPS_EXT} ${OPENCV_LINKER_LIBS} ${IPP_LIBS} ${ARGN}) @@ -969,6 +984,10 @@ function(ocv_add_perf_tests) ocv_target_link_libraries(${the_target} ${perf_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS}) add_dependencies(opencv_perf_tests ${the_target}) + set_target_properties(${the_target} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};PerfTest") + set_source_files_properties(${OPENCV_PERF_${the_module}_SOURCES} ${${the_target}_pch} + PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};PerfTest") + # Additional target properties set_target_properties(${the_target} PROPERTIES DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" @@ -989,6 +1008,12 @@ function(ocv_add_perf_tests) if(NOT BUILD_opencv_world) _ocv_add_precompiled_headers(${the_target}) endif() + + ocv_add_test_from_target("${the_target}" "Performance" "${the_target}") + ocv_add_test_from_target("opencv_sanity_${name}" "Sanity" "${the_target}" + "--perf_min_samples=1" + "--perf_force_samples=1" + "--perf_verify_sanity") else(OCV_DEPENDENCIES_FOUND) # TODO: warn about unsatisfied dependencies endif(OCV_DEPENDENCIES_FOUND) @@ -1035,6 +1060,10 @@ function(ocv_add_accuracy_tests) ocv_target_link_libraries(${the_target} ${test_deps} ${OPENCV_MODULE_${the_module}_DEPS} ${OPENCV_LINKER_LIBS}) add_dependencies(opencv_tests ${the_target}) + set_target_properties(${the_target} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};AccuracyTest") + set_source_files_properties(${OPENCV_TEST_${the_module}_SOURCES} ${${the_target}_pch} + PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};AccuracyTest") + # Additional target properties set_target_properties(${the_target} PROPERTIES DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" @@ -1045,21 +1074,11 @@ function(ocv_add_accuracy_tests) set_target_properties(${the_target} PROPERTIES FOLDER "tests accuracy") endif() - enable_testing() - get_target_property(LOC ${the_target} LOCATION) - add_test(${the_target} "${LOC}") - - if(WINRT) - # removing APPCONTAINER from tests to run from console - # look for detailed description inside of ocv_create_module macro above - add_custom_command(TARGET "opencv_test_${name}" - POST_BUILD - COMMAND link.exe /edit /APPCONTAINER:NO $(TargetPath)) - endif() - if(NOT BUILD_opencv_world) _ocv_add_precompiled_headers(${the_target}) endif() + + ocv_add_test_from_target("${the_target}" "Accuracy" "${the_target}") else(OCV_DEPENDENCIES_FOUND) # TODO: warn about unsatisfied dependencies endif(OCV_DEPENDENCIES_FOUND) @@ -1092,6 +1111,10 @@ function(ocv_add_samples) ocv_target_link_libraries(${the_target} ${samples_deps}) set_target_properties(${the_target} PROPERTIES PROJECT_LABEL "(sample) ${name}") + set_target_properties(${the_target} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};Sample") + set_source_files_properties("${source}" + PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};Sample") + if(ENABLE_SOLUTION_FOLDERS) set_target_properties(${the_target} PROPERTIES OUTPUT_NAME "${module_id}-example-${name}" diff --git a/cmake/OpenCVPCHSupport.cmake b/cmake/OpenCVPCHSupport.cmake index 1c03f36f9..910235eaa 100644 --- a/cmake/OpenCVPCHSupport.cmake +++ b/cmake/OpenCVPCHSupport.cmake @@ -277,7 +277,7 @@ MACRO(ADD_PRECOMPILED_HEADER _targetName _input) ADD_CUSTOM_COMMAND( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_name}" - COMMAND ${CMAKE_COMMAND} -E copy "${_input}" "${CMAKE_CURRENT_BINARY_DIR}/${_name}" # ensure same directory! Required by gcc + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_input}" "${CMAKE_CURRENT_BINARY_DIR}/${_name}" # ensure same directory! Required by gcc DEPENDS "${_input}" ) diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index 59d602c5d..21a82a478 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -20,21 +20,24 @@ endif(NOT OPENCV_CUSTOM_PACKAGE_INFO) #arch if(X86) - set(CPACK_DEBIAN_ARCHITECTURE "i386") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386") set(CPACK_RPM_PACKAGE_ARCHITECTURE "i686") elseif(X86_64) - set(CPACK_DEBIAN_ARCHITECTURE "amd64") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64") set(CPACK_RPM_PACKAGE_ARCHITECTURE "x86_64") elseif(ARM) - set(CPACK_DEBIAN_ARCHITECTURE "armhf") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf") set(CPACK_RPM_PACKAGE_ARCHITECTURE "armhf") +elseif(AARCH64) + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64") + set(CPACK_RPM_PACKAGE_ARCHITECTURE "aarch64") else() - set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) set(CPACK_RPM_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) endif() if(CPACK_GENERATOR STREQUAL "DEB") - set(OPENCV_PACKAGE_ARCH_SUFFIX ${CPACK_DEBIAN_ARCHITECTURE}) + set(OPENCV_PACKAGE_ARCH_SUFFIX ${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}) elseif(CPACK_GENERATOR STREQUAL "RPM") set(OPENCV_PACKAGE_ARCH_SUFFIX ${CPACK_RPM_PACKAGE_ARCHITECTURE}) else() @@ -96,6 +99,46 @@ if(HAVE_CUDA) set(CPACK_COMPONENT_dev_DEPENDS libs) endif() +if(HAVE_TBB AND NOT BUILD_TBB) + if(CPACK_DEB_DEV_PACKAGE_DEPENDS) + set(CPACK_DEB_DEV_PACKAGE_DEPENDS "${CPACK_DEB_DEV_PACKAGE_DEPENDS}, libtbb-dev") + else() + set(CPACK_DEB_DEV_PACKAGE_DEPENDS "libtbb-dev") + endif() +endif() + +set(STD_OPENCV_LIBS opencv-data) +set(STD_OPENCV_DEV libopencv-dev) + +foreach(module calib3d core cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters + cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping + cudev features2d flann hal highgui imgcodecs imgproc ml objdetect ocl + photo shape stitching superres ts video videoio videostab viz) + if(HAVE_opencv_${module}) + list(APPEND STD_OPENCV_LIBS "libopencv-${module}3.0") + list(APPEND STD_OPENCV_DEV "libopencv-${module}-dev") + endif() +endforeach() + +string(REPLACE ";" ", " CPACK_COMPONENT_LIBS_CONFLICTS "${STD_OPENCV_LIBS}") +string(REPLACE ";" ", " CPACK_COMPONENT_LIBS_PROVIDES "${STD_OPENCV_LIBS}") +string(REPLACE ";" ", " CPACK_COMPONENT_LIBS_REPLACES "${STD_OPENCV_LIBS}") + +string(REPLACE ";" ", " CPACK_COMPONENT_DEV_CONFLICTS "${STD_OPENCV_DEV}") +string(REPLACE ";" ", " CPACK_COMPONENT_DEV_PROVIDES "${STD_OPENCV_DEV}") +string(REPLACE ";" ", " CPACK_COMPONENT_DEV_REPLACES "${STD_OPENCV_DEV}") + +set(CPACK_COMPONENT_PYTHON_CONFLICTS python-opencv) +set(CPACK_COMPONENT_PYTHON_PROVIDES python-opencv) +set(CPACK_COMPONENT_PYTHON_REPLACES python-opencv) + +set(CPACK_COMPONENT_JAVA_CONFLICTS "libopencv3.0-java, libopencv3.0-jni") +set(CPACK_COMPONENT_JAVA_PROVIDES "libopencv3.0-java, libopencv3.0-jni") +set(CPACK_COMPONENT_JAVA_REPLACES "libopencv3.0-java, libopencv3.0-jni") + +set(CPACK_COMPONENT_DOCS_CONFLICTS opencv-doc) +set(CPACK_COMPONENT_SAMPLES_CONFLICTS opencv-doc) + if(NOT OPENCV_CUSTOM_PACKAGE_INFO) set(CPACK_COMPONENT_LIBS_DESCRIPTION "Open Computer Vision Library") set(CPACK_DEBIAN_COMPONENT_LIBS_NAME "lib${CMAKE_PROJECT_NAME}") diff --git a/cmake/OpenCVUtils.cmake b/cmake/OpenCVUtils.cmake index e105f8726..e4e8771bf 100644 --- a/cmake/OpenCVUtils.cmake +++ b/cmake/OpenCVUtils.cmake @@ -911,3 +911,32 @@ function(ocv_download) set(DOWNLOAD_PACKAGE_LOCATION ${DOWNLOAD_TARGET} PARENT_SCOPE) endfunction() + +function(ocv_add_test_from_target test_name test_kind the_target) + if(CMAKE_VERSION VERSION_GREATER "2.8" AND NOT CMAKE_CROSSCOMPILING) + if(NOT "${test_kind}" MATCHES "^(Accuracy|Performance|Sanity)$") + message(FATAL_ERROR "Unknown test kind : ${test_kind}") + endif() + if(NOT TARGET "${the_target}") + message(FATAL_ERROR "${the_target} is not a CMake target") + endif() + + string(TOLOWER "${test_kind}" test_kind_lower) + set(test_report_dir "${CMAKE_BINARY_DIR}/test-reports/${test_kind_lower}") + file(MAKE_DIRECTORY "${test_report_dir}") + + add_test(NAME "${test_name}" + COMMAND "${the_target}" + "--gtest_output=xml:${the_target}.xml" + ${ARGN}) + + set_tests_properties("${test_name}" PROPERTIES + LABELS "${OPENCV_MODULE_${the_module}_LABEL};${test_kind}" + WORKING_DIRECTORY "${test_report_dir}") + + if(OPENCV_TEST_DATA_PATH) + set_tests_properties("${test_name}" PROPERTIES + ENVIRONMENT "OPENCV_TEST_DATA_PATH=${OPENCV_TEST_DATA_PATH}") + endif() + endif() +endfunction() diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index fce5748c2..608372967 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -189,5 +189,8 @@ /* gPhoto2 library */ #cmakedefine HAVE_GPHOTO2 -/* Intel VA-API */ -#cmakedefine HAVE_VAAPI +/* VA library (libva) */ +#cmakedefine HAVE_VA + +/* Intel VA-API/OpenCL */ +#cmakedefine HAVE_VA_INTEL diff --git a/cmake/templates/opencv_run_all_tests_unix.sh.in b/cmake/templates/opencv_run_all_tests_unix.sh.in index 7b946af13..f92d7c613 100644 --- a/cmake/templates/opencv_run_all_tests_unix.sh.in +++ b/cmake/templates/opencv_run_all_tests_unix.sh.in @@ -55,6 +55,15 @@ OPENCV_TEST_PATH=@CMAKE_INSTALL_PREFIX@/@OPENCV_TEST_INSTALL_PATH@ OPENCV_PYTHON_TESTS=@OPENCV_PYTHON_TESTS_LIST@ export OPENCV_TEST_DATA_PATH=@CMAKE_INSTALL_PREFIX@/share/OpenCV/testdata +CUR_DIR=`pwd` +if [ -d "$CUR_DIR" -a -w "$CUR_DIR" ]; then + echo "${TEXT_CYAN}CUR_DIR : $CUR_DIR${TEXT_RESET}" +else + echo "${TEXT_RED}Error: Do not have permissions to write to $CUR_DIR${TEXT_RESET}" + echo "${TEXT_RED}Please run the script from directory with write access${TEXT_RESET}" + exit 1 +fi + # Run tests SUMMARY_STATUS=0 @@ -64,9 +73,8 @@ PASSED_TESTS="" for t in "$OPENCV_TEST_PATH/"opencv_test_* "$OPENCV_TEST_PATH/"opencv_perf_*; do test_name=`basename "$t"` - report="$test_name-`date --rfc-3339=date`.xml" - cmd="$t --perf_min_samples=1 --perf_force_samples=1 --gtest_output=xml:\"$report\"" + cmd="$t --perf_min_samples=1 --perf_force_samples=1 --gtest_output=xml:$test_name.xml" seg_reg="s/^/${TEXT_CYAN}[$test_name]${TEXT_RESET} /" # append test name if [ $COLOR_OUTPUT -eq 1 ]; then @@ -79,7 +87,7 @@ do fi echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RUN : $cmd" - $cmd | sed -r "$seg_reg" + eval "$cmd" | tee "$test_name.log" | sed -r "$seg_reg" ret=${PIPESTATUS[0]} echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RETURN_CODE : $ret" @@ -98,14 +106,13 @@ done for t in $OPENCV_PYTHON_TESTS; do test_name=`basename "$t"` - report="$test_name-`date --rfc-3339=date`.xml" - cmd="py.test --junitxml $report \"$OPENCV_TEST_PATH\"/$t" + cmd="py.test --junitxml $test_name.xml \"$OPENCV_TEST_PATH\"/$t" seg_reg="s/^/${TEXT_CYAN}[$test_name]${TEXT_RESET} /" # append test name echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RUN : $cmd" - eval "$cmd" | sed -r "$seg_reg" + eval "$cmd" | tee "$test_name.log" | sed -r "$seg_reg" ret=${PIPESTATUS[0]} echo "${TEXT_CYAN}[$test_name]${TEXT_RESET} RETURN_CODE : $ret" diff --git a/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown b/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown index f1fc1e0ec..e2c0ed428 100644 --- a/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown +++ b/doc/py_tutorials/py_feature2d/py_brief/py_brief.markdown @@ -48,6 +48,8 @@ BRIEF in OpenCV Below code shows the computation of BRIEF descriptors with the help of CenSurE detector. (CenSurE detector is called STAR detector in OpenCV) + +note, that you need [opencv contrib](https://github.com/Itseez/opencv_contrib)) to use this. @code{.py} import numpy as np import cv2 @@ -55,11 +57,11 @@ from matplotlib import pyplot as plt img = cv2.imread('simple.jpg',0) -# Initiate STAR detector -star = cv2.FeatureDetector_create("STAR") +# Initiate FAST detector +star = cv2.xfeatures2d.StarDetector_create() # Initiate BRIEF extractor -brief = cv2.DescriptorExtractor_create("BRIEF") +brief = cv2.BriefDescriptorExtractor_create() # find the keypoints with STAR kp = star.detect(img,None) diff --git a/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown b/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown index aa45c325d..1534c57ac 100644 --- a/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown +++ b/doc/py_tutorials/py_feature2d/py_fast/py_fast.markdown @@ -101,7 +101,7 @@ from matplotlib import pyplot as plt img = cv2.imread('simple.jpg',0) # Initiate FAST object with default values -fast = cv2.FastFeatureDetector() +fast = cv2.FastFeatureDetector_create() # find and draw the keypoints kp = fast.detect(img,None) diff --git a/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown b/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown index 4f5a3234d..4f5efa4a8 100644 --- a/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown +++ b/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown @@ -44,7 +44,7 @@ img1 = cv2.imread('box.png',0) # queryImage img2 = cv2.imread('box_in_scene.png',0) # trainImage # Initiate SIFT detector -sift = cv2.SIFT() +sift = cv2.xfeatures2d.SIFT_create() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) @@ -78,7 +78,7 @@ if len(good)>MIN_MATCH_COUNT: M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0) matchesMask = mask.ravel().tolist() - h,w = img1.shape + h,w,d = img1.shape pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2) dst = cv2.perspectiveTransform(pts,M) diff --git a/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.markdown b/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.markdown index 4cb01e32a..7297eb403 100644 --- a/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.markdown +++ b/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.markdown @@ -77,7 +77,7 @@ See the example below: import cv2 import numpy as np -filename = 'chessboard.jpg' +filename = 'chessboard.png' img = cv2.imread(filename) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) diff --git a/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown b/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown index 8130f39ab..c1917eb1a 100644 --- a/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown +++ b/doc/py_tutorials/py_feature2d/py_orb/py_orb.markdown @@ -69,8 +69,8 @@ from matplotlib import pyplot as plt img = cv2.imread('simple.jpg',0) -# Initiate STAR detector -orb = cv2.ORB() +# Initiate ORB detector +orb = cv2.ORB_create() # find the keypoints with ORB kp = orb.detect(img,None) diff --git a/doc/py_tutorials/py_feature2d/py_shi_tomasi/py_shi_tomasi.markdown b/doc/py_tutorials/py_feature2d/py_shi_tomasi/py_shi_tomasi.markdown index d42b10ba2..5731e2157 100644 --- a/doc/py_tutorials/py_feature2d/py_shi_tomasi/py_shi_tomasi.markdown +++ b/doc/py_tutorials/py_feature2d/py_shi_tomasi/py_shi_tomasi.markdown @@ -50,7 +50,7 @@ import numpy as np import cv2 from matplotlib import pyplot as plt -img = cv2.imread('simple.jpg') +img = cv2.imread('blox.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) corners = cv2.goodFeaturesToTrack(gray,25,0.01,10) diff --git a/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown b/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown index 05226d58e..b12505adc 100644 --- a/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown +++ b/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown @@ -104,7 +104,7 @@ greater than 0.8, they are rejected. It eliminaters around 90% of false matches So this is a summary of SIFT algorithm. For more details and understanding, reading the original paper is highly recommended. Remember one thing, this algorithm is patented. So this algorithm is -included in Non-free module in OpenCV. +included in [the opencv contrib repo](https://github.com/Itseez/opencv_contrib) SIFT in OpenCV -------------- @@ -119,7 +119,7 @@ import numpy as np img = cv2.imread('home.jpg') gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) -sift = cv2.SIFT() +sift = cv2.xfeatures2d.SIFT_create() kp = sift.detect(gray,None) img=cv2.drawKeypoints(gray,kp) @@ -151,7 +151,7 @@ Now to calculate the descriptor, OpenCV provides two methods. We will see the second method: @code{.py} -sift = cv2.SIFT() +sift = cv2.xfeatures2d.SIFT_create() kp, des = sift.detectAndCompute(gray,None) @endcode Here kp will be a list of keypoints and des is a numpy array of shape diff --git a/doc/py_tutorials/py_feature2d/py_surf_intro/py_surf_intro.markdown b/doc/py_tutorials/py_feature2d/py_surf_intro/py_surf_intro.markdown index 21998fede..7d5bd93fe 100644 --- a/doc/py_tutorials/py_feature2d/py_surf_intro/py_surf_intro.markdown +++ b/doc/py_tutorials/py_feature2d/py_surf_intro/py_surf_intro.markdown @@ -80,7 +80,7 @@ examples are shown in Python terminal since it is just same as SIFT only. # Create SURF object. You can specify params here or later. # Here I set Hessian Threshold to 400 ->>> surf = cv2.SURF(400) +>>> surf = cv2.xfeatures2d.SURF_create(400) # Find keypoints and descriptors directly >>> kp, des = surf.detectAndCompute(img,None) @@ -92,12 +92,12 @@ examples are shown in Python terminal since it is just same as SIFT only. While matching, we may need all those features, but not now. So we increase the Hessian Threshold. @code{.py} # Check present Hessian threshold ->>> print surf.hessianThreshold +>>> print surf.getHessianThreshold() 400.0 # We set it to some 50000. Remember, it is just for representing in picture. # In actual cases, it is better to have a value 300-500 ->>> surf.hessianThreshold = 50000 +>>> surf.setHessianThreshold(50000) # Again compute keypoints and check its number. >>> kp, des = surf.detectAndCompute(img,None) @@ -119,10 +119,10 @@ on wings of butterfly. You can test it with other images. Now I want to apply U-SURF, so that it won't find the orientation. @code{.py} # Check upright flag, if it False, set it to True ->>> print surf.upright +>>> print surf.getUpright() False ->>> surf.upright = True +>>> surf.setUpright(True) # Recompute the feature points and draw it >>> kp = surf.detect(img,None) @@ -143,7 +143,7 @@ Finally we check the descriptor size and change it to 128 if it is only 64-dim. 64 # That means flag, "extended" is False. ->>> surf.extended +>>> surf.getExtended() False # So we make it to True to get 128-dim descriptors. diff --git a/doc/py_tutorials/py_gui/py_video_display/py_video_display.markdown b/doc/py_tutorials/py_gui/py_video_display/py_video_display.markdown index b82e9f582..7b532ac9a 100644 --- a/doc/py_tutorials/py_gui/py_video_display/py_video_display.markdown +++ b/doc/py_tutorials/py_gui/py_video_display/py_video_display.markdown @@ -113,7 +113,7 @@ platform dependent. Following codecs works fine for me. - In OSX : *(I don't have access to OSX. Can some one fill this?)* FourCC code is passed as cv2.VideoWriter_fourcc('M','J','P','G') or -cv2.VideoWriter_fourcc(\*'MJPG) for MJPG. +cv2.VideoWriter_fourcc(\*'MJPG') for MJPG. Below code capture from a Camera, flip every frame in vertical direction and saves it. @code{.py} diff --git a/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown b/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown index 6bc5abb3e..8a1985007 100644 --- a/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown +++ b/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.markdown @@ -94,6 +94,8 @@ the weight vector \f$\beta\f$ and the bias \f$\beta_{0}\f$ of the optimal hyperp Source Code ----------- +@note The following code has been implemented with OpenCV 3.0 classes and functions. An equivalent version of the code using OpenCV 2.4 can be found in [this page.](http://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html#introductiontosvms) + @include cpp/tutorial_code/ml/introduction_to_svm/introduction_to_svm.cpp Explanation diff --git a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown index 4f8f8f34e..52b544dd0 100644 --- a/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown +++ b/doc/tutorials/ml/non_linear_svms/non_linear_svms.markdown @@ -89,6 +89,9 @@ Source Code You may also find the source code in `samples/cpp/tutorial_code/ml/non_linear_svms` folder of the OpenCV source library or [download it from here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp). +@note The following code has been implemented with OpenCV 3.0 classes and functions. An equivalent version of the code +using OpenCV 2.4 can be found in [this page.](http://docs.opencv.org/2.4/doc/tutorials/ml/non_linear_svms/non_linear_svms.html#nonlinearsvms) + @include cpp/tutorial_code/ml/non_linear_svms/non_linear_svms.cpp Explanation diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index c9dde993f..d2641fe87 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -154,7 +154,7 @@ struct CvCBQuad //static CvMat* debug_img = 0; static int icvGenerateQuads( CvCBQuad **quads, CvCBCorner **corners, - CvMemStorage *storage, CvMat *image, int flags ); + CvMemStorage *storage, CvMat *image, int flags, int *max_quad_buf_size); /*static int icvGenerateQuadsEx( CvCBQuad **out_quads, CvCBCorner **out_corners, @@ -174,7 +174,7 @@ static int icvCleanFoundConnectedQuads( int quad_count, static int icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, int *all_count, CvCBQuad **all_quads, CvCBCorner **corners, - CvSize pattern_size, CvMemStorage* storage ); + CvSize pattern_size, int max_quad_buf_size, CvMemStorage* storage ); static void icvOrderQuad(CvCBQuad *quad, CvCBCorner *corner, int common); @@ -185,7 +185,7 @@ static int icvTrimRow(CvCBQuad **quads, int count, int row, int dir); #endif static int icvAddOuterQuad(CvCBQuad *quad, CvCBQuad **quads, int quad_count, - CvCBQuad **all_quads, int all_count, CvCBCorner **corners); + CvCBQuad **all_quads, int all_count, CvCBCorner **corners, int max_quad_buf_size); static void icvRemoveQuadFromGroup(CvCBQuad **quads, int count, CvCBQuad *q0); @@ -314,6 +314,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // making it difficult to detect smaller squares. for( k = 0; k < 6; k++ ) { + int max_quad_buf_size = 0; for( dilations = min_dilations; dilations <= max_dilations; dilations++ ) { if (found) @@ -369,7 +370,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, cvRectangle( thresh_img, cvPoint(0,0), cvPoint(thresh_img->cols-1, thresh_img->rows-1), CV_RGB(255,255,255), 3, 8); - quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags ); + quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags, &max_quad_buf_size); PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num); } @@ -409,8 +410,8 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // allocate extra for adding in icvOrderFoundQuads cvFree(&quad_group); cvFree(&corner_group); - quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * (quad_count+quad_count / 2)); - corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * (quad_count+quad_count / 2)*4 ); + quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size); + corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 ); for( group_idx = 0; ; group_idx++ ) { @@ -425,7 +426,7 @@ int cvFindChessboardCorners( const void* arr, CvSize pattern_size, // maybe delete or add some PRINTF("Starting ordering of inner quads\n"); count = icvOrderFoundConnectedQuads(count, quad_group, &quad_count, &quads, &corners, - pattern_size, storage ); + pattern_size, max_quad_buf_size, storage ); PRINTF("Orig count: %d After ordering: %d\n", icount, count); @@ -624,7 +625,7 @@ icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size ) static int icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, int *all_count, CvCBQuad **all_quads, CvCBCorner **corners, - CvSize pattern_size, CvMemStorage* storage ) + CvSize pattern_size, int max_quad_buf_size, CvMemStorage* storage ) { cv::Ptr temp_storage(cvCreateChildMemStorage( storage )); CvSeq* stack = cvCreateSeq( 0, sizeof(*stack), sizeof(void*), temp_storage ); @@ -804,15 +805,18 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, if (found > 0) { PRINTF("Found %d inner quads not connected to outer quads, repairing\n", found); - for (int i=0; icount < 4 && quads[i]->ordered) { - int added = icvAddOuterQuad(quads[i],quads,quad_count,all_quads,*all_count,corners); + int added = icvAddOuterQuad(quads[i],quads,quad_count,all_quads,*all_count,corners, max_quad_buf_size); *all_count += added; quad_count += added; } } + + if (*all_count >= max_quad_buf_size) + return 0; } @@ -855,11 +859,11 @@ icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads, static int icvAddOuterQuad( CvCBQuad *quad, CvCBQuad **quads, int quad_count, - CvCBQuad **all_quads, int all_count, CvCBCorner **corners ) + CvCBQuad **all_quads, int all_count, CvCBCorner **corners, int max_quad_buf_size ) { int added = 0; - for (int i=0; i<4; i++) // find no-neighbor corners + for (int i=0; i<4 && all_count < max_quad_buf_size; i++) // find no-neighbor corners { if (!quad->neighbors[i]) // ok, create and add neighbor { @@ -1649,7 +1653,7 @@ static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count ) static int icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, - CvMemStorage *storage, CvMat *image, int flags ) + CvMemStorage *storage, CvMat *image, int flags, int *max_quad_buf_size ) { int quad_count = 0; cv::Ptr temp_storage; @@ -1754,8 +1758,9 @@ icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners, cvEndFindContours( &scanner ); // allocate quad & corner buffers - *out_quads = (CvCBQuad*)cvAlloc((root->total+root->total / 2) * sizeof((*out_quads)[0])); - *out_corners = (CvCBCorner*)cvAlloc((root->total+root->total / 2) * 4 * sizeof((*out_corners)[0])); + *max_quad_buf_size = MAX(1, (root->total+root->total / 2)) * 2; + *out_quads = (CvCBQuad*)cvAlloc(*max_quad_buf_size * sizeof((*out_quads)[0])); + *out_corners = (CvCBCorner*)cvAlloc(*max_quad_buf_size * 4 * sizeof((*out_corners)[0])); // Create array of quads structures for( idx = 0; idx < root->total; idx++ ) diff --git a/modules/calib3d/src/fisheye.cpp b/modules/calib3d/src/fisheye.cpp index a11bea0ce..78c066afb 100644 --- a/modules/calib3d/src/fisheye.cpp +++ b/modules/calib3d/src/fisheye.cpp @@ -512,7 +512,7 @@ void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(InputArray K, Input OutputArray P, double balance, const Size& new_size, double fov_scale) { CV_Assert( K.size() == Size(3, 3) && (K.depth() == CV_32F || K.depth() == CV_64F)); - CV_Assert((D.empty() || D.total() == 4) && (D.depth() == CV_32F || D.depth() == CV_64F || D.empty())); + CV_Assert(D.empty() || ((D.total() == 4) && (D.depth() == CV_32F || D.depth() == CV_64F))); int w = image_size.width, h = image_size.height; balance = std::min(std::max(balance, 0.0), 1.0); @@ -694,12 +694,12 @@ double cv::fisheye::calibrate(InputArrayOfArrays objectPoints, InputArrayOfArray CV_Assert(!objectPoints.empty() && !imagePoints.empty() && objectPoints.total() == imagePoints.total()); CV_Assert(objectPoints.type() == CV_32FC3 || objectPoints.type() == CV_64FC3); CV_Assert(imagePoints.type() == CV_32FC2 || imagePoints.type() == CV_64FC2); - CV_Assert((!K.empty() && K.size() == Size(3,3)) || K.empty()); - CV_Assert((!D.empty() && D.total() == 4) || D.empty()); - CV_Assert((!rvecs.empty() && rvecs.channels() == 3) || rvecs.empty()); - CV_Assert((!tvecs.empty() && tvecs.channels() == 3) || tvecs.empty()); + CV_Assert(K.empty() || (K.size() == Size(3,3))); + CV_Assert(D.empty() || (D.total() == 4)); + CV_Assert(rvecs.empty() || (rvecs.channels() == 3)); + CV_Assert(tvecs.empty() || (tvecs.channels() == 3)); - CV_Assert(((flags & CALIB_USE_INTRINSIC_GUESS) && !K.empty() && !D.empty()) || !(flags & CALIB_USE_INTRINSIC_GUESS)); + CV_Assert((!K.empty() && !D.empty()) || !(flags & CALIB_USE_INTRINSIC_GUESS)); using namespace cv::internal; //-------------------------------Initialization @@ -825,12 +825,12 @@ double cv::fisheye::stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayO CV_Assert(imagePoints1.type() == CV_32FC2 || imagePoints1.type() == CV_64FC2); CV_Assert(imagePoints2.type() == CV_32FC2 || imagePoints2.type() == CV_64FC2); - CV_Assert((!K1.empty() && K1.size() == Size(3,3)) || K1.empty()); - CV_Assert((!D1.empty() && D1.total() == 4) || D1.empty()); - CV_Assert((!K2.empty() && K1.size() == Size(3,3)) || K2.empty()); - CV_Assert((!D2.empty() && D1.total() == 4) || D2.empty()); + CV_Assert(K1.empty() || (K1.size() == Size(3,3))); + CV_Assert(D1.empty() || (D1.total() == 4)); + CV_Assert(K2.empty() || (K1.size() == Size(3,3))); + CV_Assert(D2.empty() || (D1.total() == 4)); - CV_Assert(((flags & CALIB_FIX_INTRINSIC) && !K1.empty() && !K2.empty() && !D1.empty() && !D2.empty()) || !(flags & CALIB_FIX_INTRINSIC)); + CV_Assert((!K1.empty() && !K2.empty() && !D1.empty() && !D2.empty()) || !(flags & CALIB_FIX_INTRINSIC)); //-------------------------------Initialization diff --git a/modules/calib3d/src/main.cpp b/modules/calib3d/src/main.cpp new file mode 100644 index 000000000..127f86b26 --- /dev/null +++ b/modules/calib3d/src/main.cpp @@ -0,0 +1,52 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +// +// Library initialization file +// + +#include "precomp.hpp" + +IPP_INITIALIZER_AUTO + +/* End of file. */ diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index 760abefa8..ed83c0cb3 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -99,7 +99,7 @@ static bool ocl_prefilter_norm(InputArray _input, OutputArray _output, int winsi _output.create(input.size(), input.type()); output = _output.getUMat(); - size_t globalThreads[3] = { input.cols, input.rows, 1 }; + size_t globalThreads[3] = { (size_t)input.cols, (size_t)input.rows, 1 }; k.args(ocl::KernelArg::PtrReadOnly(input), ocl::KernelArg::PtrWriteOnly(output), input.rows, input.cols, prefilterCap, scale_g, scale_s); @@ -180,7 +180,7 @@ static bool ocl_prefilter_xsobel(InputArray _input, OutputArray _output, int pre _output.create(input.size(), input.type()); output = _output.getUMat(); - size_t globalThreads[3] = { input.cols, input.rows, 1 }; + size_t globalThreads[3] = { (size_t)input.cols, (size_t)input.rows, 1 }; k.args(ocl::KernelArg::PtrReadOnly(input), ocl::KernelArg::PtrWriteOnly(output), input.rows, input.cols, prefilterCap); @@ -927,8 +927,8 @@ static bool ocl_stereobm( InputArray _left, InputArray _right, int globalX = (disp.cols + sizeX - 1) / sizeX, globalY = (disp.rows + sizeY - 1) / sizeY; - size_t globalThreads[3] = {N, globalX, globalY}; - size_t localThreads[3] = {N, 1, 1}; + size_t globalThreads[3] = {(size_t)N, (size_t)globalX, (size_t)globalY}; + size_t localThreads[3] = {(size_t)N, 1, 1}; int idx = 0; idx = k.set(idx, ocl::KernelArg::PtrReadOnly(left)); diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index ef71a3f7f..15b35fcf1 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -1688,6 +1688,45 @@ void filterSpecklesImpl(cv::Mat& img, int newVal, int maxSpeckleSize, int maxDif } } +#ifdef HAVE_IPP +static bool ipp_filterSpeckles(Mat &img, int maxSpeckleSize, int newVal, int maxDiff) +{ +#if IPP_VERSION_X100 >= 810 + int type = img.type(); + Ipp32s bufsize = 0; + IppiSize roisize = { img.cols, img.rows }; + IppDataType datatype = type == CV_8UC1 ? ipp8u : ipp16s; + Ipp8u *pBuffer = NULL; + IppStatus status = ippStsNoErr; + + if(ippiMarkSpecklesGetBufferSize(roisize, datatype, CV_MAT_CN(type), &bufsize) < 0) + return false; + + pBuffer = (Ipp8u*)ippMalloc(bufsize); + if(!pBuffer && bufsize) + return false; + + if (type == CV_8UC1) + { + status = ippiMarkSpeckles_8u_C1IR(img.ptr(), (int)img.step, roisize, + (Ipp8u)newVal, maxSpeckleSize, (Ipp8u)maxDiff, ippiNormL1, pBuffer); + } + else + { + status = ippiMarkSpeckles_16s_C1IR(img.ptr(), (int)img.step, roisize, + (Ipp16s)newVal, maxSpeckleSize, (Ipp16s)maxDiff, ippiNormL1, pBuffer); + } + if(pBuffer) ippFree(pBuffer); + + if (status >= 0) + return true; +#else + CV_UNUSED(img); CV_UNUSED(maxSpeckleSize); CV_UNUSED(newVal); CV_UNUSED(maxDiff); +#endif + return false; +} +#endif + } void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSize, @@ -1700,37 +1739,7 @@ void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSi int newVal = cvRound(_newval), maxDiff = cvRound(_maxDiff); -#if IPP_VERSION_X100 >= 801 - CV_IPP_CHECK() - { - Ipp32s bufsize = 0; - IppiSize roisize = { img.cols, img.rows }; - IppDataType datatype = type == CV_8UC1 ? ipp8u : ipp16s; - - if (!__buf.needed() && (type == CV_8UC1 || type == CV_16SC1)) - { - IppStatus status = ippiMarkSpecklesGetBufferSize(roisize, datatype, CV_MAT_CN(type), &bufsize); - Ipp8u * buffer = ippsMalloc_8u(bufsize); - - if ((int)status >= 0) - { - if (type == CV_8UC1) - status = ippiMarkSpeckles_8u_C1IR(img.ptr(), (int)img.step, roisize, - (Ipp8u)newVal, maxSpeckleSize, (Ipp8u)maxDiff, ippiNormL1, buffer); - else - status = ippiMarkSpeckles_16s_C1IR(img.ptr(), (int)img.step, roisize, - (Ipp16s)newVal, maxSpeckleSize, (Ipp16s)maxDiff, ippiNormL1, buffer); - } - - if (status >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } - } -#endif + CV_IPP_RUN(IPP_VERSION_X100 >= 810 && !__buf.needed() && (type == CV_8UC1 || type == CV_16SC1), ipp_filterSpeckles(img, maxSpeckleSize, newVal, maxDiff)); if (type == CV_8UC1) filterSpecklesImpl(img, newVal, maxSpeckleSize, maxDiff, _buf); diff --git a/modules/calib3d/test/test_fisheye.cpp b/modules/calib3d/test/test_fisheye.cpp index 4e7bf5363..32b77c654 100644 --- a/modules/calib3d/test/test_fisheye.cpp +++ b/modules/calib3d/test/test_fisheye.cpp @@ -101,15 +101,15 @@ TEST_F(fisheyeTest, projectPoints) TEST_F(fisheyeTest, DISABLED_undistortImage) { - cv::Matx33d K = this->K; - cv::Mat D = cv::Mat(this->D); + cv::Matx33d theK = this->K; + cv::Mat theD = cv::Mat(this->D); std::string file = combine(datasets_repository_path, "/calib-3_stereo_from_JY/left/stereo_pair_014.jpg"); - cv::Matx33d newK = K; + cv::Matx33d newK = theK; cv::Mat distorted = cv::imread(file), undistorted; { newK(0, 0) = 100; newK(1, 1) = 100; - cv::fisheye::undistortImage(distorted, undistorted, K, D, newK); + cv::fisheye::undistortImage(distorted, undistorted, theK, theD, newK); cv::Mat correct = cv::imread(combine(datasets_repository_path, "new_f_100.png")); if (correct.empty()) CV_Assert(cv::imwrite(combine(datasets_repository_path, "new_f_100.png"), undistorted)); @@ -118,8 +118,8 @@ TEST_F(fisheyeTest, DISABLED_undistortImage) } { double balance = 1.0; - cv::fisheye::estimateNewCameraMatrixForUndistortRectify(K, D, distorted.size(), cv::noArray(), newK, balance); - cv::fisheye::undistortImage(distorted, undistorted, K, D, newK); + cv::fisheye::estimateNewCameraMatrixForUndistortRectify(theK, theD, distorted.size(), cv::noArray(), newK, balance); + cv::fisheye::undistortImage(distorted, undistorted, theK, theD, newK); cv::Mat correct = cv::imread(combine(datasets_repository_path, "balance_1.0.png")); if (correct.empty()) CV_Assert(cv::imwrite(combine(datasets_repository_path, "balance_1.0.png"), undistorted)); @@ -129,8 +129,8 @@ TEST_F(fisheyeTest, DISABLED_undistortImage) { double balance = 0.0; - cv::fisheye::estimateNewCameraMatrixForUndistortRectify(K, D, distorted.size(), cv::noArray(), newK, balance); - cv::fisheye::undistortImage(distorted, undistorted, K, D, newK); + cv::fisheye::estimateNewCameraMatrixForUndistortRectify(theK, theD, distorted.size(), cv::noArray(), newK, balance); + cv::fisheye::undistortImage(distorted, undistorted, theK, theD, newK); cv::Mat correct = cv::imread(combine(datasets_repository_path, "balance_0.0.png")); if (correct.empty()) CV_Assert(cv::imwrite(combine(datasets_repository_path, "balance_0.0.png"), undistorted)); @@ -143,7 +143,7 @@ TEST_F(fisheyeTest, jacobians) { int n = 10; cv::Mat X(1, n, CV_64FC3); - cv::Mat om(3, 1, CV_64F), T(3, 1, CV_64F); + cv::Mat om(3, 1, CV_64F), theT(3, 1, CV_64F); cv::Mat f(2, 1, CV_64F), c(2, 1, CV_64F); cv::Mat k(4, 1, CV_64F); double alpha; @@ -156,8 +156,8 @@ TEST_F(fisheyeTest, jacobians) r.fill(om, cv::RNG::NORMAL, 0, 1); om = cv::abs(om); - r.fill(T, cv::RNG::NORMAL, 0, 1); - T = cv::abs(T); T.at(2) = 4; T *= 10; + r.fill(theT, cv::RNG::NORMAL, 0, 1); + theT = cv::abs(theT); theT.at(2) = 4; theT *= 10; r.fill(f, cv::RNG::NORMAL, 0, 1); f = cv::abs(f) * 1000; @@ -171,19 +171,19 @@ TEST_F(fisheyeTest, jacobians) alpha = 0.01*r.gaussian(1); cv::Mat x1, x2, xpred; - cv::Matx33d K(f.at(0), alpha * f.at(0), c.at(0), + cv::Matx33d theK(f.at(0), alpha * f.at(0), c.at(0), 0, f.at(1), c.at(1), 0, 0, 1); cv::Mat jacobians; - cv::fisheye::projectPoints(X, x1, om, T, K, k, alpha, jacobians); + cv::fisheye::projectPoints(X, x1, om, theT, theK, k, alpha, jacobians); //test on T: cv::Mat dT(3, 1, CV_64FC1); r.fill(dT, cv::RNG::NORMAL, 0, 1); - dT *= 1e-9*cv::norm(T); - cv::Mat T2 = T + dT; - cv::fisheye::projectPoints(X, x2, om, T2, K, k, alpha, cv::noArray()); + dT *= 1e-9*cv::norm(theT); + cv::Mat T2 = theT + dT; + cv::fisheye::projectPoints(X, x2, om, T2, theK, k, alpha, cv::noArray()); xpred = x1 + cv::Mat(jacobians.colRange(11,14) * dT).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); @@ -192,7 +192,7 @@ TEST_F(fisheyeTest, jacobians) r.fill(dom, cv::RNG::NORMAL, 0, 1); dom *= 1e-9*cv::norm(om); cv::Mat om2 = om + dom; - cv::fisheye::projectPoints(X, x2, om2, T, K, k, alpha, cv::noArray()); + cv::fisheye::projectPoints(X, x2, om2, theT, theK, k, alpha, cv::noArray()); xpred = x1 + cv::Mat(jacobians.colRange(8,11) * dom).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); @@ -200,8 +200,8 @@ TEST_F(fisheyeTest, jacobians) cv::Mat df(2, 1, CV_64FC1); r.fill(df, cv::RNG::NORMAL, 0, 1); df *= 1e-9*cv::norm(f); - cv::Matx33d K2 = K + cv::Matx33d(df.at(0), df.at(0) * alpha, 0, 0, df.at(1), 0, 0, 0, 0); - cv::fisheye::projectPoints(X, x2, om, T, K2, k, alpha, cv::noArray()); + cv::Matx33d K2 = theK + cv::Matx33d(df.at(0), df.at(0) * alpha, 0, 0, df.at(1), 0, 0, 0, 0); + cv::fisheye::projectPoints(X, x2, om, theT, K2, k, alpha, cv::noArray()); xpred = x1 + cv::Mat(jacobians.colRange(0,2) * df).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); @@ -209,8 +209,8 @@ TEST_F(fisheyeTest, jacobians) cv::Mat dc(2, 1, CV_64FC1); r.fill(dc, cv::RNG::NORMAL, 0, 1); dc *= 1e-9*cv::norm(c); - K2 = K + cv::Matx33d(0, 0, dc.at(0), 0, 0, dc.at(1), 0, 0, 0); - cv::fisheye::projectPoints(X, x2, om, T, K2, k, alpha, cv::noArray()); + K2 = theK + cv::Matx33d(0, 0, dc.at(0), 0, 0, dc.at(1), 0, 0, 0); + cv::fisheye::projectPoints(X, x2, om, theT, K2, k, alpha, cv::noArray()); xpred = x1 + cv::Mat(jacobians.colRange(2,4) * dc).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); @@ -219,7 +219,7 @@ TEST_F(fisheyeTest, jacobians) r.fill(dk, cv::RNG::NORMAL, 0, 1); dk *= 1e-9*cv::norm(k); cv::Mat k2 = k + dk; - cv::fisheye::projectPoints(X, x2, om, T, K, k2, alpha, cv::noArray()); + cv::fisheye::projectPoints(X, x2, om, theT, theK, k2, alpha, cv::noArray()); xpred = x1 + cv::Mat(jacobians.colRange(4,8) * dk).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); @@ -228,8 +228,8 @@ TEST_F(fisheyeTest, jacobians) r.fill(dalpha, cv::RNG::NORMAL, 0, 1); dalpha *= 1e-9*cv::norm(f); double alpha2 = alpha + dalpha.at(0); - K2 = K + cv::Matx33d(0, f.at(0) * dalpha.at(0), 0, 0, 0, 0, 0, 0, 0); - cv::fisheye::projectPoints(X, x2, om, T, K, k, alpha2, cv::noArray()); + K2 = theK + cv::Matx33d(0, f.at(0) * dalpha.at(0), 0, 0, 0, 0, 0, 0, 0); + cv::fisheye::projectPoints(X, x2, om, theT, theK, k, alpha2, cv::noArray()); xpred = x1 + cv::Mat(jacobians.col(14) * dalpha).reshape(2, 1); CV_Assert (cv::norm(x2 - xpred) < 1e-10); } @@ -259,14 +259,14 @@ TEST_F(fisheyeTest, Calibration) flag |= cv::fisheye::CALIB_CHECK_COND; flag |= cv::fisheye::CALIB_FIX_SKEW; - cv::Matx33d K; - cv::Vec4d D; + cv::Matx33d theK; + cv::Vec4d theD; - cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, K, D, + cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, theK, theD, cv::noArray(), cv::noArray(), flag, cv::TermCriteria(3, 20, 1e-6)); - EXPECT_MAT_NEAR(K, this->K, 1e-10); - EXPECT_MAT_NEAR(D, this->D, 1e-10); + EXPECT_MAT_NEAR(theK, this->K, 1e-10); + EXPECT_MAT_NEAR(theD, this->D, 1e-10); } TEST_F(fisheyeTest, Homography) @@ -303,15 +303,15 @@ TEST_F(fisheyeTest, Homography) int Np = imagePointsNormalized.cols; cv::calcCovarMatrix(_objectPoints, covObjectPoints, objectPointsMean, cv::COVAR_NORMAL | cv::COVAR_COLS); cv::SVD svd(covObjectPoints); - cv::Mat R(svd.vt); + cv::Mat theR(svd.vt); - if (cv::norm(R(cv::Rect(2, 0, 1, 2))) < 1e-6) - R = cv::Mat::eye(3,3, CV_64FC1); - if (cv::determinant(R) < 0) - R = -R; + if (cv::norm(theR(cv::Rect(2, 0, 1, 2))) < 1e-6) + theR = cv::Mat::eye(3,3, CV_64FC1); + if (cv::determinant(theR) < 0) + theR = -theR; - cv::Mat T = -R * objectPointsMean; - cv::Mat X_new = R * _objectPoints + T * cv::Mat::ones(1, Np, CV_64FC1); + cv::Mat theT = -theR * objectPointsMean; + cv::Mat X_new = theR * _objectPoints + theT * cv::Mat::ones(1, Np, CV_64FC1); cv::Mat H = cv::internal::ComputeHomography(imagePointsNormalized, X_new.rowRange(0, 2)); cv::Mat M = cv::Mat::ones(3, X_new.cols, CV_64FC1); @@ -355,19 +355,19 @@ TEST_F(fisheyeTest, EtimateUncertainties) flag |= cv::fisheye::CALIB_CHECK_COND; flag |= cv::fisheye::CALIB_FIX_SKEW; - cv::Matx33d K; - cv::Vec4d D; + cv::Matx33d theK; + cv::Vec4d theD; std::vector rvec; std::vector tvec; - cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, K, D, + cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, theK, theD, rvec, tvec, flag, cv::TermCriteria(3, 20, 1e-6)); cv::internal::IntrinsicParams param, errors; cv::Vec2d err_std; double thresh_cond = 1e6; int check_cond = 1; - param.Init(cv::Vec2d(K(0,0), K(1,1)), cv::Vec2d(K(0,2), K(1, 2)), D); + param.Init(cv::Vec2d(theK(0,0), theK(1,1)), cv::Vec2d(theK(0,2), theK(1, 2)), theD); param.isEstimate = std::vector(9, 1); param.isEstimate[4] = 0; @@ -399,12 +399,12 @@ TEST_F(fisheyeTest, rectify) cv::Matx33d K1 = this->K, K2 = K1; cv::Mat D1 = cv::Mat(this->D), D2 = D1; - cv::Vec3d T = this->T; - cv::Matx33d R = this->R; + cv::Vec3d theT = this->T; + cv::Matx33d theR = this->R; double balance = 0.0, fov_scale = 1.1; cv::Mat R1, R2, P1, P2, Q; - cv::fisheye::stereoRectify(K1, D1, K2, D2, calibration_size, R, T, R1, R2, P1, P2, Q, + cv::fisheye::stereoRectify(K1, D1, K2, D2, calibration_size, theR, theT, R1, R2, P1, P2, Q, cv::CALIB_ZERO_DISPARITY, requested_size, balance, fov_scale); cv::Mat lmapx, lmapy, rmapx, rmapy; @@ -468,8 +468,8 @@ TEST_F(fisheyeTest, stereoCalibrate) fs_object[cv::format("image_%d", i )] >> objectPoints[i]; fs_object.release(); - cv::Matx33d K1, K2, R; - cv::Vec3d T; + cv::Matx33d K1, K2, theR; + cv::Vec3d theT; cv::Vec4d D1, D2; int flag = 0; @@ -479,7 +479,7 @@ TEST_F(fisheyeTest, stereoCalibrate) // flag |= cv::fisheye::CALIB_FIX_INTRINSIC; cv::fisheye::stereoCalibrate(objectPoints, leftPoints, rightPoints, - K1, D1, K2, D2, imageSize, R, T, flag, + K1, D1, K2, D2, imageSize, theR, theT, flag, cv::TermCriteria(3, 12, 0)); cv::Matx33d R_correct( 0.9975587205950972, 0.06953016383322372, 0.006492709911733523, @@ -497,8 +497,8 @@ TEST_F(fisheyeTest, stereoCalibrate) cv::Vec4d D1_correct (-7.44253716539556e-05, -0.00702662033932424, 0.00737569823650885, -0.00342230256441771); cv::Vec4d D2_correct (-0.0130785435677431, 0.0284434505383497, -0.0360333869900506, 0.0144724062347222); - EXPECT_MAT_NEAR(R, R_correct, 1e-10); - EXPECT_MAT_NEAR(T, T_correct, 1e-10); + EXPECT_MAT_NEAR(theR, R_correct, 1e-10); + EXPECT_MAT_NEAR(theT, T_correct, 1e-10); EXPECT_MAT_NEAR(K1, K1_correct, 1e-10); EXPECT_MAT_NEAR(K2, K2_correct, 1e-10); @@ -536,8 +536,8 @@ TEST_F(fisheyeTest, stereoCalibrateFixIntrinsic) fs_object[cv::format("image_%d", i )] >> objectPoints[i]; fs_object.release(); - cv::Matx33d R; - cv::Vec3d T; + cv::Matx33d theR; + cv::Vec3d theT; int flag = 0; flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC; @@ -557,7 +557,7 @@ TEST_F(fisheyeTest, stereoCalibrateFixIntrinsic) cv::Vec4d D2 (-0.0130785435677431, 0.0284434505383497, -0.0360333869900506, 0.0144724062347222); cv::fisheye::stereoCalibrate(objectPoints, leftPoints, rightPoints, - K1, D1, K2, D2, imageSize, R, T, flag, + K1, D1, K2, D2, imageSize, theR, theT, flag, cv::TermCriteria(3, 12, 0)); cv::Matx33d R_correct( 0.9975587205950972, 0.06953016383322372, 0.006492709911733523, @@ -566,8 +566,8 @@ TEST_F(fisheyeTest, stereoCalibrateFixIntrinsic) cv::Vec3d T_correct(-0.099402724724121, 0.00270812139265413, 0.00129330292472699); - EXPECT_MAT_NEAR(R, R_correct, 1e-10); - EXPECT_MAT_NEAR(T, T_correct, 1e-10); + EXPECT_MAT_NEAR(theR, R_correct, 1e-10); + EXPECT_MAT_NEAR(theT, T_correct, 1e-10); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/core/CMakeLists.txt b/modules/core/CMakeLists.txt index dbedc5b06..14fac578a 100644 --- a/modules/core/CMakeLists.txt +++ b/modules/core/CMakeLists.txt @@ -1,7 +1,7 @@ set(the_description "The Core Functionality") ocv_add_module(core opencv_hal - PRIVATE_REQUIRED ${ZLIB_LIBRARIES} "${OPENCL_LIBRARIES}" + PRIVATE_REQUIRED ${ZLIB_LIBRARIES} "${OPENCL_LIBRARIES}" "${VA_LIBRARIES}" OPTIONAL opencv_cudev WRAP java python) diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index d7289a627..40d678206 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -2381,8 +2381,7 @@ class CV_EXPORTS LDA { public: /** @brief constructor - Initializes a LDA with num_components (default 0) and specifies how - samples are aligned (default dataAsRow=true). + Initializes a LDA with num_components (default 0). */ explicit LDA(int num_components = 0); @@ -2413,15 +2412,17 @@ public: */ ~LDA(); - /** Compute the discriminants for data in src and labels. + /** Compute the discriminants for data in src (row aligned) and labels. */ void compute(InputArrayOfArrays src, InputArray labels); /** Projects samples into the LDA subspace. + src may be one or more row aligned samples. */ Mat project(InputArray src); /** Reconstructs projections from the LDA subspace. + src may be one or more row aligned projections. */ Mat reconstruct(InputArray src); @@ -2437,11 +2438,10 @@ public: static Mat subspaceReconstruct(InputArray W, InputArray mean, InputArray src); protected: - bool _dataAsRow; + bool _dataAsRow; // unused, but needed for 3.0 ABI compatibility. int _num_components; Mat _eigenvectors; Mat _eigenvalues; - void lda(InputArrayOfArrays src, InputArray labels); }; diff --git a/modules/core/include/opencv2/core/base.hpp b/modules/core/include/opencv2/core/base.hpp index 95142c513..3ab0982ce 100644 --- a/modules/core/include/opencv2/core/base.hpp +++ b/modules/core/include/opencv2/core/base.hpp @@ -645,6 +645,7 @@ namespace cudev namespace ipp { +CV_EXPORTS int getIppFeatures(); CV_EXPORTS void setIppStatus(int status, const char * const funcname = NULL, const char * const filename = NULL, int line = 0); CV_EXPORTS int getIppStatus(); diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index e85bf6fa5..caeecbf80 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -496,6 +496,8 @@ struct CV_EXPORTS UMatData void* handle; void* userdata; int allocatorFlags_; + int mapcount; + UMatData* originalUMatData; }; @@ -1071,6 +1073,7 @@ public: @param m Destination matrix. If it does not have a proper size or type before the operation, it is reallocated. @param mask Operation mask. Its non-zero elements indicate which matrix elements need to be copied. + The mask has to be of type CV_8U and can have 1 or multiple channels. */ void copyTo( OutputArray m, InputArray mask ) const; diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index 2a17744e5..9e0fb8118 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -494,7 +494,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1) { - CV_StaticAssert(channels >= 2, "Matx should have at least 2 elaments."); + CV_StaticAssert(channels >= 2, "Matx should have at least 2 elements."); val[0] = v0; val[1] = v1; for(int i = 2; i < channels; i++) val[i] = _Tp(0); } @@ -502,7 +502,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2) { - CV_StaticAssert(channels >= 3, "Matx should have at least 3 elaments."); + CV_StaticAssert(channels >= 3, "Matx should have at least 3 elements."); val[0] = v0; val[1] = v1; val[2] = v2; for(int i = 3; i < channels; i++) val[i] = _Tp(0); } @@ -510,7 +510,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3) { - CV_StaticAssert(channels >= 4, "Matx should have at least 4 elaments."); + CV_StaticAssert(channels >= 4, "Matx should have at least 4 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; for(int i = 4; i < channels; i++) val[i] = _Tp(0); } @@ -518,7 +518,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4) { - CV_StaticAssert(channels >= 5, "Matx should have at least 5 elaments."); + CV_StaticAssert(channels >= 5, "Matx should have at least 5 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; for(int i = 5; i < channels; i++) val[i] = _Tp(0); } @@ -526,7 +526,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5) { - CV_StaticAssert(channels >= 6, "Matx should have at least 6 elaments."); + CV_StaticAssert(channels >= 6, "Matx should have at least 6 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; for(int i = 6; i < channels; i++) val[i] = _Tp(0); @@ -535,7 +535,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6) { - CV_StaticAssert(channels >= 7, "Matx should have at least 7 elaments."); + CV_StaticAssert(channels >= 7, "Matx should have at least 7 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; for(int i = 7; i < channels; i++) val[i] = _Tp(0); @@ -544,7 +544,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6) template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7) { - CV_StaticAssert(channels >= 8, "Matx should have at least 8 elaments."); + CV_StaticAssert(channels >= 8, "Matx should have at least 8 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; for(int i = 8; i < channels; i++) val[i] = _Tp(0); @@ -553,7 +553,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _T template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8) { - CV_StaticAssert(channels >= 9, "Matx should have at least 9 elaments."); + CV_StaticAssert(channels >= 9, "Matx should have at least 9 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; val[8] = v8; @@ -563,7 +563,7 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _T template inline Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9) { - CV_StaticAssert(channels >= 10, "Matx should have at least 10 elaments."); + CV_StaticAssert(channels >= 10, "Matx should have at least 10 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; val[8] = v8; val[9] = v9; @@ -574,20 +574,22 @@ Matx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _T template inline Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11) { - CV_StaticAssert(channels == 12, "Matx should have at least 12 elaments."); + CV_StaticAssert(channels >= 12, "Matx should have at least 12 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11; + for(int i = 12; i < channels; i++) val[i] = _Tp(0); } template inline Matx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11, _Tp v12, _Tp v13, _Tp v14, _Tp v15) { - CV_StaticAssert(channels == 16, "Matx should have at least 16 elaments."); + CV_StaticAssert(channels >= 16, "Matx should have at least 16 elements."); val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7; val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11; val[12] = v12; val[13] = v13; val[14] = v14; val[15] = v15; + for(int i = 16; i < channels; i++) val[i] = _Tp(0); } template inline diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 0e8765be1..c71ec626e 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -191,9 +191,16 @@ CV_EXPORTS void scalarToRawData(const cv::Scalar& s, void* buf, int type, int un \****************************************************************************************/ #ifdef HAVE_IPP -# include "ipp.h" +#include "ipp.h" -# define IPP_VERSION_X100 (IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR) +#ifndef IPP_VERSION_UPDATE // prior to 7.1 +#define IPP_VERSION_UPDATE 0 +#endif + +#define IPP_VERSION_X100 (IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR*10 + IPP_VERSION_UPDATE) + +// General define for ipp function disabling +#define IPP_DISABLE_BLOCK 0 #ifdef CV_MALLOC_ALIGN #undef CV_MALLOC_ALIGN @@ -234,8 +241,33 @@ static inline IppDataType ippiGetDataType(int depth) depth == CV_64F ? ipp64f : (IppDataType)-1; } +// IPP temporary buffer hepler +template +class IppAutoBuffer +{ +public: + IppAutoBuffer() { m_pBuffer = NULL; } + IppAutoBuffer(int size) { Alloc(size); } + ~IppAutoBuffer() { Release(); } + T* Alloc(int size) { m_pBuffer = (T*)ippMalloc(size); return m_pBuffer; } + void Release() { if(m_pBuffer) ippFree(m_pBuffer); } + inline operator T* () { return (T*)m_pBuffer;} + inline operator const T* () const { return (const T*)m_pBuffer;} +private: + // Disable copy operations + IppAutoBuffer(IppAutoBuffer &) {}; + IppAutoBuffer& operator =(const IppAutoBuffer &) {return *this;}; + + T* m_pBuffer; +}; + #else -# define IPP_VERSION_X100 0 +#define IPP_VERSION_X100 0 +#endif + +// There shoud be no API difference in OpenCV between ICV and IPP since 9.0 +#if (defined HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 900 +#undef HAVE_IPP_ICV_ONLY #endif #ifdef HAVE_IPP_ICV_ONLY @@ -244,6 +276,42 @@ static inline IppDataType ippiGetDataType(int depth) #define HAVE_ICV 0 #endif +#if defined HAVE_IPP +#if IPP_VERSION_X100 >= 900 +#define IPP_INITIALIZER(FEAT) \ +{ \ + if(FEAT) \ + ippSetCpuFeatures(FEAT); \ + else \ + ippInit(); \ +} +#elif IPP_VERSION_X100 >= 800 +#define IPP_INITIALIZER(FEAT) \ +{ \ + ippInit(); \ +} +#else +#define IPP_INITIALIZER(FEAT) \ +{ \ + ippStaticInit(); \ +} +#endif + +#ifdef CVAPI_EXPORTS +#define IPP_INITIALIZER_AUTO \ +struct __IppInitializer__ \ +{ \ + __IppInitializer__() \ + {IPP_INITIALIZER(cv::ipp::getIppFeatures())} \ +}; \ +static struct __IppInitializer__ __ipp_initializer__; +#else +#define IPP_INITIALIZER_AUTO +#endif +#else +#define IPP_INITIALIZER +#define IPP_INITIALIZER_AUTO +#endif #define CV_IPP_CHECK_COND (cv::ipp::useIPP()) #define CV_IPP_CHECK() if(CV_IPP_CHECK_COND) diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index dcb625b3d..4d7d7df66 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -520,6 +520,7 @@ protected: TLSDataContainer(); virtual ~TLSDataContainer(); + void gatherData(std::vector &data) const; #if OPENCV_ABI_COMPATIBILITY > 300 void* getData() const; void release(); @@ -546,9 +547,20 @@ public: inline ~TLSData() { release(); } // Release key and delete associated data inline T* get() const { return (T*)getData(); } // Get data assosiated with key + // Get data from all threads + inline void gather(std::vector &data) const + { + std::vector &dataVoid = reinterpret_cast&>(data); + gatherData(dataVoid); + } + private: virtual void* createDataInstance() const {return new T;} // Wrapper to allocate data by template virtual void deleteDataInstance(void* pData) const {delete (T*)pData;} // Wrapper to release data by template + + // Disable TLS copy operations + TLSData(TLSData &) {}; + TLSData& operator =(const TLSData &) {return *this;}; }; /** @brief Designed for command line parsing @@ -597,7 +609,7 @@ For example: const String keys = "{help h usage ? | | print this message }" "{@image1 | | image1 for compare }" - "{@image2 | | image2 for compare }" + "{@image2 || image2 for compare }" "{@repeat |1 | number }" "{path |. | path to file }" "{fps | -1.0 | fps for output video }" @@ -607,6 +619,13 @@ For example: } @endcode +Note that there are no default values for `help` and `timestamp` so we can check their presence using the `has()` method. +Arguments with default values are considered to be always present. Use the `get()` method in these cases to check their +actual value instead. + +String keys like `get("@image1")` return the empty string `""` by default - even with an empty default value. +Use the special `` default value to enforce that the returned string must not be empty. (like in `get("@image2")`) + ### Usage For the described keys: @@ -618,7 +637,7 @@ For the described keys: # Bad call $ ./app -fps=aaa ERRORS: - Exception: can not convert: [aaa] to [double] + Parameter 'fps': can not convert: [aaa] to [double] @endcode */ class CV_EXPORTS CommandLineParser diff --git a/modules/core/include/opencv2/core/vaapi.hpp b/modules/core/include/opencv2/core/va_intel.hpp similarity index 54% rename from modules/core/include/opencv2/core/vaapi.hpp rename to modules/core/include/opencv2/core/va_intel.hpp index 19f9fe6ac..f4bb8a650 100644 --- a/modules/core/include/opencv2/core/vaapi.hpp +++ b/modules/core/include/opencv2/core/va_intel.hpp @@ -5,36 +5,36 @@ // Copyright (C) 2015, Itseez, Inc., all rights reserved. // Third party copyrights are property of their respective owners. -#ifndef __OPENCV_CORE_VAAPI_HPP__ -#define __OPENCV_CORE_VAAPI_HPP__ +#ifndef __OPENCV_CORE_VA_INTEL_HPP__ +#define __OPENCV_CORE_VA_INTEL_HPP__ #ifndef __cplusplus -# error vaapi.hpp header must be compiled as C++ +# error va_intel.hpp header must be compiled as C++ #endif #include "opencv2/core.hpp" #include "ocl.hpp" -#if defined(HAVE_VAAPI) +#if defined(HAVE_VA) # include "va/va.h" -#else // HAVE_VAAPI +#else // HAVE_VA # if !defined(_VA_H_) typedef void* VADisplay; typedef unsigned int VASurfaceID; # endif // !_VA_H_ -#endif // HAVE_VAAPI +#endif // HAVE_VA -namespace cv { namespace vaapi { +namespace cv { namespace va_intel { -/** @addtogroup core_vaapi -This section describes CL-VA (VA-API) interoperability. +/** @addtogroup core_va_intel +This section describes Intel VA-API/OpenCL (CL-VA) interoperability. -To enable CL-VA interoperability support, configure OpenCV using CMake with WITH_VAAPI=ON . Currently VA-API is +To enable CL-VA interoperability support, configure OpenCV using CMake with WITH_VA_INTEL=ON . Currently VA-API is supported on Linux only. You should also install Intel Media Server Studio (MSS) to use this feature. You may -have to specify the path(s) to MSS components for cmake in environment variables: VAAPI_MSDK_ROOT for Media SDK -(default is "/opt/intel/mediasdk"), and VAAPI_IOCL_ROOT for Intel OpenCL (default is "/opt/intel/opencl"). +have to specify the path(s) to MSS components for cmake in environment variables: VA_INTEL_MSDK_ROOT for Media SDK +(default is "/opt/intel/mediasdk"), and VA_INTEL_IOCL_ROOT for Intel OpenCL (default is "/opt/intel/opencl"). -To use VA-API interoperability you should first create VADisplay (libva), and then call initializeContextFromVA() +To use CL-VA interoperability you should first create VADisplay (libva), and then call initializeContextFromVA() function to create OpenCL context and set up interoperability. */ //! @{ @@ -46,29 +46,32 @@ using namespace cv::ocl; // TODO static functions in the Context class /** @brief Creates OpenCL context from VA. -@param display - VADisplay for which CL interop should be established. +@param display - VADisplay for which CL interop should be established. +@param tryInterop - try to set up for interoperability, if true; set up for use slow copy if false. @return Returns reference to OpenCL Context */ -CV_EXPORTS Context& initializeContextFromVA(VADisplay display); +CV_EXPORTS Context& initializeContextFromVA(VADisplay display, bool tryInterop = true); -} // namespace cv::vaapi::ocl +} // namespace cv::va_intel::ocl /** @brief Converts InputArray to VASurfaceID object. +@param display - VADisplay object. @param src - source InputArray. @param surface - destination VASurfaceID object. @param size - size of image represented by VASurfaceID object. */ -CV_EXPORTS void convertToVASurface(InputArray src, VASurfaceID surface, Size size); +CV_EXPORTS void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface, Size size); /** @brief Converts VASurfaceID object to OutputArray. +@param display - VADisplay object. @param surface - source VASurfaceID object. @param size - size of image represented by VASurfaceID object. @param dst - destination OutputArray. */ -CV_EXPORTS void convertFromVASurface(VASurfaceID surface, Size size, OutputArray dst); +CV_EXPORTS void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, OutputArray dst); //! @} -}} // namespace cv::vaapi +}} // namespace cv::va_intel -#endif /* __OPENCV_CORE_VAAPI_HPP__ */ +#endif /* __OPENCV_CORE_VA_INTEL_HPP__ */ diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 1b8705983..6ad72461d 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -1504,7 +1504,7 @@ static bool ocl_binary_op(InputArray _src1, InputArray _src2, OutputArray _dst, k.args(src1arg, src2arg, maskarg, dstarg); } - size_t globalsize[] = { src1.cols * cn / kercn, (src1.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[] = { (size_t)src1.cols * cn / kercn, ((size_t)src1.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, 0, false); } @@ -1917,7 +1917,7 @@ static bool ocl_arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst, k.args(src1arg, src2arg, maskarg, dstarg); } - size_t globalsize[] = { src1.cols * cn / kercn, (src1.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[] = { (size_t)src1.cols * cn / kercn, ((size_t)src1.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -4692,7 +4692,7 @@ static void cmp16s(const short* src1, size_t step1, const short* src2, size_t st CV_IPP_CHECK() { IppCmpOp op = convert_cmp(*(int *)_cmpop); - if( op > 0 ) + if( op >= 0 ) { fixSteps(size, sizeof(dst[0]), step1, step2, step); if (0 <= ippiCompare_16s_C1R(src1, (int)step1, src2, (int)step2, dst, (int)step, ippiSize(size), op)) @@ -4974,7 +4974,7 @@ static bool ocl_compare(InputArray _src1, InputArray _src2, OutputArray _dst, in ocl::KernelArg::WriteOnly(dst, cn, kercn)); } - size_t globalsize[2] = { dst.cols * cn / kercn, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols * cn / kercn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -5668,7 +5668,7 @@ static bool ocl_inRange( InputArray _src, InputArray _lowerb, ker.args(srcarg, dstarg, ocl::KernelArg::ReadOnlyNoSize(lscalaru), ocl::KernelArg::ReadOnlyNoSize(uscalaru), rowsPerWI); - size_t globalsize[2] = { ssize.width / colsPerWI, (ssize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)ssize.width / colsPerWI, ((size_t)ssize.height + rowsPerWI - 1) / rowsPerWI }; return ker.run(2, globalsize, NULL, false); } diff --git a/modules/core/src/command_line_parser.cpp b/modules/core/src/command_line_parser.cpp index 2753ef30a..542b231ff 100644 --- a/modules/core/src/command_line_parser.cpp +++ b/modules/core/src/command_line_parser.cpp @@ -4,6 +4,20 @@ namespace cv { +namespace { +static const char* noneValue = ""; + +static String cat_string(const String& str) +{ + int left = 0, right = (int)str.length(); + while( left <= right && str[left] == ' ' ) + left++; + while( right > left && str[right-1] == ' ' ) + right--; + return left >= right ? String("") : str.substr(left, right-left); +} +} + struct CommandLineParserParams { public: @@ -27,7 +41,6 @@ struct CommandLineParser::Impl std::vector split_range_string(const String& str, char fs, char ss) const; std::vector split_string(const String& str, char symbol = ' ', bool create_empty_item = false) const; - String cat_string(const String& str) const; void apply_params(const String& key, const String& value); void apply_params(int i, String value); @@ -37,7 +50,7 @@ struct CommandLineParser::Impl }; -static String get_type_name(int type) +static const char* get_type_name(int type) { if( type == Param::INT ) return "int"; @@ -78,14 +91,11 @@ static void from_str(const String& str, int type, void* dst) else if( type == Param::STRING ) *(String*)dst = str; else - throw cv::Exception(CV_StsBadArg, "unknown/unsupported parameter type", "", __FILE__, __LINE__); + CV_Error(Error::StsBadArg, "unknown/unsupported parameter type"); if (ss.fail()) { - String err_msg = "can not convert: [" + str + - + "] to [" + get_type_name(type) + "]"; - - throw cv::Exception(CV_StsBadArg, err_msg, "", __FILE__, __LINE__); + CV_Error_(Error::StsBadArg, ("can not convert: [%s] to [%s]", str.c_str(), get_type_name(type))); } } @@ -97,24 +107,33 @@ void CommandLineParser::getByName(const String& name, bool space_delete, int typ { for (size_t j = 0; j < impl->data[i].keys.size(); j++) { - if (name.compare(impl->data[i].keys[j]) == 0) + if (name == impl->data[i].keys[j]) { String v = impl->data[i].def_value; if (space_delete) - v = impl->cat_string(v); + v = cat_string(v); + + // the key was neither specified nor has it a default value + if((v.empty() && type != Param::STRING) || v == noneValue) { + impl->error = true; + impl->error_message = impl->error_message + "Missing parameter: '" + name + "'\n"; + return; + } + from_str(v, type, dst); return; } } } - impl->error = true; - impl->error_message = impl->error_message + "Unknown parameter " + name + "\n"; } - catch (std::exception& e) + catch (Exception& e) { impl->error = true; - impl->error_message = impl->error_message + "Exception: " + String(e.what()) + "\n"; + impl->error_message = impl->error_message + "Parameter '"+ name + "': " + e.err + "\n"; + return; } + + CV_Error_(Error::StsBadArg, ("undeclared key '%s' requested", name.c_str())); } @@ -127,19 +146,27 @@ void CommandLineParser::getByIndex(int index, bool space_delete, int type, void* if (impl->data[i].number == index) { String v = impl->data[i].def_value; - if (space_delete == true) v = impl->cat_string(v); + if (space_delete == true) v = cat_string(v); + + // the key was neither specified nor has it a default value + if((v.empty() && type != Param::STRING) || v == noneValue) { + impl->error = true; + impl->error_message = impl->error_message + format("Missing parameter #%d\n", index); + return; + } from_str(v, type, dst); return; } } - impl->error = true; - impl->error_message = impl->error_message + "Unknown parameter #" + format("%d", index) + "\n"; } - catch(std::exception & e) + catch(Exception& e) { impl->error = true; - impl->error_message = impl->error_message + "Exception: " + String(e.what()) + "\n"; + impl->error_message = impl->error_message + format("Parameter #%d: ", index) + e.err + "\n"; + return; } + + CV_Error_(Error::StsBadArg, ("undeclared position %d requested", index)); } static bool cmp_params(const CommandLineParserParams & p1, const CommandLineParserParams & p2) @@ -184,7 +211,7 @@ CommandLineParser::CommandLineParser(int argc, const char* const argv[], const S CommandLineParserParams p; p.keys = impl->split_string(l[0]); p.def_value = l[1]; - p.help_message = impl->cat_string(l[2]); + p.help_message = cat_string(l[2]); p.number = -1; if (p.keys.size() <= 0) { @@ -207,25 +234,21 @@ CommandLineParser::CommandLineParser(int argc, const char* const argv[], const S jj = 0; for (int i = 1; i < argc; i++) { - String s = String(argv[i]); + String s(argv[i]); + bool hasSingleDash = s.length() > 1 && s[0] == '-'; - if (s.find('=') != String::npos && s.find('=') < s.length()) + if (hasSingleDash) { - std::vector k_v = impl->split_string(s, '=', true); - for (int h = 0; h < 2; h++) - { - if (k_v[0][0] == '-') - k_v[0] = k_v[0].substr(1, k_v[0].length() -1); + bool hasDoubleDash = s.length() > 2 && s[1] == '-'; + String key = s.substr(hasDoubleDash ? 2 : 1); + String value = "true"; + size_t equalsPos = key.find('='); + + if(equalsPos != String::npos) { + value = key.substr(equalsPos + 1); + key = key.substr(0, equalsPos); } - impl->apply_params(k_v[0], k_v[1]); - } - else if (s.length() > 2 && s[0] == '-' && s[1] == '-') - { - impl->apply_params(s.substr(2), "true"); - } - else if (s.length() > 1 && s[0] == '-') - { - impl->apply_params(s.substr(1), "true"); + impl->apply_params(key, value); } else { @@ -303,16 +326,6 @@ void CommandLineParser::Impl::sort_params() std::sort (data.begin(), data.end(), cmp_params); } -String CommandLineParser::Impl::cat_string(const String& str) const -{ - int left = 0, right = (int)str.length(); - while( left <= right && str[left] == ' ' ) - left++; - while( right > left && str[right-1] == ' ' ) - right--; - return left >= right ? String("") : str.substr(left, right-left); -} - String CommandLineParser::getPathToApplication() const { return impl->path_to_app; @@ -324,12 +337,15 @@ bool CommandLineParser::has(const String& name) const { for (size_t j = 0; j < impl->data[i].keys.size(); j++) { - if (name.compare(impl->data[i].keys[j]) == 0 && String("true").compare(impl->data[i].def_value) == 0) + if (name == impl->data[i].keys[j]) { - return true; + const String v = cat_string(impl->data[i].def_value); + return !v.empty() && v != noneValue; } } } + + CV_Error_(Error::StsBadArg, ("undeclared key '%s' requested", name.c_str())); return false; } @@ -388,7 +404,7 @@ void CommandLineParser::printMessage() const printf(", "); } } - String dv = impl->cat_string(impl->data[i].def_value); + String dv = cat_string(impl->data[i].def_value); if (dv.compare("") != 0) { printf(" (value:%s)", dv.c_str()); @@ -408,7 +424,7 @@ void CommandLineParser::printMessage() const printf("%s", k.c_str()); - String dv = impl->cat_string(impl->data[i].def_value); + String dv = cat_string(impl->data[i].def_value); if (dv.compare("") != 0) { printf(" (value:%s)", dv.c_str()); diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index fd07a7fc5..1e9d832f3 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -902,7 +902,7 @@ static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv ) argidx = k.set(argidx, ocl::KernelArg::WriteOnlyNoSize(dst[i])); k.set(argidx, rowsPerWI); - size_t globalsize[2] = { size.width, (size.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)size.width, ((size_t)size.height + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1069,7 +1069,7 @@ static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst ) argidx = k.set(argidx, ocl::KernelArg::WriteOnly(dst)); k.set(argidx, rowsPerWI); - size_t globalsize[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1338,7 +1338,7 @@ static bool ocl_mixChannels(InputArrayOfArrays _src, InputOutputArrayOfArrays _d argindex = k.set(argindex, size.width); k.set(argindex, rowsPerWI); - size_t globalsize[2] = { size.width, (size.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)size.width, ((size_t)size.height + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -5505,7 +5505,7 @@ static bool ocl_convertScaleAbs( InputArray _src, OutputArray _dst, double alpha else if (wdepth == CV_64F) k.args(srcarg, dstarg, alpha, beta); - size_t globalsize[2] = { src.cols * cn / kercn, (src.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -5673,7 +5673,7 @@ static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst) k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::ReadOnlyNoSize(lut), ocl::KernelArg::WriteOnly(dst, dcn, kercn)); - size_t globalSize[2] = { dst.cols * dcn / kercn, (dst.rows + 3) / 4 }; + size_t globalSize[2] = { (size_t)dst.cols * dcn / kercn, ((size_t)dst.rows + 3) / 4 }; return k.run(2, globalSize, NULL, false); } @@ -5682,7 +5682,7 @@ static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst) #if defined(HAVE_IPP) namespace ipp { -#if 0 // there are no performance benefits (PR #2653) +#if IPP_DISABLE_BLOCK // there are no performance benefits (PR #2653) class IppLUTParallelBody_LUTC1 : public ParallelLoopBody { public: @@ -5850,7 +5850,7 @@ static bool ipp_lut(Mat &src, Mat &lut, Mat &dst) Ptr body; size_t elemSize1 = CV_ELEM_SIZE1(dst.depth()); -#if 0 // there are no performance benefits (PR #2653) +#if IPP_DISABLE_BLOCK // there are no performance benefits (PR #2653) if (lutcn == 1) { ParallelLoopBody* p = new ipp::IppLUTParallelBody_LUTC1(src, lut, dst, &ok); @@ -6053,7 +6053,7 @@ static bool ocl_normalize( InputArray _src, InputOutputArray _dst, InputArray _m k.args(srcarg, maskarg, dstarg); } - size_t globalsize[2] = { src.cols, (src.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)src.cols, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } else diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 22b18710d..b2ef33cad 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -377,7 +377,7 @@ Mat& Mat::operator = (const Scalar& s) if( is[0] == 0 && is[1] == 0 && is[2] == 0 && is[3] == 0 ) { -#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && 0 +#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if (dims <= 2 || isContinuous()) @@ -692,7 +692,7 @@ static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode ) size_t maxWorkGroupSize = dev.maxWorkGroupSize(); CV_Assert(maxWorkGroupSize % 4 == 0); - size_t globalsize[2] = { cols, (rows + pxPerWIy - 1) / pxPerWIy }, + size_t globalsize[2] = { (size_t)cols, ((size_t)rows + pxPerWIy - 1) / pxPerWIy }, localsize[2] = { maxWorkGroupSize / 4, 4 }; return k.run(2, globalsize, (flipType == FLIP_COLS) && !dev.isIntel() ? localsize : NULL, false); } @@ -833,7 +833,7 @@ static bool ocl_repeat(InputArray _src, int ny, int nx, OutputArray _dst) UMat src = _src.getUMat(), dst = _dst.getUMat(); k.args(ocl::KernelArg::ReadOnly(src, cn, kercn), ocl::KernelArg::WriteOnlyNoSize(dst)); - size_t globalsize[] = { src.cols * cn / kercn, (src.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1110,7 +1110,7 @@ static bool ocl_copyMakeBorder( InputArray _src, OutputArray _dst, int top, int k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst), top, left, ocl::KernelArg::Constant(Mat(1, 1, sctype, value))); - size_t globalsize[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1157,7 +1157,7 @@ void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom, borderType &= ~BORDER_ISOLATED; -#if defined HAVE_IPP && 0 +#if defined HAVE_IPP && IPP_DISABLE_BLOCK CV_IPP_CHECK() { typedef IppStatus (CV_STDCALL * ippiCopyMakeBorder)(const void * pSrc, int srcStep, IppiSize srcRoiSize, void * pDst, diff --git a/modules/core/src/datastructs.cpp b/modules/core/src/datastructs.cpp index 519d00ee5..2612de6c5 100644 --- a/modules/core/src/datastructs.cpp +++ b/modules/core/src/datastructs.cpp @@ -352,6 +352,7 @@ CV_IMPL CvString cvMemStorageAllocString( CvMemStorage* storage, const char* ptr, int len ) { CvString str; + memset(&str, 0, sizeof(CvString)); str.len = len >= 0 ? len : (int)strlen(ptr); str.ptr = (char*)cvMemStorageAlloc( storage, str.len + 1 ); @@ -1694,6 +1695,9 @@ cvSeqRemoveSlice( CvSeq* seq, CvSlice slice ) slice.end_index = slice.start_index + length; + if ( slice.start_index == slice.end_index ) + return; + if( slice.end_index < total ) { CvSeqReader reader_to, reader_from; diff --git a/modules/core/src/directx.cpp b/modules/core/src/directx.cpp index 46f353240..23a7b94c6 100644 --- a/modules/core/src/directx.cpp +++ b/modules/core/src/directx.cpp @@ -729,7 +729,7 @@ bool ocl_convert_nv12_to_bgr( k.args(clImageY, clImageUV, clBuffer, step, cols, rows); - size_t globalsize[] = { cols, rows }; + size_t globalsize[] = { (size_t)cols, (size_t)rows }; return k.run(2, globalsize, 0, false); } @@ -750,7 +750,7 @@ bool ocl_convert_bgr_to_nv12( k.args(clBuffer, step, cols, rows, clImageY, clImageUV); - size_t globalsize[] = { cols, rows }; + size_t globalsize[] = { (size_t)cols, (size_t)rows }; return k.run(2, globalsize, 0, false); } @@ -834,7 +834,7 @@ void convertToD3D11Texture2D(InputArray src, ID3D11Texture2D* pD3D11Texture2D) { size_t offset = 0; // TODO size_t origin[3] = { 0, 0, 0 }; - size_t region[3] = { u.cols, u.rows, 1 }; + size_t region[3] = { (size_t)u.cols, (size_t)u.rows, 1 }; status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, origin, region, 0, NULL, NULL); if (status != CL_SUCCESS) @@ -939,7 +939,7 @@ void convertFromD3D11Texture2D(ID3D11Texture2D* pD3D11Texture2D, OutputArray dst { size_t offset = 0; // TODO size_t origin[3] = { 0, 0, 0 }; - size_t region[3] = { u.cols, u.rows, 1 }; + size_t region[3] = { (size_t)u.cols, (size_t)u.rows, 1 }; status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, origin, region, offset, 0, NULL, NULL); if (status != CL_SUCCESS) @@ -1041,7 +1041,7 @@ void convertToD3D10Texture2D(InputArray src, ID3D10Texture2D* pD3D10Texture2D) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D10ObjectsKHR failed"); size_t offset = 0; // TODO size_t dst_origin[3] = {0, 0, 0}; - size_t region[3] = {u.cols, u.rows, 1}; + size_t region[3] = {(size_t)u.cols, (size_t)u.rows, 1}; status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed"); @@ -1100,7 +1100,7 @@ void convertFromD3D10Texture2D(ID3D10Texture2D* pD3D10Texture2D, OutputArray dst CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireD3D10ObjectsKHR failed"); size_t offset = 0; // TODO size_t src_origin[3] = {0, 0, 0}; - size_t region[3] = {u.cols, u.rows, 1}; + size_t region[3] = {(size_t)u.cols, (size_t)u.rows, 1}; status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed"); @@ -1195,7 +1195,7 @@ void convertToDirect3DSurface9(InputArray src, IDirect3DSurface9* pDirect3DSurfa CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireDX9MediaSurfacesKHR failed"); size_t offset = 0; // TODO size_t dst_origin[3] = {0, 0, 0}; - size_t region[3] = {u.cols, u.rows, 1}; + size_t region[3] = {(size_t)u.cols, (size_t)u.rows, 1}; status = clEnqueueCopyBufferToImage(q, clBuffer, clImage, offset, dst_origin, region, 0, NULL, NULL); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyBufferToImage failed"); @@ -1261,7 +1261,7 @@ void convertFromDirect3DSurface9(IDirect3DSurface9* pDirect3DSurface9, OutputArr CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireDX9MediaSurfacesKHR failed"); size_t offset = 0; // TODO size_t src_origin[3] = {0, 0, 0}; - size_t region[3] = {u.cols, u.rows, 1}; + size_t region[3] = {(size_t)u.cols, (size_t)u.rows, 1}; status = clEnqueueCopyImageToBuffer(q, clImage, clBuffer, src_origin, region, offset, 0, NULL, NULL); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueCopyImageToBuffer failed"); diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index ef01c2139..5576a347a 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -54,7 +54,7 @@ namespace cv # pragma warning(disable: 4748) #endif -#if IPP_VERSION_X100 >= 701 +#if IPP_VERSION_X100 >= 710 #define USE_IPP_DFT 1 #else #undef USE_IPP_DFT @@ -2934,7 +2934,7 @@ static bool ocl_mulSpectrums( InputArray _srcA, InputArray _srcB, k.args(ocl::KernelArg::ReadOnlyNoSize(A), ocl::KernelArg::ReadOnlyNoSize(B), ocl::KernelArg::WriteOnly(dst), rowsPerWI); - size_t globalsize[2] = { asize.width, (asize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)asize.width, ((size_t)asize.height + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -3318,28 +3318,102 @@ static void IDCT_64f(const double* src, int src_step, double* dft_src, double* d } +#ifdef HAVE_IPP namespace cv { -#if defined HAVE_IPP && IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 900 +typedef IppStatus (CV_STDCALL * ippiDCTFunc)(const Ipp32f* pSrc, int srcStep, Ipp32f* pDst, int dstStep, const void* pDCTSpec, Ipp8u* pBuffer); +typedef IppStatus (CV_STDCALL * ippiDCTInit)(void* pDCTSpec, IppiSize roiSize, Ipp8u* pMemInit ); +typedef IppStatus (CV_STDCALL * ippiDCTGetSize)(IppiSize roiSize, int* pSizeSpec, int* pSizeInit, int* pSizeBuf); +#elif IPP_VERSION_X100 >= 700 typedef IppStatus (CV_STDCALL * ippiDCTFunc)(const Ipp32f*, int, Ipp32f*, int, const void*, Ipp8u*); typedef IppStatus (CV_STDCALL * ippiDCTInitAlloc)(void**, IppiSize, IppHintAlgorithm); typedef IppStatus (CV_STDCALL * ippiDCTFree)(void* pDCTSpec); typedef IppStatus (CV_STDCALL * ippiDCTGetBufSize)(const void*, int*); +#endif -template class DctIPPLoop_Invoker : public ParallelLoopBody { public: - - DctIPPLoop_Invoker(const Mat& _src, Mat& _dst, const Dct* _ippidct, bool _inv, bool *_ok) : - ParallelLoopBody(), src(&_src), dst(&_dst), ippidct(_ippidct), inv(_inv), ok(_ok) + DctIPPLoop_Invoker(const Mat& _src, Mat& _dst, bool _inv, bool *_ok) : + ParallelLoopBody(), src(&_src), dst(&_dst), inv(_inv), ok(_ok) { *ok = true; } virtual void operator()(const Range& range) const { + if(*ok == false) + return; + +#if IPP_VERSION_X100 >= 900 + IppiSize srcRoiSize = {src->cols, 1}; + + int specSize = 0; + int initSize = 0; + int bufferSize = 0; + + Ipp8u* pDCTSpec = NULL; + Ipp8u* pBuffer = NULL; + Ipp8u* pInitBuf = NULL; + + #define IPP_RETURN \ + if(pDCTSpec) \ + ippFree(pDCTSpec); \ + if(pBuffer) \ + ippFree(pBuffer); \ + if(pInitBuf) \ + ippFree(pInitBuf); \ + return; + + ippiDCTFunc ippDctFun = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; + ippiDCTInit ippDctInit = inv ? (ippiDCTInit)ippiDCTInvInit_32f : (ippiDCTInit)ippiDCTFwdInit_32f; + ippiDCTGetSize ippDctGetSize = inv ? (ippiDCTGetSize)ippiDCTInvGetSize_32f : (ippiDCTGetSize)ippiDCTFwdGetSize_32f; + + if(ippDctGetSize(srcRoiSize, &specSize, &initSize, &bufferSize) < 0) + { + *ok = false; + return; + } + + pDCTSpec = (Ipp8u*)ippMalloc(specSize); + if(!pDCTSpec && specSize) + { + *ok = false; + return; + } + + pBuffer = (Ipp8u*)ippMalloc(bufferSize); + if(!pBuffer && bufferSize) + { + *ok = false; + IPP_RETURN + } + pInitBuf = (Ipp8u*)ippMalloc(initSize); + if(!pInitBuf && initSize) + { + *ok = false; + IPP_RETURN + } + + if(ippDctInit(pDCTSpec, srcRoiSize, pInitBuf) < 0) + { + *ok = false; + IPP_RETURN + } + + for(int i = range.start; i < range.end; ++i) + { + if(ippDctFun(src->ptr(i), (int)src->step,dst->ptr(i), (int)dst->step, pDCTSpec, pBuffer) < 0) + { + *ok = false; + IPP_RETURN + } + } + IPP_RETURN +#undef IPP_RETURN +#elif IPP_VERSION_X100 >= 700 void* pDCTSpec; AutoBuffer buf; uchar* pBuffer = 0; @@ -3349,6 +3423,7 @@ public: CV_SUPPRESS_DEPRECATED_START + ippiDCTFunc ippDctFun = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; ippiDCTInitAlloc ippInitAlloc = inv ? (ippiDCTInitAlloc)ippiDCTInvInitAlloc_32f : (ippiDCTInitAlloc)ippiDCTFwdInitAlloc_32f; ippiDCTFree ippFree = inv ? (ippiDCTFree)ippiDCTInvFree_32f : (ippiDCTFree)ippiDCTFwdFree_32f; ippiDCTGetBufSize ippGetBufSize = inv ? (ippiDCTGetBufSize)ippiDCTInvGetBufSize_32f : (ippiDCTGetBufSize)ippiDCTFwdGetBufSize_32f; @@ -3359,8 +3434,13 @@ public: pBuffer = (uchar*)buf; for( int i = range.start; i < range.end; ++i) - if(!(*ippidct)(src->ptr(i), (int)src->step,dst->ptr(i), (int)dst->step, pDCTSpec, (Ipp8u*)pBuffer)) + { + if(ippDctFun(src->ptr(i), (int)src->step,dst->ptr(i), (int)dst->step, pDCTSpec, (Ipp8u*)pBuffer) < 0) + { *ok = false; + break; + } + } } else *ok = false; @@ -3369,44 +3449,91 @@ public: ippFree(pDCTSpec); CV_SUPPRESS_DEPRECATED_END +#else + CV_UNUSED(range); + *ok = false; +#endif } private: const Mat* src; Mat* dst; - const Dct* ippidct; bool inv; bool *ok; }; -template -bool DctIPPLoop(const Mat& src, Mat& dst, const Dct& ippidct, bool inv) +static bool DctIPPLoop(const Mat& src, Mat& dst, bool inv) { bool ok; - parallel_for_(Range(0, src.rows), DctIPPLoop_Invoker(src, dst, &ippidct, inv, &ok), src.rows/(double)(1<<4) ); + parallel_for_(Range(0, src.rows), DctIPPLoop_Invoker(src, dst, inv, &ok), src.rows/(double)(1<<4) ); return ok; } -struct IPPDCTFunctor -{ - IPPDCTFunctor(ippiDCTFunc _func) : func(_func){} - - bool operator()(const Ipp32f* src, int srcStep, Ipp32f* dst, int dstStep, const void* pDCTSpec, Ipp8u* pBuffer) const - { - return func ? func(src, srcStep, dst, dstStep, pDCTSpec, pBuffer) >= 0 : false; - } -private: - ippiDCTFunc func; -}; - static bool ippi_DCT_32f(const Mat& src, Mat& dst, bool inv, bool row) { - ippiDCTFunc ippFunc = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R ; - - if (row) - return(DctIPPLoop(src,dst,IPPDCTFunctor(ippFunc),inv)); + if(row) + return DctIPPLoop(src, dst, inv); else { +#if IPP_VERSION_X100 >= 900 + IppiSize srcRoiSize = {src.cols, src.rows}; + + int specSize = 0; + int initSize = 0; + int bufferSize = 0; + + Ipp8u* pDCTSpec = NULL; + Ipp8u* pBuffer = NULL; + Ipp8u* pInitBuf = NULL; + + #define IPP_RELEASE \ + if(pDCTSpec) \ + ippFree(pDCTSpec); \ + if(pBuffer) \ + ippFree(pBuffer); \ + if(pInitBuf) \ + ippFree(pInitBuf); \ + + ippiDCTFunc ippDctFun = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; + ippiDCTInit ippDctInit = inv ? (ippiDCTInit)ippiDCTInvInit_32f : (ippiDCTInit)ippiDCTFwdInit_32f; + ippiDCTGetSize ippDctGetSize = inv ? (ippiDCTGetSize)ippiDCTInvGetSize_32f : (ippiDCTGetSize)ippiDCTFwdGetSize_32f; + + if(ippDctGetSize(srcRoiSize, &specSize, &initSize, &bufferSize) < 0) + return false; + + pDCTSpec = (Ipp8u*)ippMalloc(specSize); + if(!pDCTSpec && specSize) + return false; + + pBuffer = (Ipp8u*)ippMalloc(bufferSize); + if(!pBuffer && bufferSize) + { + IPP_RELEASE + return false; + } + pInitBuf = (Ipp8u*)ippMalloc(initSize); + if(!pInitBuf && initSize) + { + IPP_RELEASE + return false; + } + + if(ippDctInit(pDCTSpec, srcRoiSize, pInitBuf) < 0) + { + IPP_RELEASE + return false; + } + + if(ippDctFun(src.ptr(), (int)src.step,dst.ptr(), (int)dst.step, pDCTSpec, pBuffer) < 0) + { + IPP_RELEASE + return false; + } + + IPP_RELEASE + return true; +#undef IPP_RELEASE +#elif IPP_VERSION_X100 >= 700 IppStatus status; void* pDCTSpec; AutoBuffer buf; @@ -3417,6 +3544,7 @@ static bool ippi_DCT_32f(const Mat& src, Mat& dst, bool inv, bool row) CV_SUPPRESS_DEPRECATED_START + ippiDCTFunc ippDctFun = inv ? (ippiDCTFunc)ippiDCTInv_32f_C1R : (ippiDCTFunc)ippiDCTFwd_32f_C1R; ippiDCTInitAlloc ippInitAlloc = inv ? (ippiDCTInitAlloc)ippiDCTInvInitAlloc_32f : (ippiDCTInitAlloc)ippiDCTFwdInitAlloc_32f; ippiDCTFree ippFree = inv ? (ippiDCTFree)ippiDCTInvFree_32f : (ippiDCTFree)ippiDCTFwdFree_32f; ippiDCTGetBufSize ippGetBufSize = inv ? (ippiDCTGetBufSize)ippiDCTInvGetBufSize_32f : (ippiDCTGetBufSize)ippiDCTFwdGetBufSize_32f; @@ -3428,7 +3556,7 @@ static bool ippi_DCT_32f(const Mat& src, Mat& dst, bool inv, bool row) buf.allocate( bufSize ); pBuffer = (uchar*)buf; - status = ippFunc(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, pDCTSpec, (Ipp8u*)pBuffer); + status = ippDctFun(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, pDCTSpec, (Ipp8u*)pBuffer); } if (pDCTSpec) @@ -3437,11 +3565,14 @@ static bool ippi_DCT_32f(const Mat& src, Mat& dst, bool inv, bool row) CV_SUPPRESS_DEPRECATED_END return status >= 0; +#else + CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(inv); CV_UNUSED(row); + return false; +#endif } } - -#endif } +#endif void cv::dct( InputArray _src0, OutputArray _dst, int flags ) { @@ -3473,21 +3604,7 @@ void cv::dct( InputArray _src0, OutputArray _dst, int flags ) _dst.create( src.rows, src.cols, type ); Mat dst = _dst.getMat(); -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - CV_IPP_CHECK() - { - bool row = (flags & DCT_ROWS) != 0; - if (src.type() == CV_32F) - { - if(ippi_DCT_32f(src,dst,inv, row)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } - } -#endif + CV_IPP_RUN(IPP_VERSION_X100 >= 700 && src.type() == CV_32F, ippi_DCT_32f(src, dst, inv, ((flags & DCT_ROWS) != 0))) DCTFunc dct_func = dct_tbl[(int)inv + (depth == CV_64F)*2]; diff --git a/modules/core/src/lda.cpp b/modules/core/src/lda.cpp index 5e20b5e6a..76e8db29a 100644 --- a/modules/core/src/lda.cpp +++ b/modules/core/src/lda.cpp @@ -937,9 +937,9 @@ public: // Linear Discriminant Analysis implementation //------------------------------------------------------------------------------ -LDA::LDA(int num_components) : _num_components(num_components) { } +LDA::LDA(int num_components) : _dataAsRow(true), _num_components(num_components) { } -LDA::LDA(InputArrayOfArrays src, InputArray labels, int num_components) : _num_components(num_components) +LDA::LDA(InputArrayOfArrays src, InputArray labels, int num_components) : _dataAsRow(true), _num_components(num_components) { this->compute(src, labels); //! compute eigenvectors and eigenvalues } @@ -1106,14 +1106,14 @@ void LDA::compute(InputArrayOfArrays _src, InputArray _lbls) { } } -// Projects samples into the LDA subspace. +// Projects one or more row aligned samples into the LDA subspace. Mat LDA::project(InputArray src) { - return subspaceProject(_eigenvectors, Mat(), _dataAsRow ? src : src.getMat().t()); + return subspaceProject(_eigenvectors, Mat(), src); } -// Reconstructs projections from the LDA subspace. +// Reconstructs projections from the LDA subspace from one or more row aligned samples. Mat LDA::reconstruct(InputArray src) { - return subspaceReconstruct(_eigenvectors, Mat(), _dataAsRow ? src : src.getMat().t()); + return subspaceReconstruct(_eigenvectors, Mat(), src); } } diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 97f36299d..2859b2d5d 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -93,7 +93,7 @@ static bool ocl_math_op(InputArray _src1, InputArray _src2, OutputArray _dst, in else k.args(src1arg, src2arg, dstarg); - size_t globalsize[] = { src1.cols * cn / kercn, (src1.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[] = { (size_t)src1.cols * cn / kercn, ((size_t)src1.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, 0, false); } @@ -330,7 +330,7 @@ static bool ocl_cartToPolar( InputArray _src1, InputArray _src2, ocl::KernelArg::WriteOnly(dst1, cn), ocl::KernelArg::WriteOnlyNoSize(dst2)); - size_t globalsize[2] = { dst1.cols * cn, (dst1.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst1.cols * cn, ((size_t)dst1.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -612,7 +612,7 @@ static bool ocl_polarToCart( InputArray _mag, InputArray _angle, k.args(ocl::KernelArg::ReadOnlyNoSize(mag), ocl::KernelArg::ReadOnlyNoSize(angle), ocl::KernelArg::WriteOnly(dst1, cn), ocl::KernelArg::WriteOnlyNoSize(dst2)); - size_t globalsize[2] = { dst1.cols * cn, (dst1.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst1.cols * cn, ((size_t)dst1.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1181,8 +1181,8 @@ iPow_i( const T* src, T* dst, int len, int power ) { T tab[5] = { - power == -1 ? saturate_cast(-1) : 0, (power & 1) ? -1 : 1, - std::numeric_limits::max(), 1, power == -1 ? 1 : 0 + saturate_cast(power == -1 ? -1 : 0), saturate_cast((power & 1) ? -1 : 1), + std::numeric_limits::max(), 1, saturate_cast(power == -1 ? 1 : 0) }; for( int i = 0; i < len; i++ ) { @@ -1349,7 +1349,7 @@ static bool ocl_pow(InputArray _src, double power, OutputArray _dst, k.args(srcarg, dstarg, power); } - size_t globalsize[2] = { dst.cols * cn, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols * cn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -1734,7 +1734,7 @@ static bool ocl_patchNaNs( InputOutputArray _a, float value ) k.args(ocl::KernelArg::ReadOnlyNoSize(a), ocl::KernelArg::WriteOnly(a, cn), (float)value); - size_t globalsize[2] = { a.cols * cn, (a.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)a.cols * cn, ((size_t)a.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index c1eacfd21..bf58dd0f3 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -859,8 +859,8 @@ static bool ocl_gemm( InputArray matA, InputArray matB, double alpha, ocl::KernelArg::ReadWrite(D, cn, kercn), sizeA.width, (float)alpha, (float)beta); - size_t globalsize[2] = { sizeD.width * cn / kercn, sizeD.height}; - size_t localsize[2] = { block_size, block_size}; + size_t globalsize[2] = { (size_t)sizeD.width * cn / kercn, (size_t)sizeD.height}; + size_t localsize[2] = { (size_t)block_size, (size_t)block_size}; return k.run(2, globalsize, block_size!=1 ? localsize : NULL, false); } #endif @@ -2304,7 +2304,7 @@ static bool ocl_scaleAdd( InputArray _src1, double alpha, InputArray _src2, Outp else k.args(src1arg, src2arg, dstarg, alpha); - size_t globalsize[2] = { dst.cols * cn / kercn, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols * cn / kercn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -2916,7 +2916,7 @@ dotProd_(const T* src1, const T* src2, int len) static double dotProd_8u(const uchar* src1, const uchar* src2, int len) { double r = 0; -#if ARITHM_USE_IPP && 0 +#if ARITHM_USE_IPP && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if (0 <= ippiDotProd_8u64f_C1R(src1, (int)(len*sizeof(src1[0])), @@ -3131,7 +3131,7 @@ static double dotProd_16u(const ushort* src1, const ushort* src2, int len) static double dotProd_16s(const short* src1, const short* src2, int len) { -#if (ARITHM_USE_IPP == 1) +#if (ARITHM_USE_IPP == 1) && (IPP_VERSION_X100 != 900) // bug in IPP 9.0.0 CV_IPP_CHECK() { double r = 0; diff --git a/modules/core/src/matop.cpp b/modules/core/src/matop.cpp index 30933e08a..2a6ec2635 100644 --- a/modules/core/src/matop.cpp +++ b/modules/core/src/matop.cpp @@ -1583,12 +1583,12 @@ void MatOp_Initializer::multiply(const MatExpr& e, double s, MatExpr& res) const inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, Size sz, int type, double alpha) { - res = MatExpr(getGlobalMatOpInitializer(), method, Mat(sz, type, (void*)0xEEEEEEEE), Mat(), Mat(), alpha, 0); + res = MatExpr(getGlobalMatOpInitializer(), method, Mat(sz, type, (void*)(size_t)0xEEEEEEEE), Mat(), Mat(), alpha, 0); } inline void MatOp_Initializer::makeExpr(MatExpr& res, int method, int ndims, const int* sizes, int type, double alpha) { - res = MatExpr(getGlobalMatOpInitializer(), method, Mat(ndims, sizes, type, (void*)0xEEEEEEEE), Mat(), Mat(), alpha, 0); + res = MatExpr(getGlobalMatOpInitializer(), method, Mat(ndims, sizes, type, (void*)(size_t)0xEEEEEEEE), Mat(), Mat(), alpha, 0); } /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index c0ad8c4ec..8c391aa0d 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -208,17 +208,14 @@ public: if(!u) return; - CV_Assert(u->urefcount >= 0); - CV_Assert(u->refcount >= 0); - if(u->refcount == 0) + CV_Assert(u->urefcount == 0); + CV_Assert(u->refcount == 0); + if( !(u->flags & UMatData::USER_ALLOCATED) ) { - if( !(u->flags & UMatData::USER_ALLOCATED) ) - { - fastFree(u->origdata); - u->origdata = 0; - } - delete u; + fastFree(u->origdata); + u->origdata = 0; } + delete u; } }; @@ -2834,7 +2831,7 @@ static bool ocl_setIdentity( InputOutputArray _m, const Scalar& s ) k.args(ocl::KernelArg::WriteOnly(m, cn, kercn), ocl::KernelArg::Constant(Mat(1, 1, sctype, s))); - size_t globalsize[2] = { m.cols * cn / kercn, (m.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)m.cols * cn / kercn, ((size_t)m.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } @@ -3074,7 +3071,7 @@ static bool ocl_transpose( InputArray _src, OutputArray _dst ) ocl::KernelArg::WriteOnlyNoSize(dst)); size_t localsize[2] = { TILE_DIM, BLOCK_ROWS }; - size_t globalsize[2] = { src.cols, inplace ? (src.rows + rowsPerWI - 1) / rowsPerWI : (divUp(src.rows, TILE_DIM) * BLOCK_ROWS) }; + size_t globalsize[2] = { (size_t)src.cols, inplace ? ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI : (divUp((size_t)src.rows, TILE_DIM) * BLOCK_ROWS) }; if (inplace && dev.isIntel()) { @@ -3370,22 +3367,20 @@ typedef void (*ReduceFunc)( const Mat& src, Mat& dst ); #define reduceMinR32f reduceR_ > #define reduceMinR64f reduceR_ > -#if IPP_VERSION_X100 > 0 - -static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat) +#ifdef HAVE_IPP +static inline bool ipp_reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat) { - cv::Size size = srcmat.size(); - IppiSize roisize = { size.width, 1 }; int sstep = (int)srcmat.step, stype = srcmat.type(), - sdepth = CV_MAT_DEPTH(stype), ddepth = dstmat.depth(); + ddepth = dstmat.depth(); + + IppiSize roisize = { srcmat.size().width, 1 }; typedef IppStatus (CV_STDCALL * ippiSum)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum); typedef IppStatus (CV_STDCALL * ippiSumHint)(const void * pSrc, int srcStep, IppiSize roiSize, Ipp64f* pSum, IppHintAlgorithm hint); ippiSum ippFunc = 0; ippiSumHint ippFuncHint = 0; - cv::ReduceFunc func = 0; - if (ddepth == CV_64F) + if(ddepth == CV_64F) { ippFunc = stype == CV_8UC1 ? (ippiSum)ippiSum_8u_C1R : @@ -3401,41 +3396,46 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds stype == CV_32FC1 ? (ippiSumHint)ippiSum_32f_C1R : stype == CV_32FC3 ? (ippiSumHint)ippiSum_32f_C3R : stype == CV_32FC4 ? (ippiSumHint)ippiSum_32f_C4R : 0; + } + + if(ippFunc) + { + for(int y = 0; y < srcmat.size().height; y++) + { + if(ippFunc(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0) + return false; + } + return true; + } + else if(ippFuncHint) + { + for(int y = 0; y < srcmat.size().height; y++) + { + if(ippFuncHint(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y), ippAlgHintAccurate) < 0) + return false; + } + return true; + } + + return false; +} + +static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat) +{ + CV_IPP_RUN(true, ipp_reduceSumC_8u16u16s32f_64f(srcmat, dstmat)); + + cv::ReduceFunc func = 0; + + if(dstmat.depth() == CV_64F) + { + int sdepth = CV_MAT_DEPTH(srcmat.type()); func = sdepth == CV_8U ? (cv::ReduceFunc)cv::reduceC_ > : sdepth == CV_16U ? (cv::ReduceFunc)cv::reduceC_ > : sdepth == CV_16S ? (cv::ReduceFunc)cv::reduceC_ > : sdepth == CV_32F ? (cv::ReduceFunc)cv::reduceC_ > : 0; } - CV_Assert(!(ippFunc && ippFuncHint) && func); - - CV_IPP_CHECK() - { - if (ippFunc) - { - for (int y = 0; y < size.height; ++y) - if (ippFunc(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0) - { - setIppErrorStatus(); - cv::Mat dstroi = dstmat.rowRange(y, y + 1); - func(srcmat.rowRange(y, y + 1), dstroi); - } - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - else if (ippFuncHint) - { - for (int y = 0; y < size.height; ++y) - if (ippFuncHint(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y), ippAlgHintAccurate) < 0) - { - setIppErrorStatus(); - cv::Mat dstroi = dstmat.rowRange(y, y + 1); - func(srcmat.rowRange(y, y + 1), dstroi); - } - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - } + CV_Assert(func); func(srcmat, dstmat); } @@ -3449,7 +3449,7 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds #define reduceSumC32f32f reduceC_ > #define reduceSumC64f64f reduceC_ > -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define reduceSumC8u64f reduceSumC_8u16u16s32f_64f #define reduceSumC16u64f reduceSumC_8u16u16s32f_64f #define reduceSumC16s64f reduceSumC_8u16u16s32f_64f @@ -3461,35 +3461,32 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds #define reduceSumC32f64f reduceC_ > #endif -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define REDUCE_OP(favor, optype, type1, type2) \ +static inline bool ipp_reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \ +{ \ + if((srcmat.channels() == 1)) \ + { \ + int sstep = (int)srcmat.step; \ + typedef Ipp##favor IppType; \ + IppiSize roisize = ippiSize(srcmat.size().width, 1);\ + for(int y = 0; y < srcmat.size().height; y++)\ + {\ + if(ippi##optype##_##favor##_C1R(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0)\ + return false;\ + }\ + return true;\ + }\ + return false; \ +} \ static inline void reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \ { \ - typedef Ipp##favor IppType; \ - cv::Size size = srcmat.size(); \ - IppiSize roisize = ippiSize(size.width, 1);\ - int sstep = (int)srcmat.step; \ - \ - if (CV_IPP_CHECK_COND && (srcmat.channels() == 1)) \ - { \ - for (int y = 0; y < size.height; ++y) \ - if (ippi##optype##_##favor##_C1R(srcmat.ptr(y), sstep, roisize, dstmat.ptr(y)) < 0) \ - { \ - setIppErrorStatus(); \ - cv::Mat dstroi = dstmat.rowRange(y, y + 1); \ - cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat.rowRange(y, y + 1), dstroi); \ - } \ - else \ - { \ - CV_IMPL_ADD(CV_IMPL_IPP);\ - } \ - return; \ - } \ + CV_IPP_RUN(true, ipp_reduce##optype##C##favor(srcmat, dstmat)); \ cv::reduceC_ < type1, type2, cv::Op##optype < type2 > >(srcmat, dstmat); \ } #endif -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP REDUCE_OP(8u, Max, uchar, uchar) REDUCE_OP(16u, Max, ushort, ushort) REDUCE_OP(16s, Max, short, short) @@ -3502,7 +3499,7 @@ REDUCE_OP(32f, Max, float, float) #endif #define reduceMaxC64f reduceC_ > -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP REDUCE_OP(8u, Min, uchar, uchar) REDUCE_OP(16u, Min, ushort, ushort) REDUCE_OP(16s, Min, short, short) @@ -3579,8 +3576,8 @@ static bool ocl_reduce(InputArray _src, OutputArray _dst, k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnlyNoSize(dst)); - size_t localSize[2] = { buf_cols, tileHeight}; - size_t globalSize[2] = { buf_cols, src.rows }; + size_t localSize[2] = { (size_t)buf_cols, (size_t)tileHeight}; + size_t globalSize[2] = { (size_t)buf_cols, (size_t)src.rows }; return k.run(2, globalSize, localSize, false); } else @@ -3775,7 +3772,7 @@ void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype) namespace cv { -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define USE_IPP_SORT typedef IppStatus (CV_STDCALL * IppSortFunc)(void *, int); @@ -3785,18 +3782,24 @@ static IppSortFunc getSortFunc(int depth, bool sortDescending) { if (!sortDescending) return depth == CV_8U ? (IppSortFunc)ippsSortAscend_8u_I : - /*depth == CV_16U ? (IppSortFunc)ippsSortAscend_16u_I : +#if IPP_DISABLE_BLOCK + depth == CV_16U ? (IppSortFunc)ippsSortAscend_16u_I : depth == CV_16S ? (IppSortFunc)ippsSortAscend_16s_I : depth == CV_32S ? (IppSortFunc)ippsSortAscend_32s_I : depth == CV_32F ? (IppSortFunc)ippsSortAscend_32f_I : - depth == CV_64F ? (IppSortFunc)ippsSortAscend_64f_I :*/ 0; + depth == CV_64F ? (IppSortFunc)ippsSortAscend_64f_I : +#endif + 0; else return depth == CV_8U ? (IppSortFunc)ippsSortDescend_8u_I : - /*depth == CV_16U ? (IppSortFunc)ippsSortDescend_16u_I : +#if IPP_DISABLE_BLOCK + depth == CV_16U ? (IppSortFunc)ippsSortDescend_16u_I : depth == CV_16S ? (IppSortFunc)ippsSortDescend_16s_I : depth == CV_32S ? (IppSortFunc)ippsSortDescend_32s_I : depth == CV_32F ? (IppSortFunc)ippsSortDescend_32f_I : - depth == CV_64F ? (IppSortFunc)ippsSortDescend_64f_I :*/ 0; + depth == CV_64F ? (IppSortFunc)ippsSortDescend_64f_I : +#endif + 0; } static IppFlipFunc getFlipFunc(int depth) @@ -3911,7 +3914,7 @@ public: const _Tp* arr; }; -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(void *, int *, int); @@ -3958,7 +3961,7 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) bptr = (T*)buf; _iptr = (int*)ibuf; -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK int depth = src.depth(); IppSortIndexFunc ippFunc = 0; IppFlipFunc ippFlipFunc = 0; @@ -3987,27 +3990,27 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) for( j = 0; j < len; j++ ) iptr[j] = j; -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK if (sortRows || !ippFunc || ippFunc(ptr, iptr, len) < 0) #endif { -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK setIppErrorStatus(); #endif std::sort( iptr, iptr + len, LessThanIdx(ptr) ); if( sortDescending ) { -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK if (!ippFlipFunc || ippFlipFunc(iptr, len) < 0) #endif { -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK setIppErrorStatus(); #endif for( j = 0; j < len/2; j++ ) std::swap(iptr[j], iptr[len-1-j]); } -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK else { CV_IMPL_ADD(CV_IMPL_IPP); @@ -4015,7 +4018,7 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) #endif } } -#if defined USE_IPP_SORT && 0 +#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK else { CV_IMPL_ADD(CV_IMPL_IPP); diff --git a/modules/core/src/ocl.cpp b/modules/core/src/ocl.cpp index 1074f9b01..1345c52e3 100644 --- a/modules/core/src/ocl.cpp +++ b/modules/core/src/ocl.cpp @@ -4453,8 +4453,11 @@ public: #endif { tempUMatFlags = UMatData::TEMP_UMAT; - handle = clCreateBuffer(ctx_handle, CL_MEM_USE_HOST_PTR|createFlags, - u->size, u->origdata, &retval); + if (u->origdata == cv::alignPtr(u->origdata, 4)) // There are OpenCL runtime issues for less aligned data + { + handle = clCreateBuffer(ctx_handle, CL_MEM_USE_HOST_PTR|createFlags, + u->size, u->origdata, &retval); + } if((!handle || retval < 0) && !(accessFlags & ACCESS_FAST)) { handle = clCreateBuffer(ctx_handle, CL_MEM_COPY_HOST_PTR|CL_MEM_READ_WRITE|createFlags, @@ -4510,16 +4513,17 @@ public: if(!u) return; - CV_Assert(u->urefcount >= 0); - CV_Assert(u->refcount >= 0); + CV_Assert(u->urefcount == 0); + CV_Assert(u->refcount == 0 && "UMat deallocation error: some derived Mat is still alive"); - CV_Assert(u->handle != 0 && u->urefcount == 0); + CV_Assert(u->handle != 0); + CV_Assert(u->mapcount == 0); if(u->tempUMat()) { CV_Assert(u->origdata); // UMatDataAutoLock lock(u); - if( u->hostCopyObsolete() && u->refcount > 0 ) + if (u->hostCopyObsolete()) { #ifdef HAVE_OPENCL_SVM if ((u->allocatorFlags_ & svm::OPENCL_SVM_BUFFER_MASK) != 0) @@ -4572,16 +4576,29 @@ public: else { cl_int retval = 0; - void* data = clEnqueueMapBuffer(q, (cl_mem)u->handle, CL_TRUE, - (CL_MAP_READ | CL_MAP_WRITE), - 0, u->size, 0, 0, 0, &retval); - CV_OclDbgAssert(retval == CL_SUCCESS); - CV_OclDbgAssert(clEnqueueUnmapMemObject(q, (cl_mem)u->handle, data, 0, 0, 0) == CL_SUCCESS); - CV_OclDbgAssert(clFinish(q) == CL_SUCCESS); + if (u->tempUMat()) + { + CV_Assert(u->mapcount == 0); + void* data = clEnqueueMapBuffer(q, (cl_mem)u->handle, CL_TRUE, + (CL_MAP_READ | CL_MAP_WRITE), + 0, u->size, 0, 0, 0, &retval); + CV_Assert(u->origdata == data); + CV_OclDbgAssert(retval == CL_SUCCESS); + if (u->originalUMatData) + { + CV_Assert(u->originalUMatData->data == data); + } + CV_OclDbgAssert(clEnqueueUnmapMemObject(q, (cl_mem)u->handle, data, 0, 0, 0) == CL_SUCCESS); + CV_OclDbgAssert(clFinish(q) == CL_SUCCESS); + } } } u->markHostCopyObsolete(false); } + else + { + // nothing + } #ifdef HAVE_OPENCL_SVM if ((u->allocatorFlags_ & svm::OPENCL_SVM_BUFFER_MASK) != 0) { @@ -4607,16 +4624,12 @@ public: if(u->data && u->copyOnMap() && u->data != u->origdata) fastFree(u->data); u->data = u->origdata; - if(u->refcount == 0) - { - u->currAllocator->deallocate(u); - u = NULL; - } + u->currAllocator->deallocate(u); + u = NULL; } else { CV_Assert(u->origdata == NULL); - CV_Assert(u->refcount == 0); if(u->data && u->copyOnMap() && u->data != u->origdata) { fastFree(u->data); @@ -4665,17 +4678,13 @@ public: delete u; u = NULL; } - CV_Assert(u == NULL || u->refcount); + CV_Assert(u == NULL); } + // synchronized call (external UMatDataAutoLock, see UMat::getMat) void map(UMatData* u, int accessFlags) const { - if(!u) - return; - - CV_Assert( u->handle != 0 ); - - UMatDataAutoLock autolock(u); + CV_Assert(u && u->handle); if(accessFlags & ACCESS_WRITE) u->markDeviceCopyObsolete(true); @@ -4715,11 +4724,16 @@ public: } #endif - cl_int retval = 0; - u->data = (uchar*)clEnqueueMapBuffer(q, (cl_mem)u->handle, CL_TRUE, - (CL_MAP_READ | CL_MAP_WRITE), - 0, u->size, 0, 0, 0, &retval); - if(u->data && retval == CL_SUCCESS) + cl_int retval = CL_SUCCESS; + if (!u->deviceMemMapped()) + { + CV_Assert(u->refcount == 1); + CV_Assert(u->mapcount++ == 0); + u->data = (uchar*)clEnqueueMapBuffer(q, (cl_mem)u->handle, CL_TRUE, + (CL_MAP_READ | CL_MAP_WRITE), + 0, u->size, 0, 0, 0, &retval); + } + if (u->data && retval == CL_SUCCESS) { u->markHostCopyObsolete(false); u->markDeviceMemMapped(true); @@ -4765,7 +4779,6 @@ public: if( !u->copyOnMap() && u->deviceMemMapped() ) { CV_Assert(u->data != NULL); - u->markDeviceMemMapped(false); #ifdef HAVE_OPENCL_SVM if ((u->allocatorFlags_ & svm::OPENCL_SVM_BUFFER_MASK) != 0) { @@ -4792,16 +4805,21 @@ public: return; } #endif - CV_Assert( (retval = clEnqueueUnmapMemObject(q, - (cl_mem)u->handle, u->data, 0, 0, 0)) == CL_SUCCESS ); - if (Device::getDefault().isAMD()) - { - // required for multithreaded applications (see stitching test) - CV_OclDbgAssert(clFinish(q) == CL_SUCCESS); - } - if (u->refcount == 0) + { + CV_Assert(u->mapcount-- == 1); + CV_Assert((retval = clEnqueueUnmapMemObject(q, + (cl_mem)u->handle, u->data, 0, 0, 0)) == CL_SUCCESS); + if (Device::getDefault().isAMD()) + { + // required for multithreaded applications (see stitching test) + CV_OclDbgAssert(clFinish(q) == CL_SUCCESS); + } + u->markDeviceMemMapped(false); u->data = 0; + u->markDeviceCopyObsolete(false); + u->markHostCopyObsolete(true); + } } else if( u->copyOnMap() && u->deviceCopyObsolete() ) { @@ -4811,9 +4829,9 @@ public: #endif CV_Assert( (retval = clEnqueueWriteBuffer(q, (cl_mem)u->handle, CL_TRUE, 0, u->size, alignedPtr.getAlignedPtr(), 0, 0, 0)) == CL_SUCCESS ); + u->markDeviceCopyObsolete(false); + u->markHostCopyObsolete(true); } - u->markDeviceCopyObsolete(false); - u->markHostCopyObsolete(true); } bool checkContinuous(int dims, const size_t sz[], diff --git a/modules/core/src/parallel_pthreads.cpp b/modules/core/src/parallel_pthreads.cpp index df99f18bf..8bf131e14 100644 --- a/modules/core/src/parallel_pthreads.cpp +++ b/modules/core/src/parallel_pthreads.cpp @@ -304,14 +304,18 @@ void ForThread::stop() { if(m_state == eFTStarted) { + pthread_mutex_lock(&m_thread_mutex); m_state = eFTToStop; + pthread_mutex_unlock(&m_thread_mutex); run(); pthread_join(m_posix_thread, NULL); } + pthread_mutex_lock(&m_thread_mutex); m_state = eFTStoped; + pthread_mutex_unlock(&m_thread_mutex); } void ForThread::run() diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index e20a66f69..6123d3f3d 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -50,7 +50,7 @@ #include "opencv2/core/core_c.h" #include "opencv2/core/cuda.hpp" #include "opencv2/core/opengl.hpp" -#include "opencv2/core/vaapi.hpp" +#include "opencv2/core/va_intel.hpp" #include "opencv2/core/private.hpp" #include "opencv2/core/private.cuda.hpp" @@ -206,7 +206,7 @@ extern volatile bool USE_AVX2; enum { BLOCK_SIZE = 1024 }; -#if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7) +#if defined HAVE_IPP && (IPP_VERSION_X100 >= 700) #define ARITHM_USE_IPP 1 #else #define ARITHM_USE_IPP 0 diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 0a4c0415c..4e60dbe4f 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -1141,7 +1141,7 @@ static bool ocl_sum( InputArray _src, Scalar & res, int sum_op, InputArray _mask #ifdef HAVE_IPP static bool ipp_sum(Mat &src, Scalar &_res) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 int cn = src.channels(); size_t total_size = src.total(); int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; @@ -1203,7 +1203,7 @@ cv::Scalar cv::sum( InputArray _src ) #endif Mat src = _src.getMat(); - CV_IPP_RUN(IPP_VERSION_MAJOR >= 7, ipp_sum(src, _res), _res); + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_sum(src, _res), _res); int k, cn = src.channels(), depth = src.depth(); SumFunc func = getSumFunc(depth); @@ -1368,100 +1368,106 @@ int cv::countNonZero( InputArray _src ) return nz; } +#if defined HAVE_IPP +namespace cv +{ +static bool ipp_mean( Mat &src, Mat &mask, Scalar &ret ) +{ +#if IPP_VERSION_X100 >= 700 + size_t total_size = src.total(); + int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; + if( src.dims == 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) ) + { + IppiSize sz = { cols, rows }; + int type = src.type(); + if( !mask.empty() ) + { + typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *); + ippiMaskMeanFuncC1 ippFuncC1 = + type == CV_8UC1 ? (ippiMaskMeanFuncC1)ippiMean_8u_C1MR : + type == CV_16UC1 ? (ippiMaskMeanFuncC1)ippiMean_16u_C1MR : + type == CV_32FC1 ? (ippiMaskMeanFuncC1)ippiMean_32f_C1MR : + 0; + if( ippFuncC1 ) + { + Ipp64f res; + if( ippFuncC1(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &res) >= 0 ) + { + ret = Scalar(res); + return true; + } + } + typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); + ippiMaskMeanFuncC3 ippFuncC3 = + type == CV_8UC3 ? (ippiMaskMeanFuncC3)ippiMean_8u_C3CMR : + type == CV_16UC3 ? (ippiMaskMeanFuncC3)ippiMean_16u_C3CMR : + type == CV_32FC3 ? (ippiMaskMeanFuncC3)ippiMean_32f_C3CMR : + 0; + if( ippFuncC3 ) + { + Ipp64f res1, res2, res3; + if( ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 1, &res1) >= 0 && + ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 2, &res2) >= 0 && + ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 3, &res3) >= 0 ) + { + ret = Scalar(res1, res2, res3); + return true; + } + } + } + else + { + typedef IppStatus (CV_STDCALL* ippiMeanFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm); + typedef IppStatus (CV_STDCALL* ippiMeanFuncNoHint)(const void*, int, IppiSize, double *); + ippiMeanFuncHint ippFuncHint = + type == CV_32FC1 ? (ippiMeanFuncHint)ippiMean_32f_C1R : + type == CV_32FC3 ? (ippiMeanFuncHint)ippiMean_32f_C3R : + type == CV_32FC4 ? (ippiMeanFuncHint)ippiMean_32f_C4R : + 0; + ippiMeanFuncNoHint ippFuncNoHint = + type == CV_8UC1 ? (ippiMeanFuncNoHint)ippiMean_8u_C1R : + type == CV_8UC3 ? (ippiMeanFuncNoHint)ippiMean_8u_C3R : + type == CV_8UC4 ? (ippiMeanFuncNoHint)ippiMean_8u_C4R : + type == CV_16UC1 ? (ippiMeanFuncNoHint)ippiMean_16u_C1R : + type == CV_16UC3 ? (ippiMeanFuncNoHint)ippiMean_16u_C3R : + type == CV_16UC4 ? (ippiMeanFuncNoHint)ippiMean_16u_C4R : + type == CV_16SC1 ? (ippiMeanFuncNoHint)ippiMean_16s_C1R : + type == CV_16SC3 ? (ippiMeanFuncNoHint)ippiMean_16s_C3R : + type == CV_16SC4 ? (ippiMeanFuncNoHint)ippiMean_16s_C4R : + 0; + // Make sure only zero or one version of the function pointer is valid + CV_Assert(!ippFuncHint || !ippFuncNoHint); + if( ippFuncHint || ippFuncNoHint ) + { + Ipp64f res[4]; + IppStatus status = ippFuncHint ? ippFuncHint(src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) : + ippFuncNoHint(src.ptr(), (int)src.step[0], sz, res); + if( status >= 0 ) + { + for( int i = 0; i < src.channels(); i++ ) + ret[i] = res[i]; + return true; + } + } + } + } + return false; +#else + return false; +#endif +} +} +#endif + cv::Scalar cv::mean( InputArray _src, InputArray _mask ) { Mat src = _src.getMat(), mask = _mask.getMat(); CV_Assert( mask.empty() || mask.type() == CV_8U ); int k, cn = src.channels(), depth = src.depth(); + Scalar s; -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - CV_IPP_CHECK() - { - size_t total_size = src.total(); - int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; - if( src.dims == 2 || (src.isContinuous() && mask.isContinuous() && cols > 0 && (size_t)rows*cols == total_size) ) - { - IppiSize sz = { cols, rows }; - int type = src.type(); - if( !mask.empty() ) - { - typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC1)(const void *, int, const void *, int, IppiSize, Ipp64f *); - ippiMaskMeanFuncC1 ippFuncC1 = - type == CV_8UC1 ? (ippiMaskMeanFuncC1)ippiMean_8u_C1MR : - type == CV_16UC1 ? (ippiMaskMeanFuncC1)ippiMean_16u_C1MR : - type == CV_32FC1 ? (ippiMaskMeanFuncC1)ippiMean_32f_C1MR : - 0; - if( ippFuncC1 ) - { - Ipp64f res; - if( ippFuncC1(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, &res) >= 0 ) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return Scalar(res); - } - setIppErrorStatus(); - } - typedef IppStatus (CV_STDCALL* ippiMaskMeanFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); - ippiMaskMeanFuncC3 ippFuncC3 = - type == CV_8UC3 ? (ippiMaskMeanFuncC3)ippiMean_8u_C3CMR : - type == CV_16UC3 ? (ippiMaskMeanFuncC3)ippiMean_16u_C3CMR : - type == CV_32FC3 ? (ippiMaskMeanFuncC3)ippiMean_32f_C3CMR : - 0; - if( ippFuncC3 ) - { - Ipp64f res1, res2, res3; - if( ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 1, &res1) >= 0 && - ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 2, &res2) >= 0 && - ippFuncC3(src.ptr(), (int)src.step[0], mask.ptr(), (int)mask.step[0], sz, 3, &res3) >= 0 ) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return Scalar(res1, res2, res3); - } - setIppErrorStatus(); - } - } - else - { - typedef IppStatus (CV_STDCALL* ippiMeanFuncHint)(const void*, int, IppiSize, double *, IppHintAlgorithm); - typedef IppStatus (CV_STDCALL* ippiMeanFuncNoHint)(const void*, int, IppiSize, double *); - ippiMeanFuncHint ippFuncHint = - type == CV_32FC1 ? (ippiMeanFuncHint)ippiMean_32f_C1R : - type == CV_32FC3 ? (ippiMeanFuncHint)ippiMean_32f_C3R : - type == CV_32FC4 ? (ippiMeanFuncHint)ippiMean_32f_C4R : - 0; - ippiMeanFuncNoHint ippFuncNoHint = - type == CV_8UC1 ? (ippiMeanFuncNoHint)ippiMean_8u_C1R : - type == CV_8UC3 ? (ippiMeanFuncNoHint)ippiMean_8u_C3R : - type == CV_8UC4 ? (ippiMeanFuncNoHint)ippiMean_8u_C4R : - type == CV_16UC1 ? (ippiMeanFuncNoHint)ippiMean_16u_C1R : - type == CV_16UC3 ? (ippiMeanFuncNoHint)ippiMean_16u_C3R : - type == CV_16UC4 ? (ippiMeanFuncNoHint)ippiMean_16u_C4R : - type == CV_16SC1 ? (ippiMeanFuncNoHint)ippiMean_16s_C1R : - type == CV_16SC3 ? (ippiMeanFuncNoHint)ippiMean_16s_C3R : - type == CV_16SC4 ? (ippiMeanFuncNoHint)ippiMean_16s_C4R : - 0; - // Make sure only zero or one version of the function pointer is valid - CV_Assert(!ippFuncHint || !ippFuncNoHint); - if( ippFuncHint || ippFuncNoHint ) - { - Ipp64f res[4]; - IppStatus ret = ippFuncHint ? ippFuncHint(src.ptr(), (int)src.step[0], sz, res, ippAlgHintAccurate) : - ippFuncNoHint(src.ptr(), (int)src.step[0], sz, res); - if( ret >= 0 ) - { - Scalar sc; - for( int i = 0; i < cn; i++ ) - sc[i] = res[i]; - CV_IMPL_ADD(CV_IMPL_IPP); - return sc; - } - setIppErrorStatus(); - } - } - } - } -#endif + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_mean(src, mask, s), s) SumFunc func = getSumFunc(depth); @@ -1470,7 +1476,6 @@ cv::Scalar cv::mean( InputArray _src, InputArray _mask ) const Mat* arrays[] = {&src, &mask, 0}; uchar* ptrs[2]; NAryMatIterator it(arrays, ptrs); - Scalar s; int total = (int)it.size, blockSize = total, intSumBlockSize = 0; int j, count = 0; AutoBuffer _buf; @@ -1640,7 +1645,7 @@ namespace cv { static bool ipp_meanStdDev(Mat& src, OutputArray _mean, OutputArray _sdv, Mat& mask) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 int cn = src.channels(); size_t total_size = src.total(); int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; @@ -1712,7 +1717,7 @@ static bool ipp_meanStdDev(Mat& src, OutputArray _mean, OutputArray _sdv, Mat& m ippiMeanStdDevFuncC1 ippFuncC1 = type == CV_8UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_8u_C1R : type == CV_16UC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_16u_C1R : -#if (IPP_VERSION_X100 >= 801) +#if (IPP_VERSION_X100 >= 810) type == CV_32FC1 ? (ippiMeanStdDevFuncC1)ippiMean_StdDev_32f_C1R ://Aug 2013: bug in IPP 7.1, 8.0 #endif 0; @@ -1756,7 +1761,7 @@ void cv::meanStdDev( InputArray _src, OutputArray _mean, OutputArray _sdv, Input Mat src = _src.getMat(), mask = _mask.getMat(); CV_Assert( mask.empty() || mask.type() == CV_8UC1 ); - CV_IPP_RUN(IPP_VERSION_MAJOR >= 7, ipp_meanStdDev(src, _mean, _sdv, mask)); + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_meanStdDev(src, _mean, _sdv, mask)); int k, cn = src.channels(), depth = src.depth(); @@ -2212,7 +2217,7 @@ static bool ocl_minMaxIdx( InputArray _src, double* minVal, double* maxVal, int* #ifdef HAVE_IPP static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx, int* maxIdx, Mat &mask) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); size_t total_size = src.total(); int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; @@ -2228,7 +2233,9 @@ static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx CV_SUPPRESS_DEPRECATED_START ippiMaskMinMaxIndxFuncC1 ippFuncC1 = type == CV_8UC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_16u_C1MR : type == CV_32FC1 ? (ippiMaskMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1MR : 0; CV_SUPPRESS_DEPRECATED_END @@ -2265,8 +2272,12 @@ static bool ipp_minMaxIdx( Mat &src, double* minVal, double* maxVal, int* minIdx CV_SUPPRESS_DEPRECATED_START ippiMinMaxIndxFuncC1 ippFuncC1 = +#if IPP_VERSION_X100 != 900 // bug in 9.0.0 avx2 optimization depth == CV_8U ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_8u_C1R : +#endif +#if IPP_VERSION_X100 < 900 depth == CV_8S ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_8s_C1R : +#endif depth == CV_16U ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_16u_C1R : #if !((defined _MSC_VER && defined _M_IX86) || defined __i386__) depth == CV_32F ? (ippiMinMaxIndxFuncC1)ippiMinMaxIndx_32f_C1R : @@ -2320,7 +2331,7 @@ void cv::minMaxIdx(InputArray _src, double* minVal, ocl_minMaxIdx(_src, minVal, maxVal, minIdx, maxIdx, _mask)) Mat src = _src.getMat(), mask = _mask.getMat(); - CV_IPP_RUN(IPP_VERSION_MAJOR >= 7, ipp_minMaxIdx(src, minVal, maxVal, minIdx, maxIdx, mask)) + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_minMaxIdx(src, minVal, maxVal, minIdx, maxIdx, mask)) MinMaxIdxFunc func = getMinmaxTab(depth); CV_Assert( func != 0 ); @@ -2331,8 +2342,8 @@ void cv::minMaxIdx(InputArray _src, double* minVal, size_t minidx = 0, maxidx = 0; int iminval = INT_MAX, imaxval = INT_MIN; - float fminval = FLT_MAX, fmaxval = -FLT_MAX; - double dminval = DBL_MAX, dmaxval = -DBL_MAX; + float fminval = std::numeric_limits::infinity(), fmaxval = -fminval; + double dminval = std::numeric_limits::infinity(), dmaxval = -dminval; size_t startidx = 1; int *minval = &iminval, *maxval = &imaxval; int planeSize = (int)it.size*cn; @@ -2345,6 +2356,14 @@ void cv::minMaxIdx(InputArray _src, double* minVal, for( size_t i = 0; i < it.nplanes; i++, ++it, startidx += planeSize ) func( ptrs[0], ptrs[1], minval, maxval, &minidx, &maxidx, planeSize, startidx ); + if (!src.empty() && mask.empty()) + { + if( minidx == 0 ) + minidx = 1; + if( maxidx == 0 ) + maxidx = 1; + } + if( minidx == 0 ) dminval = dmaxval = 0; else if( depth == CV_32F ) @@ -2645,7 +2664,7 @@ static bool ocl_norm( InputArray _src, int normType, InputArray _mask, double & #ifdef HAVE_IPP static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 int cn = src.channels(); size_t total_size = src.total(); int rows = src.size[0], cols = rows ? (int)(total_size/rows) : 0; @@ -2663,19 +2682,25 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) ippiMaskNormFuncC1 ippFuncC1 = normType == NORM_INF ? (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_8s_C1MR : +#endif // type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_Inf_32f_C1MR : 0) : normType == NORM_L1 ? (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_L1_32f_C1MR : 0) : normType == NORM_L2 || normType == NORM_L2SQR ? (type == CV_8UC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormFuncC1)ippiNorm_L2_32f_C1MR : 0) : 0; @@ -2688,7 +2713,8 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) return true; } } - /*typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); +#if IPP_DISABLE_BLOCK + typedef IppStatus (CV_STDCALL* ippiMaskNormFuncC3)(const void *, int, const void *, int, IppiSize, int, Ipp64f *); ippiMaskNormFuncC3 ippFuncC3 = normType == NORM_INF ? (type == CV_8UC3 ? (ippiMaskNormFuncC3)ippiNorm_Inf_8u_C3CMR : @@ -2723,7 +2749,8 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) result = (normType == NORM_L2SQR ? (double)(norm * norm) : (double)norm); return true; } - }*/ + } +#endif } else { @@ -2749,7 +2776,7 @@ static bool ipp_norm(Mat &src, int normType, Mat &mask, double &result) type == CV_16UC3 ? (ippiNormFuncNoHint)ippiNorm_Inf_16u_C3R : type == CV_16UC4 ? (ippiNormFuncNoHint)ippiNorm_Inf_16u_C4R : type == CV_16SC1 ? (ippiNormFuncNoHint)ippiNorm_Inf_16s_C1R : -#if (IPP_VERSION_X100 >= 801) +#if (IPP_VERSION_X100 >= 810) type == CV_16SC3 ? (ippiNormFuncNoHint)ippiNorm_Inf_16s_C3R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 type == CV_16SC4 ? (ippiNormFuncNoHint)ippiNorm_Inf_16s_C4R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 #endif @@ -2829,7 +2856,7 @@ double cv::norm( InputArray _src, int normType, InputArray _mask ) #endif Mat src = _src.getMat(), mask = _mask.getMat(); - CV_IPP_RUN(IPP_VERSION_MAJOR >= 7, ipp_norm(src, normType, mask, _result), _result); + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_norm(src, normType, mask, _result), _result); int depth = src.depth(), cn = src.channels(); if( src.isContinuous() && mask.empty() ) @@ -3033,7 +3060,7 @@ namespace cv { static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArray _mask, double &result) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); if( normType & CV_RELATIVE ) @@ -3056,23 +3083,29 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra ippiMaskNormRelFuncC1 ippFuncC1 = normType == NORM_INF ? (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_8u_C1MR : +#if IPP_VERSION_X100 < 900 #ifndef __APPLE__ type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_8s_C1MR : +#endif #endif type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_Inf_32f_C1MR : 0) : normType == NORM_L1 ? (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_8u_C1MR : +#if IPP_VERSION_X100 < 900 #ifndef __APPLE__ type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_8s_C1MR : +#endif #endif type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L1_32f_C1MR : 0) : normType == NORM_L2 || normType == NORM_L2SQR ? (type == CV_8UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormRelFuncC1)ippiNormRel_L2_32f_C1MR : 0) : 0; @@ -3157,21 +3190,27 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra ippiMaskNormDiffFuncC1 ippFuncC1 = normType == NORM_INF ? (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_Inf_32f_C1MR : 0) : normType == NORM_L1 ? (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_8u_C1MR : +#if IPP_VERSION_X100 < 900 #ifndef __APPLE__ type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_8s_C1MR : +#endif #endif type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L1_32f_C1MR : 0) : normType == NORM_L2 || normType == NORM_L2SQR ? (type == CV_8UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_8u_C1MR : +#if IPP_VERSION_X100 < 900 type == CV_8SC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_8s_C1MR : +#endif type == CV_16UC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_16u_C1MR : type == CV_32FC1 ? (ippiMaskNormDiffFuncC1)ippiNormDiff_L2_32f_C1MR : 0) : 0; @@ -3189,19 +3228,25 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra ippiMaskNormDiffFuncC3 ippFuncC3 = normType == NORM_INF ? (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_8u_C3CMR : +#if IPP_VERSION_X100 < 900 type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_8s_C3CMR : +#endif type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_16u_C3CMR : type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_Inf_32f_C3CMR : 0) : normType == NORM_L1 ? (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_8u_C3CMR : +#if IPP_VERSION_X100 < 900 type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_8s_C3CMR : +#endif type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_16u_C3CMR : type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L1_32f_C3CMR : 0) : normType == NORM_L2 || normType == NORM_L2SQR ? (type == CV_8UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_8u_C3CMR : +#if IPP_VERSION_X100 < 900 type == CV_8SC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_8s_C3CMR : +#endif type == CV_16UC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_16u_C3CMR : type == CV_32FC3 ? (ippiMaskNormDiffFuncC3)ippiNormDiff_L2_32f_C3CMR : 0) : 0; @@ -3247,7 +3292,7 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra type == CV_16UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16u_C3R : type == CV_16UC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16u_C4R : type == CV_16SC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16s_C1R : -#if (IPP_VERSION_X100 >= 801) +#if (IPP_VERSION_X100 >= 810) type == CV_16SC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16s_C3R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 type == CV_16SC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_Inf_16s_C4R : //Aug 2013: problem in IPP 7.1, 8.0 : -32768 #endif @@ -3262,7 +3307,7 @@ static bool ipp_norm(InputArray _src1, InputArray _src2, int normType, InputArra type == CV_16UC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16u_C1R : type == CV_16UC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16u_C3R : type == CV_16UC4 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16u_C4R : -#if !(IPP_VERSION_X100 == 802 && (!defined(IPP_VERSION_UPDATE) || IPP_VERSION_UPDATE <= 1)) // Oct 2014: Accuracy issue with IPP 8.2 / 8.2.1 +#if !(IPP_VERSION_X100 == 820 || IPP_VERSION_X100 == 821) // Oct 2014: Accuracy issue with IPP 8.2 / 8.2.1 type == CV_16SC1 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16s_C1R : #endif type == CV_16SC3 ? (ippiNormDiffFuncNoHint)ippiNormDiff_L1_16s_C3R : @@ -3326,7 +3371,7 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m _result) #endif - CV_IPP_RUN(IPP_VERSION_MAJOR >= 7, ipp_norm(_src1, _src2, normType, _mask, _result), _result); + CV_IPP_RUN(IPP_VERSION_X100 >= 700, ipp_norm(_src1, _src2, normType, _mask, _result), _result); if( normType & CV_RELATIVE ) { diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 743341daf..8c0072aed 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -42,6 +42,7 @@ //M*/ #include "precomp.hpp" +#include namespace cv { @@ -377,21 +378,6 @@ bool checkHardwareSupport(int feature) volatile bool useOptimizedFlag = true; -#ifdef HAVE_IPP -struct IPPInitializer -{ - IPPInitializer(void) - { -#if IPP_VERSION_MAJOR >= 8 - ippInit(); -#else - ippStaticInit(); -#endif - } -}; - -IPPInitializer ippInitializer; -#endif volatile bool USE_SSE2 = featuresEnabled.have[CV_CPU_SSE2]; volatile bool USE_SSE4_2 = featuresEnabled.have[CV_CPU_SSE4_2]; @@ -1034,7 +1020,7 @@ class TlsStorage public: TlsStorage() { - tlsSlots = 0; + tlsSlots.reserve(32); threads.reserve(32); } ~TlsStorage() @@ -1077,15 +1063,27 @@ public: size_t reserveSlot() { AutoLock guard(mtxGlobalAccess); - tlsSlots++; - return (tlsSlots-1); + + // Find unused slots + for(size_t slot = 0; slot < tlsSlots.size(); slot++) + { + if(!tlsSlots[slot]) + { + tlsSlots[slot] = 1; + return slot; + } + } + + // Create new slot + tlsSlots.push_back(1); + return (tlsSlots.size()-1); } // Release TLS storage index and pass assosiated data to caller void releaseSlot(size_t slotIdx, std::vector &dataVec) { AutoLock guard(mtxGlobalAccess); - CV_Assert(tlsSlots > slotIdx); + CV_Assert(tlsSlots.size() > slotIdx); for(size_t i = 0; i < threads.size(); i++) { @@ -1096,15 +1094,14 @@ public: threads[i]->slots[slotIdx] = 0; } } - // If we removing last element, decriment slots size to save space - if(tlsSlots-1 == slotIdx) - tlsSlots--; + + tlsSlots[slotIdx] = 0; } // Get data by TLS storage index void* getData(size_t slotIdx) const { - CV_Assert(tlsSlots > slotIdx); + CV_Assert(tlsSlots.size() > slotIdx); ThreadData* threadData = (ThreadData*)tls.GetData(); if(threadData && threadData->slots.size() > slotIdx) @@ -1113,10 +1110,24 @@ public: return NULL; } + // Gather data from threads by TLS storage index + void gather(size_t slotIdx, std::vector &dataVec) + { + AutoLock guard(mtxGlobalAccess); + CV_Assert(tlsSlots.size() > slotIdx); + + for(size_t i = 0; i < threads.size(); i++) + { + std::vector& thread_slots = threads[i]->slots; + if (thread_slots.size() > slotIdx && thread_slots[slotIdx]) + dataVec.push_back(thread_slots[slotIdx]); + } + } + // Set data to storage index void setData(size_t slotIdx, void* pData) { - CV_Assert(pData != NULL); + CV_Assert(tlsSlots.size() > slotIdx && pData != NULL); ThreadData* threadData = (ThreadData*)tls.GetData(); if(!threadData) @@ -1131,7 +1142,11 @@ public: } if(slotIdx >= threadData->slots.size()) - threadData->slots.resize(slotIdx+1); + { + AutoLock guard(mtxGlobalAccess); + while(slotIdx >= threadData->slots.size()) + threadData->slots.push_back(NULL); + } threadData->slots[slotIdx] = pData; } @@ -1139,7 +1154,7 @@ private: TlsAbstraction tls; // TLS abstraction layer instance Mutex mtxGlobalAccess; // Shared objects operation guard - size_t tlsSlots; // TLS storage counter + std::vector tlsSlots; // TLS keys state std::vector threads; // Array for all allocated data. Thread data pointers are placed here to allow data cleanup }; @@ -1159,6 +1174,11 @@ TLSDataContainer::~TLSDataContainer() CV_Assert(key_ == -1); // Key must be released in child object } +void TLSDataContainer::gatherData(std::vector &data) const +{ + getTlsStorage().gather(key_, data); +} + void TLSDataContainer::release() { std::vector data; @@ -1271,26 +1291,93 @@ void setUseCollection(bool flag) namespace ipp { -static int ippStatus = 0; // 0 - all is ok, -1 - IPP functions failed -static const char * funcname = NULL, * filename = NULL; -static int linen = 0; +struct IPPInitSingelton +{ +public: + IPPInitSingelton() + { + useIPP = true; + ippStatus = 0; + funcname = NULL; + filename = NULL; + linen = 0; + ippFeatures = 0; + +#ifdef HAVE_IPP + const char* pIppEnv = getenv("OPENCV_IPP"); + cv::String env = pIppEnv; + if(env.size()) + { + if(env == "disabled") + { + std::cerr << "WARNING: IPP was disabled by OPENCV_IPP environment variable" << std::endl; + useIPP = false; + } +#if IPP_VERSION_X100 >= 900 + else if(env == "sse") + ippFeatures = ippCPUID_SSE; + else if(env == "sse2") + ippFeatures = ippCPUID_SSE2; + else if(env == "sse3") + ippFeatures = ippCPUID_SSE3; + else if(env == "ssse3") + ippFeatures = ippCPUID_SSSE3; + else if(env == "sse41") + ippFeatures = ippCPUID_SSE41; + else if(env == "sse42") + ippFeatures = ippCPUID_SSE42; + else if(env == "avx") + ippFeatures = ippCPUID_AVX; + else if(env == "avx2") + ippFeatures = ippCPUID_AVX2; +#endif + else + std::cerr << "ERROR: Improper value of OPENCV_IPP: " << env.c_str() << std::endl; + } + + IPP_INITIALIZER(ippFeatures) +#endif + } + + bool useIPP; + + int ippStatus; // 0 - all is ok, -1 - IPP functions failed + const char *funcname; + const char *filename; + int linen; + int ippFeatures; +}; + +static IPPInitSingelton& getIPPSingelton() +{ + CV_SINGLETON_LAZY_INIT_REF(IPPInitSingelton, new IPPInitSingelton()) +} + +int getIppFeatures() +{ +#ifdef HAVE_IPP + return getIPPSingelton().ippFeatures; +#else + return 0; +#endif +} void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line) { - ippStatus = status; - funcname = _funcname; - filename = _filename; - linen = _line; + getIPPSingelton().ippStatus = status; + getIPPSingelton().funcname = _funcname; + getIPPSingelton().filename = _filename; + getIPPSingelton().linen = _line; } int getIppStatus() { - return ippStatus; + return getIPPSingelton().ippStatus; } String getIppErrorLocation() { - return format("%s:%d %s", filename ? filename : "", linen, funcname ? funcname : ""); + return format("%s:%d %s", getIPPSingelton().filename ? getIPPSingelton().filename : "", getIPPSingelton().linen, getIPPSingelton().funcname ? getIPPSingelton().funcname : ""); } bool useIPP() @@ -1299,11 +1386,7 @@ bool useIPP() CoreTLSData* data = getCoreTlsData().get(); if(data->useIPP < 0) { - const char* pIppEnv = getenv("OPENCV_IPP"); - if(pIppEnv && (cv::String(pIppEnv) == "disabled")) - data->useIPP = false; - else - data->useIPP = true; + data->useIPP = getIPPSingelton().useIPP; } return (data->useIPP > 0); #else diff --git a/modules/core/src/umatrix.cpp b/modules/core/src/umatrix.cpp index ad7efae16..999a5cc18 100644 --- a/modules/core/src/umatrix.cpp +++ b/modules/core/src/umatrix.cpp @@ -60,25 +60,71 @@ static Mutex umatLocks[UMAT_NLOCKS]; UMatData::UMatData(const MatAllocator* allocator) { prevAllocator = currAllocator = allocator; - urefcount = refcount = 0; + urefcount = refcount = mapcount = 0; data = origdata = 0; size = 0; flags = 0; handle = 0; userdata = 0; allocatorFlags_ = 0; + originalUMatData = NULL; } UMatData::~UMatData() { prevAllocator = currAllocator = 0; urefcount = refcount = 0; + CV_Assert(mapcount == 0); data = origdata = 0; size = 0; flags = 0; handle = 0; userdata = 0; allocatorFlags_ = 0; + if (originalUMatData) + { + UMatData* u = originalUMatData; + CV_XADD(&(u->urefcount), -1); + CV_XADD(&(u->refcount), -1); + bool showWarn = false; + if (u->refcount == 0) + { + if (u->urefcount > 0) + showWarn = true; + // simulate Mat::deallocate + if (u->mapcount != 0) + { + (u->currAllocator ? u->currAllocator : /* TODO allocator ? allocator :*/ Mat::getStdAllocator())->unmap(u); + } + else + { + // we don't do "map", so we can't do "unmap" + } + } + if (u->refcount == 0 && u->urefcount == 0) // oops, we need to free resources + { + showWarn = true; + // simulate UMat::deallocate + u->currAllocator->deallocate(u); + } +#ifndef NDEBUG + if (showWarn) + { + static int warn_message_showed = 0; + if (warn_message_showed++ < 100) + { + fflush(stdout); + fprintf(stderr, "\n! OPENCV warning: getUMat()/getMat() call chain possible problem." + "\n! Base object is dead, while nested/derived object is still alive or processed." + "\n! Please check lifetime of UMat/Mat objects!\n"); + fflush(stderr); + } + } +#else + (void)showWarn; +#endif + originalUMatData = NULL; + } } void UMatData::lock() @@ -221,19 +267,34 @@ UMat Mat::getUMat(int accessFlags, UMatUsageFlags usageFlags) const UMat hdr; if(!data) return hdr; + Size wholeSize; + Point ofs; + locateROI(wholeSize, ofs); + Size sz(cols, rows); + if (ofs.x != 0 || ofs.y != 0) + { + Mat src = *this; + int dtop = ofs.y; + int dbottom = wholeSize.height - src.rows - ofs.y; + int dleft = ofs.x; + int dright = wholeSize.width - src.cols - ofs.x; + src.adjustROI(dtop, dbottom, dleft, dright); + return src.getUMat(accessFlags, usageFlags)(cv::Rect(ofs.x, ofs.y, sz.width, sz.height)); + } + CV_Assert(data == datastart); + accessFlags |= ACCESS_RW; - UMatData* temp_u = u; - if(!temp_u) + UMatData* new_u = NULL; { MatAllocator *a = allocator, *a0 = getStdAllocator(); if(!a) a = a0; - temp_u = a->allocate(dims, size.p, type(), data, step.p, accessFlags, usageFlags); + new_u = a->allocate(dims, size.p, type(), data, step.p, accessFlags, usageFlags); } bool allocated = false; try { - allocated = UMat::getStdAllocator()->allocate(temp_u, accessFlags, usageFlags); + allocated = UMat::getStdAllocator()->allocate(new_u, accessFlags, usageFlags); } catch (const cv::Exception& e) { @@ -241,14 +302,26 @@ UMat Mat::getUMat(int accessFlags, UMatUsageFlags usageFlags) const } if (!allocated) { - allocated = getStdAllocator()->allocate(temp_u, accessFlags, usageFlags); + allocated = getStdAllocator()->allocate(new_u, accessFlags, usageFlags); CV_Assert(allocated); } + if (u != NULL) + { +#ifdef HAVE_OPENCL + if (ocl::useOpenCL() && new_u->currAllocator == ocl::getOpenCLAllocator()) + { + CV_Assert(new_u->tempUMat()); + } +#endif + new_u->originalUMatData = u; + CV_XADD(&(u->refcount), 1); + CV_XADD(&(u->urefcount), 1); + } hdr.flags = flags; setSize(hdr, dims, size.p, step.p); finalizeHdr(hdr); - hdr.u = temp_u; - hdr.offset = data - datastart; + hdr.u = new_u; + hdr.offset = 0; //data - datastart; hdr.addref(); return hdr; } @@ -639,16 +712,25 @@ Mat UMat::getMat(int accessFlags) const return Mat(); // TODO Support ACCESS_READ (ACCESS_WRITE) without unnecessary data transfers accessFlags |= ACCESS_RW; - u->currAllocator->map(u, accessFlags); - CV_Assert(u->data != 0); - Mat hdr(dims, size.p, type(), u->data + offset, step.p); - hdr.flags = flags; - hdr.u = u; - hdr.datastart = u->data; - hdr.data = u->data + offset; - hdr.datalimit = hdr.dataend = u->data + u->size; - CV_XADD(&hdr.u->refcount, 1); - return hdr; + UMatDataAutoLock autolock(u); + if(CV_XADD(&u->refcount, 1) == 0) + u->currAllocator->map(u, accessFlags); + if (u->data != 0) + { + Mat hdr(dims, size.p, type(), u->data + offset, step.p); + hdr.flags = flags; + hdr.u = u; + hdr.datastart = u->data; + hdr.data = u->data + offset; + hdr.datalimit = hdr.dataend = u->data + u->size; + return hdr; + } + else + { + CV_XADD(&u->refcount, -1); + CV_Assert(u->data != 0 && "Error mapping of UMat to host memory."); + return Mat(); + } } void* UMat::handle(int accessFlags) const @@ -656,10 +738,10 @@ void* UMat::handle(int accessFlags) const if( !u ) return 0; - // check flags: if CPU copy is newer, copy it back to GPU. - if( u->deviceCopyObsolete() ) + CV_Assert(u->refcount == 0); + CV_Assert(!u->deviceCopyObsolete() || u->copyOnMap()); + if (u->deviceCopyObsolete()) { - CV_Assert(u->refcount == 0 || u->origdata); u->currAllocator->unmap(u); } @@ -758,7 +840,7 @@ void UMat::copyTo(OutputArray _dst, InputArray _mask) const haveDstUninit ? ocl::KernelArg::WriteOnly(dst) : ocl::KernelArg::ReadWrite(dst)); - size_t globalsize[2] = { cols, rows }; + size_t globalsize[2] = { (size_t)cols, (size_t)rows }; if (k.run(2, globalsize, NULL, false)) { CV_IMPL_ADD(CV_IMPL_OCL); @@ -819,7 +901,7 @@ void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) con else k.args(srcarg, dstarg, alpha, beta, rowsPerWI); - size_t globalsize[2] = { dst.cols * cn, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dst.cols * cn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; if (k.run(2, globalsize, NULL, false)) { CV_IMPL_ADD(CV_IMPL_OCL); @@ -875,7 +957,7 @@ UMat& UMat::setTo(InputArray _value, InputArray _mask) setK.args(dstarg, scalararg); } - size_t globalsize[] = { cols * cn / kercn, (rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[] = { (size_t)cols * cn / kercn, ((size_t)rows + rowsPerWI - 1) / rowsPerWI }; if( setK.run(2, globalsize, NULL, false) ) { CV_IMPL_ADD(CV_IMPL_OCL); diff --git a/modules/core/src/va_intel.cpp b/modules/core/src/va_intel.cpp new file mode 100644 index 000000000..5cdd6e8f3 --- /dev/null +++ b/modules/core/src/va_intel.cpp @@ -0,0 +1,528 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +// Copyright (C) 2015, Itseez, Inc., all rights reserved. +// Third party copyrights are property of their respective owners. + +#include "precomp.hpp" + +#ifdef HAVE_VA +# include +#else // HAVE_VA +# define NO_VA_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without VA support (libva)") +#endif // HAVE_VA + +using namespace cv; + +//////////////////////////////////////////////////////////////////////// +// CL-VA Interoperability + +#ifdef HAVE_OPENCL +# include "opencv2/core/opencl/runtime/opencl_core.hpp" +# include "opencv2/core.hpp" +# include "opencv2/core/ocl.hpp" +# include "opencl_kernels_core.hpp" +#endif // HAVE_OPENCL + +#if defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL) +# include +#endif // HAVE_VA_INTEL && HAVE_OPENCL + +namespace cv { namespace va_intel { + +#if defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL) + +static clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn clGetDeviceIDsFromVA_APIMediaAdapterINTEL = NULL; +static clCreateFromVA_APIMediaSurfaceINTEL_fn clCreateFromVA_APIMediaSurfaceINTEL = NULL; +static clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn clEnqueueAcquireVA_APIMediaSurfacesINTEL = NULL; +static clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn clEnqueueReleaseVA_APIMediaSurfacesINTEL = NULL; + +static bool contextInitialized = false; + +#endif // HAVE_VA_INTEL && HAVE_OPENCL + +namespace ocl { + +Context& initializeContextFromVA(VADisplay display, bool tryInterop) +{ + (void)display; (void)tryInterop; +#if !defined(HAVE_VA) + NO_VA_SUPPORT_ERROR; +#else // !HAVE_VA +# if (defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL)) + contextInitialized = false; + if (tryInterop) + { + cl_uint numPlatforms; + cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms"); + if (numPlatforms == 0) + CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms"); + + std::vector platforms(numPlatforms); + status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get platform Id list"); + + // For CL-VA interop, we must find platform/device with "cl_intel_va_api_media_sharing" extension. + // With standard initialization procedure, we should examine platform extension string for that. + // But in practice, the platform ext string doesn't contain it, while device ext string does. + // Follow Intel procedure (see tutorial), we should obtain device IDs by extension call. + // Note that we must obtain function pointers using specific platform ID, and can't provide pointers in advance. + // So, we iterate and select the first platform, for which we got non-NULL pointers, device, and CL context. + + int found = -1; + cl_context context = 0; + cl_device_id device = 0; + + for (int i = 0; i < (int)numPlatforms; ++i) + { + // Get extension function pointers + + clGetDeviceIDsFromVA_APIMediaAdapterINTEL = (clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn) + clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromVA_APIMediaAdapterINTEL"); + clCreateFromVA_APIMediaSurfaceINTEL = (clCreateFromVA_APIMediaSurfaceINTEL_fn) + clGetExtensionFunctionAddressForPlatform(platforms[i], "clCreateFromVA_APIMediaSurfaceINTEL"); + clEnqueueAcquireVA_APIMediaSurfacesINTEL = (clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn) + clGetExtensionFunctionAddressForPlatform(platforms[i], "clEnqueueAcquireVA_APIMediaSurfacesINTEL"); + clEnqueueReleaseVA_APIMediaSurfacesINTEL = (clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn) + clGetExtensionFunctionAddressForPlatform(platforms[i], "clEnqueueReleaseVA_APIMediaSurfacesINTEL"); + + if (((void*)clGetDeviceIDsFromVA_APIMediaAdapterINTEL == NULL) || + ((void*)clCreateFromVA_APIMediaSurfaceINTEL == NULL) || + ((void*)clEnqueueAcquireVA_APIMediaSurfacesINTEL == NULL) || + ((void*)clEnqueueReleaseVA_APIMediaSurfacesINTEL == NULL)) + { + continue; + } + + // Query device list + + cl_uint numDevices = 0; + + status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display, + CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, &numDevices); + if ((status != CL_SUCCESS) || !(numDevices > 0)) + continue; + numDevices = 1; // initializeContextFromHandle() expects only 1 device + status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display, + CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, numDevices, &device, NULL); + if (status != CL_SUCCESS) + continue; + + // Creating CL-VA media sharing OpenCL context + + cl_context_properties props[] = { + CL_CONTEXT_VA_API_DISPLAY_INTEL, (cl_context_properties) display, + CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE, // no explicit sync required + 0 + }; + + context = clCreateContext(props, numDevices, &device, NULL, NULL, &status); + if (status != CL_SUCCESS) + { + clReleaseDevice(device); + } + else + { + found = i; + break; + } + } + + if (found >= 0) + { + contextInitialized = true; + Context& ctx = Context::getDefault(false); + initializeContextFromHandle(ctx, platforms[found], context, device); + return ctx; + } + } +# endif // HAVE_VA_INTEL && HAVE_OPENCL + { + Context& ctx = Context::getDefault(true); + return ctx; + } +#endif // !HAVE_VA +} + +#if defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL) +static bool ocl_convert_nv12_to_bgr(cl_mem clImageY, cl_mem clImageUV, cl_mem clBuffer, int step, int cols, int rows) +{ + ocl::Kernel k; + k.create("YUV2BGR_NV12_8u", cv::ocl::core::cvtclr_dx_oclsrc, ""); + if (k.empty()) + return false; + + k.args(clImageY, clImageUV, clBuffer, step, cols, rows); + + size_t globalsize[] = { (size_t)cols, (size_t)rows }; + return k.run(2, globalsize, 0, false); +} + +static bool ocl_convert_bgr_to_nv12(cl_mem clBuffer, int step, int cols, int rows, cl_mem clImageY, cl_mem clImageUV) +{ + ocl::Kernel k; + k.create("BGR2YUV_NV12_8u", cv::ocl::core::cvtclr_dx_oclsrc, ""); + if (k.empty()) + return false; + + k.args(clBuffer, step, cols, rows, clImageY, clImageUV); + + size_t globalsize[] = { (size_t)cols, (size_t)rows }; + return k.run(2, globalsize, 0, false); +} +#endif // HAVE_VA_INTEL && HAVE_OPENCL + +} // namespace cv::va_intel::ocl + +#if defined(HAVE_VA) +const int NCHANNELS = 3; + +static void copy_convert_nv12_to_bgr(const VAImage& image, const unsigned char* buffer, Mat& bgr) +{ + const float d1 = 16.0f; + const float d2 = 128.0f; + + static const float coeffs[5] = + { + 1.163999557f, + 2.017999649f, + -0.390999794f, + -0.812999725f, + 1.5959997177f + }; + + const size_t srcOffsetY = image.offsets[0]; + const size_t srcOffsetUV = image.offsets[1]; + + const size_t srcStepY = image.pitches[0]; + const size_t srcStepUV = image.pitches[1]; + + const size_t dstStep = bgr.step; + + const unsigned char* srcY0 = buffer + srcOffsetY; + const unsigned char* srcUV = buffer + srcOffsetUV; + + unsigned char* dst0 = bgr.data; + + for (int y = 0; y < bgr.rows; y += 2) + { + const unsigned char* srcY1 = srcY0 + srcStepY; + unsigned char *dst1 = dst0 + dstStep; + + for (int x = 0; x < bgr.cols; x += 2) + { + float Y0 = float(srcY0[x+0]); + float Y1 = float(srcY0[x+1]); + float Y2 = float(srcY1[x+0]); + float Y3 = float(srcY1[x+1]); + + float U = float(srcUV[2*(x/2)+0]) - d2; + float V = float(srcUV[2*(x/2)+1]) - d2; + + Y0 = std::max(0.0f, Y0 - d1) * coeffs[0]; + Y1 = std::max(0.0f, Y1 - d1) * coeffs[0]; + Y2 = std::max(0.0f, Y2 - d1) * coeffs[0]; + Y3 = std::max(0.0f, Y3 - d1) * coeffs[0]; + + float ruv = coeffs[4]*V; + float guv = coeffs[3]*V + coeffs[2]*U; + float buv = coeffs[1]*U; + + dst0[(x+0)*NCHANNELS+0] = saturate_cast(Y0 + buv); + dst0[(x+0)*NCHANNELS+1] = saturate_cast(Y0 + guv); + dst0[(x+0)*NCHANNELS+2] = saturate_cast(Y0 + ruv); + + dst0[(x+1)*NCHANNELS+0] = saturate_cast(Y1 + buv); + dst0[(x+1)*NCHANNELS+1] = saturate_cast(Y1 + guv); + dst0[(x+1)*NCHANNELS+2] = saturate_cast(Y1 + ruv); + + dst1[(x+0)*NCHANNELS+0] = saturate_cast(Y2 + buv); + dst1[(x+0)*NCHANNELS+1] = saturate_cast(Y2 + guv); + dst1[(x+0)*NCHANNELS+2] = saturate_cast(Y2 + ruv); + + dst1[(x+1)*NCHANNELS+0] = saturate_cast(Y3 + buv); + dst1[(x+1)*NCHANNELS+1] = saturate_cast(Y3 + guv); + dst1[(x+1)*NCHANNELS+2] = saturate_cast(Y3 + ruv); + } + + srcY0 = srcY1 + srcStepY; + srcUV += srcStepUV; + dst0 = dst1 + dstStep; + } +} + +static void copy_convert_bgr_to_nv12(const VAImage& image, const Mat& bgr, unsigned char* buffer) +{ + const float d1 = 16.0f; + const float d2 = 128.0f; + + static const float coeffs[8] = + { + 0.256999969f, 0.50399971f, 0.09799957f, -0.1479988098f, + -0.2909994125f, 0.438999176f, -0.3679990768f, -0.0709991455f + }; + + const size_t dstOffsetY = image.offsets[0]; + const size_t dstOffsetUV = image.offsets[1]; + + const size_t dstStepY = image.pitches[0]; + const size_t dstStepUV = image.pitches[1]; + + const size_t srcStep = bgr.step; + + const unsigned char* src0 = bgr.data; + + unsigned char* dstY0 = buffer + dstOffsetY; + unsigned char* dstUV = buffer + dstOffsetUV; + + for (int y = 0; y < bgr.rows; y += 2) + { + const unsigned char *src1 = src0 + srcStep; + unsigned char* dstY1 = dstY0 + dstStepY; + + for (int x = 0; x < bgr.cols; x += 2) + { + float B0 = float(src0[(x+0)*NCHANNELS+0]); + float G0 = float(src0[(x+0)*NCHANNELS+1]); + float R0 = float(src0[(x+0)*NCHANNELS+2]); + + float B1 = float(src0[(x+1)*NCHANNELS+0]); + float G1 = float(src0[(x+1)*NCHANNELS+1]); + float R1 = float(src0[(x+1)*NCHANNELS+2]); + + float B2 = float(src1[(x+0)*NCHANNELS+0]); + float G2 = float(src1[(x+0)*NCHANNELS+1]); + float R2 = float(src1[(x+0)*NCHANNELS+2]); + + float B3 = float(src1[(x+1)*NCHANNELS+0]); + float G3 = float(src1[(x+1)*NCHANNELS+1]); + float R3 = float(src1[(x+1)*NCHANNELS+2]); + + float Y0 = coeffs[0]*R0 + coeffs[1]*G0 + coeffs[2]*B0 + d1; + float Y1 = coeffs[0]*R1 + coeffs[1]*G1 + coeffs[2]*B1 + d1; + float Y2 = coeffs[0]*R2 + coeffs[1]*G2 + coeffs[2]*B2 + d1; + float Y3 = coeffs[0]*R3 + coeffs[1]*G3 + coeffs[2]*B3 + d1; + + float U = coeffs[3]*R0 + coeffs[4]*G0 + coeffs[5]*B0 + d2; + float V = coeffs[5]*R0 + coeffs[6]*G0 + coeffs[7]*B0 + d2; + + dstY0[x+0] = saturate_cast(Y0); + dstY0[x+1] = saturate_cast(Y1); + dstY1[x+0] = saturate_cast(Y2); + dstY1[x+1] = saturate_cast(Y3); + + dstUV[2*(x/2)+0] = saturate_cast(U); + dstUV[2*(x/2)+1] = saturate_cast(V); + } + + src0 = src1 + srcStep; + dstY0 = dstY1 + dstStepY; + dstUV += dstStepUV; + } +} +#endif // HAVE_VA + +void convertToVASurface(VADisplay display, InputArray src, VASurfaceID surface, Size size) +{ + (void)display; (void)src; (void)surface; (void)size; +#if !defined(HAVE_VA) + NO_VA_SUPPORT_ERROR; +#else // !HAVE_VA + const int stype = CV_8UC3; + + int srcType = src.type(); + CV_Assert(srcType == stype); + + Size srcSize = src.size(); + CV_Assert(srcSize.width == size.width && srcSize.height == size.height); + +# if (defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL)) + if (contextInitialized) + { + UMat u = src.getUMat(); + + // TODO Add support for roi + CV_Assert(u.offset == 0); + CV_Assert(u.isContinuous()); + + cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ); + + using namespace cv::ocl; + Context& ctx = Context::getDefault(); + cl_context context = (cl_context)ctx.ptr(); + + cl_int status = 0; + + cl_mem clImageY = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_WRITE_ONLY, &surface, 0, &status); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (Y plane)"); + cl_mem clImageUV = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_WRITE_ONLY, &surface, 1, &status); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (UV plane)"); + + cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); + + cl_mem images[2] = { clImageY, clImageUV }; + status = clEnqueueAcquireVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireVA_APIMediaSurfacesINTEL failed"); + if (!ocl::ocl_convert_bgr_to_nv12(clBuffer, (int)u.step[0], u.cols, u.rows, clImageY, clImageUV)) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_bgr_to_nv12 failed"); + clEnqueueReleaseVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseVA_APIMediaSurfacesINTEL failed"); + + status = clFinish(q); // TODO Use events + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed"); + + status = clReleaseMemObject(clImageY); // TODO RAII + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (Y plane)"); + status = clReleaseMemObject(clImageUV); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)"); + } + else +# endif // HAVE_VA_INTEL && HAVE_OPENCL + { + Mat m = src.getMat(); + + // TODO Add support for roi + CV_Assert(m.data == m.datastart); + CV_Assert(m.isContinuous()); + + VAStatus status = 0; + + status = vaSyncSurface(display, surface); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaSyncSurface failed"); + + VAImage image; + status = vaDeriveImage(display, surface, &image); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaDeriveImage failed"); + + unsigned char* buffer = 0; + status = vaMapBuffer(display, image.buf, (void **)&buffer); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaMapBuffer failed"); + + CV_Assert(image.format.fourcc == VA_FOURCC_NV12); + + copy_convert_bgr_to_nv12(image, m, buffer); + + status = vaUnmapBuffer(display, image.buf); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaUnmapBuffer failed"); + + status = vaDestroyImage(display, image.image_id); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaDestroyImage failed"); + } +#endif // !HAVE_VA +} + +void convertFromVASurface(VADisplay display, VASurfaceID surface, Size size, OutputArray dst) +{ + (void)display; (void)surface; (void)dst; (void)size; +#if !defined(HAVE_VA) + NO_VA_SUPPORT_ERROR; +#else // !HAVE_VA + const int dtype = CV_8UC3; + + // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying! + dst.create(size, dtype); + +# if (defined(HAVE_VA_INTEL) && defined(HAVE_OPENCL)) + if (contextInitialized) + { + UMat u = dst.getUMat(); + + // TODO Add support for roi + CV_Assert(u.offset == 0); + CV_Assert(u.isContinuous()); + + cl_mem clBuffer = (cl_mem)u.handle(ACCESS_WRITE); + + using namespace cv::ocl; + Context& ctx = Context::getDefault(); + cl_context context = (cl_context)ctx.ptr(); + + cl_int status = 0; + + cl_mem clImageY = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_READ_ONLY, &surface, 0, &status); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (Y plane)"); + cl_mem clImageUV = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_READ_ONLY, &surface, 1, &status); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (UV plane)"); + + cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); + + cl_mem images[2] = { clImageY, clImageUV }; + status = clEnqueueAcquireVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireVA_APIMediaSurfacesINTEL failed"); + if (!ocl::ocl_convert_nv12_to_bgr(clImageY, clImageUV, clBuffer, (int)u.step[0], u.cols, u.rows)) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_nv12_to_bgr failed"); + status = clEnqueueReleaseVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseVA_APIMediaSurfacesINTEL failed"); + + status = clFinish(q); // TODO Use events + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed"); + + status = clReleaseMemObject(clImageY); // TODO RAII + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (Y plane)"); + status = clReleaseMemObject(clImageUV); + if (status != CL_SUCCESS) + CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)"); + } + else +# endif // HAVE_VA_INTEL && HAVE_OPENCL + { + Mat m = dst.getMat(); + + // TODO Add support for roi + CV_Assert(m.data == m.datastart); + CV_Assert(m.isContinuous()); + + VAStatus status = 0; + + status = vaSyncSurface(display, surface); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaSyncSurface failed"); + + VAImage image; + status = vaDeriveImage(display, surface, &image); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaDeriveImage failed"); + + unsigned char* buffer = 0; + status = vaMapBuffer(display, image.buf, (void **)&buffer); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaMapBuffer failed"); + + CV_Assert(image.format.fourcc == VA_FOURCC_NV12); + + copy_convert_nv12_to_bgr(image, buffer, m); + + status = vaUnmapBuffer(display, image.buf); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaUnmapBuffer failed"); + + status = vaDestroyImage(display, image.image_id); + if (status != VA_STATUS_SUCCESS) + CV_Error(cv::Error::StsError, "VA-API: vaDestroyImage failed"); + } +#endif // !HAVE_VA +} + +}} // namespace cv::va_intel diff --git a/modules/core/src/vaapi.cpp b/modules/core/src/vaapi.cpp deleted file mode 100644 index 39390bbac..000000000 --- a/modules/core/src/vaapi.cpp +++ /dev/null @@ -1,302 +0,0 @@ -// This file is part of OpenCV project. -// It is subject to the license terms in the LICENSE file found in the top-level directory -// of this distribution and at http://opencv.org/license.html. - -// Copyright (C) 2015, Itseez, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. - -#include "precomp.hpp" - -#ifdef HAVE_VAAPI -#else // HAVE_VAAPI -# define NO_VAAPI_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without VA-API support") -#endif // HAVE_VAAPI - -using namespace cv; - -//////////////////////////////////////////////////////////////////////// -// CL-VA Interoperability - -#ifdef HAVE_OPENCL -# include "opencv2/core/opencl/runtime/opencl_core.hpp" -# include "opencv2/core.hpp" -# include "opencv2/core/ocl.hpp" -# include "opencl_kernels_core.hpp" -#else // HAVE_OPENCL -# define NO_OPENCL_SUPPORT_ERROR CV_ErrorNoReturn(cv::Error::StsBadFunc, "OpenCV was build without OpenCL support") -#endif // HAVE_OPENCL - -#if defined(HAVE_VAAPI) && defined(HAVE_OPENCL) -# include -#endif // HAVE_VAAPI && HAVE_OPENCL - -namespace cv { namespace vaapi { - -#if defined(HAVE_VAAPI) && defined(HAVE_OPENCL) - -static clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn clGetDeviceIDsFromVA_APIMediaAdapterINTEL = NULL; -static clCreateFromVA_APIMediaSurfaceINTEL_fn clCreateFromVA_APIMediaSurfaceINTEL = NULL; -static clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn clEnqueueAcquireVA_APIMediaSurfacesINTEL = NULL; -static clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn clEnqueueReleaseVA_APIMediaSurfacesINTEL = NULL; - -static bool contextInitialized = false; - -#endif // HAVE_VAAPI && HAVE_OPENCL - -namespace ocl { - -Context& initializeContextFromVA(VADisplay display) -{ - (void)display; -#if !defined(HAVE_VAAPI) - NO_VAAPI_SUPPORT_ERROR; -#elif !defined(HAVE_OPENCL) - NO_OPENCL_SUPPORT_ERROR; -#else - contextInitialized = false; - - cl_uint numPlatforms; - cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms"); - if (numPlatforms == 0) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms"); - - std::vector platforms(numPlatforms); - status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get platform Id list"); - - // For CL-VA interop, we must find platform/device with "cl_intel_va_api_media_sharing" extension. - // With standard initialization procedure, we should examine platform extension string for that. - // But in practice, the platform ext string doesn't contain it, while device ext string does. - // Follow Intel procedure (see tutorial), we should obtain device IDs by extension call. - // Note that we must obtain function pointers using specific platform ID, and can't provide pointers in advance. - // So, we iterate and select the first platform, for which we got non-NULL pointers, device, and CL context. - - int found = -1; - cl_context context = 0; - cl_device_id device = 0; - - for (int i = 0; i < (int)numPlatforms; ++i) - { - // Get extension function pointers - - clGetDeviceIDsFromVA_APIMediaAdapterINTEL = (clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn) - clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromVA_APIMediaAdapterINTEL"); - clCreateFromVA_APIMediaSurfaceINTEL = (clCreateFromVA_APIMediaSurfaceINTEL_fn) - clGetExtensionFunctionAddressForPlatform(platforms[i], "clCreateFromVA_APIMediaSurfaceINTEL"); - clEnqueueAcquireVA_APIMediaSurfacesINTEL = (clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn) - clGetExtensionFunctionAddressForPlatform(platforms[i], "clEnqueueAcquireVA_APIMediaSurfacesINTEL"); - clEnqueueReleaseVA_APIMediaSurfacesINTEL = (clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn) - clGetExtensionFunctionAddressForPlatform(platforms[i], "clEnqueueReleaseVA_APIMediaSurfacesINTEL"); - - if (((void*)clGetDeviceIDsFromVA_APIMediaAdapterINTEL == NULL) || - ((void*)clCreateFromVA_APIMediaSurfaceINTEL == NULL) || - ((void*)clEnqueueAcquireVA_APIMediaSurfacesINTEL == NULL) || - ((void*)clEnqueueReleaseVA_APIMediaSurfacesINTEL == NULL)) - { - continue; - } - - // Query device list - - cl_uint numDevices = 0; - - status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display, - CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, &numDevices); - if ((status != CL_SUCCESS) || !(numDevices > 0)) - continue; - numDevices = 1; // initializeContextFromHandle() expects only 1 device - status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display, - CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, numDevices, &device, NULL); - if (status != CL_SUCCESS) - continue; - - // Creating CL-VA media sharing OpenCL context - - cl_context_properties props[] = { - CL_CONTEXT_VA_API_DISPLAY_INTEL, (cl_context_properties) display, - CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE, // no explicit sync required - 0 - }; - - context = clCreateContext(props, numDevices, &device, NULL, NULL, &status); - if (status != CL_SUCCESS) - { - clReleaseDevice(device); - } - else - { - found = i; - break; - } - } - - if (found < 0) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for VA-API interop"); - - Context& ctx = Context::getDefault(false); - initializeContextFromHandle(ctx, platforms[found], context, device); - contextInitialized = true; - return ctx; -#endif -} - -#if defined(HAVE_VAAPI) && defined(HAVE_OPENCL) -static bool ocl_convert_nv12_to_bgr(cl_mem clImageY, cl_mem clImageUV, cl_mem clBuffer, int step, int cols, int rows) -{ - ocl::Kernel k; - k.create("YUV2BGR_NV12_8u", cv::ocl::core::cvtclr_dx_oclsrc, ""); - if (k.empty()) - return false; - - k.args(clImageY, clImageUV, clBuffer, step, cols, rows); - - size_t globalsize[] = { cols, rows }; - return k.run(2, globalsize, 0, false); -} - -static bool ocl_convert_bgr_to_nv12(cl_mem clBuffer, int step, int cols, int rows, cl_mem clImageY, cl_mem clImageUV) -{ - ocl::Kernel k; - k.create("BGR2YUV_NV12_8u", cv::ocl::core::cvtclr_dx_oclsrc, ""); - if (k.empty()) - return false; - - k.args(clBuffer, step, cols, rows, clImageY, clImageUV); - - size_t globalsize[] = { cols, rows }; - return k.run(2, globalsize, 0, false); -} -#endif // HAVE_VAAPI && HAVE_OPENCL - -} // namespace cv::vaapi::ocl - -void convertToVASurface(InputArray src, VASurfaceID surface, Size size) -{ - (void)src; (void)surface; (void)size; -#if !defined(HAVE_VAAPI) - NO_VAAPI_SUPPORT_ERROR; -#elif !defined(HAVE_OPENCL) - NO_OPENCL_SUPPORT_ERROR; -#else - if (!contextInitialized) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: Context for VA-API interop hasn't been created"); - - const int stype = CV_8UC4; - - int srcType = src.type(); - CV_Assert(srcType == stype); - - Size srcSize = src.size(); - CV_Assert(srcSize.width == size.width && srcSize.height == size.height); - - UMat u = src.getUMat(); - - // TODO Add support for roi - CV_Assert(u.offset == 0); - CV_Assert(u.isContinuous()); - - cl_mem clBuffer = (cl_mem)u.handle(ACCESS_READ); - - using namespace cv::ocl; - Context& ctx = Context::getDefault(); - cl_context context = (cl_context)ctx.ptr(); - - cl_int status = 0; - - cl_mem clImageY = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_WRITE_ONLY, &surface, 0, &status); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (Y plane)"); - cl_mem clImageUV = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_WRITE_ONLY, &surface, 1, &status); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (UV plane)"); - - cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); - - cl_mem images[2] = { clImageY, clImageUV }; - status = clEnqueueAcquireVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireVA_APIMediaSurfacesINTEL failed"); - if (!ocl::ocl_convert_bgr_to_nv12(clBuffer, (int)u.step[0], u.cols, u.rows, clImageY, clImageUV)) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_bgr_to_nv12 failed"); - clEnqueueReleaseVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseVA_APIMediaSurfacesINTEL failed"); - - status = clFinish(q); // TODO Use events - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed"); - - status = clReleaseMemObject(clImageY); // TODO RAII - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (Y plane)"); - status = clReleaseMemObject(clImageUV); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)"); -#endif -} - -void convertFromVASurface(VASurfaceID surface, Size size, OutputArray dst) -{ - (void)surface; (void)dst; (void)size; -#if !defined(HAVE_VAAPI) - NO_VAAPI_SUPPORT_ERROR; -#elif !defined(HAVE_OPENCL) - NO_OPENCL_SUPPORT_ERROR; -#else - if (!contextInitialized) - CV_Error(cv::Error::OpenCLInitError, "OpenCL: Context for VA-API interop hasn't been created"); - - const int dtype = CV_8UC4; - - // TODO Need to specify ACCESS_WRITE here somehow to prevent useless data copying! - dst.create(size, dtype); - UMat u = dst.getUMat(); - - // TODO Add support for roi - CV_Assert(u.offset == 0); - CV_Assert(u.isContinuous()); - - cl_mem clBuffer = (cl_mem)u.handle(ACCESS_WRITE); - - using namespace cv::ocl; - Context& ctx = Context::getDefault(); - cl_context context = (cl_context)ctx.ptr(); - - cl_int status = 0; - - cl_mem clImageY = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_READ_ONLY, &surface, 0, &status); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (Y plane)"); - cl_mem clImageUV = clCreateFromVA_APIMediaSurfaceINTEL(context, CL_MEM_READ_ONLY, &surface, 1, &status); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clCreateFromVA_APIMediaSurfaceINTEL failed (UV plane)"); - - cl_command_queue q = (cl_command_queue)Queue::getDefault().ptr(); - - cl_mem images[2] = { clImageY, clImageUV }; - status = clEnqueueAcquireVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueAcquireVA_APIMediaSurfacesINTEL failed"); - if (!ocl::ocl_convert_nv12_to_bgr(clImageY, clImageUV, clBuffer, (int)u.step[0], u.cols, u.rows)) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: ocl_convert_nv12_to_bgr failed"); - status = clEnqueueReleaseVA_APIMediaSurfacesINTEL(q, 2, images, 0, NULL, NULL); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clEnqueueReleaseVA_APIMediaSurfacesINTEL failed"); - - status = clFinish(q); // TODO Use events - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clFinish failed"); - - status = clReleaseMemObject(clImageY); // TODO RAII - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (Y plane)"); - status = clReleaseMemObject(clImageUV); - if (status != CL_SUCCESS) - CV_Error(cv::Error::OpenCLApiCallError, "OpenCL: clReleaseMem failed (UV plane)"); -#endif -} - -}} // namespace cv::vaapi diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 8bd45ee39..0471ffc0b 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -1792,7 +1792,6 @@ INSTANTIATE_TEST_CASE_P(Arithm, SubtractOutputMatNotEmpty, testing::Combine( testing::Values(-1, CV_16S, CV_32S, CV_32F), testing::Bool())); - TEST(Core_FindNonZero, singular) { Mat img(10, 10, CV_8U, Scalar::all(0)); @@ -1816,3 +1815,21 @@ TEST(Core_BoolVector, support) ASSERT_EQ( nz, countNonZero(test) ); ASSERT_FLOAT_EQ((float)nz/n, (float)(mean(test)[0])); } + +TEST(MinMaxLoc, Mat_IntMax_Without_Mask) +{ + Mat_ mat(50, 50); + int iMaxVal = numeric_limits::max(); + mat.setTo(iMaxVal); + + double min, max; + Point minLoc, maxLoc; + + minMaxLoc(mat, &min, &max, &minLoc, &maxLoc, Mat()); + + ASSERT_EQ(iMaxVal, min); + ASSERT_EQ(iMaxVal, max); + + ASSERT_EQ(Point(0, 0), minLoc); + ASSERT_EQ(Point(0, 0), maxLoc); +} diff --git a/modules/core/test/test_ds.cpp b/modules/core/test/test_ds.cpp index 25a5f11b1..def3fe20e 100644 --- a/modules/core/test/test_ds.cpp +++ b/modules/core/test/test_ds.cpp @@ -491,6 +491,7 @@ class Core_SeqBaseTest : public Core_DynStructBaseTest { public: Core_SeqBaseTest(); + virtual ~Core_SeqBaseTest(); void clear(); void run( int ); @@ -501,11 +502,14 @@ protected: int test_seq_ops( int iters ); }; - Core_SeqBaseTest::Core_SeqBaseTest() { } +Core_SeqBaseTest::~Core_SeqBaseTest() +{ + clear(); +} void Core_SeqBaseTest::clear() { @@ -1206,6 +1210,7 @@ class Core_SetTest : public Core_DynStructBaseTest { public: Core_SetTest(); + virtual ~Core_SetTest(); void clear(); void run( int ); @@ -1219,6 +1224,10 @@ Core_SetTest::Core_SetTest() { } +Core_SetTest::~Core_SetTest() +{ + clear(); +} void Core_SetTest::clear() { @@ -1417,6 +1426,7 @@ class Core_GraphTest : public Core_DynStructBaseTest { public: Core_GraphTest(); + virtual ~Core_GraphTest(); void clear(); void run( int ); @@ -1430,6 +1440,10 @@ Core_GraphTest::Core_GraphTest() { } +Core_GraphTest::~Core_GraphTest() +{ + clear(); +} void Core_GraphTest::clear() { @@ -2042,6 +2056,8 @@ void Core_GraphScanTest::run( int ) CV_TS_SEQ_CHECK_CONDITION( vtx_count == 0 && edge_count == 0, "Not every vertex/edge has been visited" ); update_progressbar(); + + cvReleaseGraphScanner( &scanner ); } // for a random graph the test just checks that every graph vertex and @@ -2106,8 +2122,6 @@ void Core_GraphScanTest::run( int ) catch(int) { } - - cvReleaseGraphScanner( &scanner ); } diff --git a/modules/core/test/test_umat.cpp b/modules/core/test/test_umat.cpp index 56a7a1817..6afd432cf 100644 --- a/modules/core/test/test_umat.cpp +++ b/modules/core/test/test_umat.cpp @@ -243,9 +243,11 @@ TEST_P(UMatBasicTests, GetUMat) EXPECT_MAT_NEAR(ub, ua, 0); } { - Mat b; - b = a.getUMat(ACCESS_RW).getMat(ACCESS_RW); - EXPECT_MAT_NEAR(b, a, 0); + UMat u = a.getUMat(ACCESS_RW); + { + Mat b = u.getMat(ACCESS_RW); + EXPECT_MAT_NEAR(b, a, 0); + } } { Mat b; @@ -253,13 +255,15 @@ TEST_P(UMatBasicTests, GetUMat) EXPECT_MAT_NEAR(b, a, 0); } { - UMat ub; - ub = ua.getMat(ACCESS_RW).getUMat(ACCESS_RW); - EXPECT_MAT_NEAR(ub, ua, 0); + Mat m = ua.getMat(ACCESS_RW); + { + UMat ub = m.getUMat(ACCESS_RW); + EXPECT_MAT_NEAR(ub, ua, 0); + } } } -INSTANTIATE_TEST_CASE_P(UMat, UMatBasicTests, Combine(testing::Values(CV_8U), testing::Values(1, 2), +INSTANTIATE_TEST_CASE_P(UMat, UMatBasicTests, Combine(testing::Values(CV_8U, CV_64F), testing::Values(1, 2), testing::Values(cv::Size(1, 1), cv::Size(1, 128), cv::Size(128, 1), cv::Size(128, 128), cv::Size(640, 480)), Bool())); //////////////////////////////////////////////////////////////// Reshape //////////////////////////////////////////////////////////////////////// @@ -1080,7 +1084,7 @@ TEST(UMat, unmap_in_class) Mat dst; m.convertTo(dst, CV_32FC1); // some additional CPU-based per-pixel processing into dst - intermediateResult = dst.getUMat(ACCESS_READ); + intermediateResult = dst.getUMat(ACCESS_READ); // this violates lifetime of base(dst) / derived (intermediateResult) objects. Use copyTo? std::cout << "data processed..." << std::endl; } // problem is here: dst::~Mat() std::cout << "leave ProcessData()" << std::endl; @@ -1268,5 +1272,69 @@ TEST(UMat, DISABLED_Test_same_behaviour_write_and_write) ASSERT_TRUE(exceptionDetected); // data race } +TEST(UMat, mat_umat_sync) +{ + UMat u(10, 10, CV_8UC1, Scalar(1)); + { + Mat m = u.getMat(ACCESS_RW).reshape(1); + m.setTo(Scalar(255)); + } + + UMat uDiff; + compare(u, 255, uDiff, CMP_NE); + ASSERT_EQ(0, countNonZero(uDiff)); +} + +TEST(UMat, testTempObjects_UMat) +{ + UMat u(10, 10, CV_8UC1, Scalar(1)); + { + UMat u2 = u.getMat(ACCESS_RW).getUMat(ACCESS_RW); + u2.setTo(Scalar(255)); + } + + UMat uDiff; + compare(u, 255, uDiff, CMP_NE); + ASSERT_EQ(0, countNonZero(uDiff)); +} + +// Disabled due to failure in VS 2015: +// C++11 is enabled by default ==> +// destructors have implicit 'noexcept(true)' specifier ==> +// throwing exception from destructor is not handled correctly +#if defined(_MSC_VER) && _MSC_VER >= 1900 /* MSVC 14 */ +TEST(UMat, DISABLED_testTempObjects_Mat) +#else +TEST(UMat, testTempObjects_Mat) +#endif +{ + Mat m(10, 10, CV_8UC1, Scalar(1)); + { + Mat m2; + ASSERT_ANY_THROW(m2 = m.getUMat(ACCESS_RW).getMat(ACCESS_RW)); + } +} + +TEST(UMat, testWrongLifetime_UMat) +{ + UMat u(10, 10, CV_8UC1, Scalar(1)); + { + UMat u2 = u.getMat(ACCESS_RW).getUMat(ACCESS_RW); + u.release(); // base object + u2.release(); // derived object, should show warning message + } +} + +TEST(UMat, testWrongLifetime_Mat) +{ + Mat m(10, 10, CV_8UC1, Scalar(1)); + { + UMat u = m.getUMat(ACCESS_RW); + Mat m2 = u.getMat(ACCESS_RW); + m.release(); // base object + m2.release(); // map of derived object + u.release(); // derived object, should show warning message + } +} } } // namespace cvtest::ocl diff --git a/modules/core/test/test_utils.cpp b/modules/core/test/test_utils.cpp new file mode 100644 index 000000000..18b0a5a7e --- /dev/null +++ b/modules/core/test/test_utils.cpp @@ -0,0 +1,221 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#include "test_precomp.hpp" + +using namespace cv; + +namespace { + +static const char * const keys = + "{ h help | | print help }" + "{ i info | false | print info }" + "{ t true | true | true value }" + "{ n unused | | dummy }" +; + +TEST(CommandLineParser, testFailure) +{ + const char* argv[] = {"", "-q"}; + const int argc = 2; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_ANY_THROW(parser.has("q")); + EXPECT_ANY_THROW(parser.get("q")); + EXPECT_ANY_THROW(parser.get(0)); + + parser.get("h"); + EXPECT_FALSE(parser.check()); +} +TEST(CommandLineParser, testHas_noValues) +{ + const char* argv[] = {"", "-h", "--info"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_TRUE(parser.has("help")); + EXPECT_TRUE(parser.has("h")); + EXPECT_TRUE(parser.has("info")); + EXPECT_TRUE(parser.has("i")); + EXPECT_FALSE(parser.has("n")); + EXPECT_FALSE(parser.has("unused")); +} +TEST(CommandLineParser, testHas_TrueValues) +{ + const char* argv[] = {"", "-h=TRUE", "--info=true"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_TRUE(parser.has("help")); + EXPECT_TRUE(parser.has("h")); + EXPECT_TRUE(parser.has("info")); + EXPECT_TRUE(parser.has("i")); + EXPECT_FALSE(parser.has("n")); + EXPECT_FALSE(parser.has("unused")); +} +TEST(CommandLineParser, testHas_TrueValues1) +{ + const char* argv[] = {"", "-h=1", "--info=1"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_TRUE(parser.has("help")); + EXPECT_TRUE(parser.has("h")); + EXPECT_TRUE(parser.has("info")); + EXPECT_TRUE(parser.has("i")); + EXPECT_FALSE(parser.has("n")); + EXPECT_FALSE(parser.has("unused")); +} +TEST(CommandLineParser, testHas_FalseValues0) +{ + const char* argv[] = {"", "-h=0", "--info=0"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_TRUE(parser.has("help")); + EXPECT_TRUE(parser.has("h")); + EXPECT_TRUE(parser.has("info")); + EXPECT_TRUE(parser.has("i")); + EXPECT_FALSE(parser.has("n")); + EXPECT_FALSE(parser.has("unused")); +} + +TEST(CommandLineParser, testBoolOption_noArgs) +{ + const char* argv[] = {""}; + const int argc = 1; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_FALSE(parser.get("help")); + EXPECT_FALSE(parser.get("h")); + EXPECT_FALSE(parser.get("info")); + EXPECT_FALSE(parser.get("i")); + EXPECT_TRUE(parser.get("true")); // default is true + EXPECT_TRUE(parser.get("t")); +} + +TEST(CommandLineParser, testBoolOption_noValues) +{ + const char* argv[] = {"", "-h", "--info"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_TRUE(parser.get("help")); + EXPECT_TRUE(parser.get("h")); + EXPECT_TRUE(parser.get("info")); + EXPECT_TRUE(parser.get("i")); +} + +TEST(CommandLineParser, testBoolOption_TrueValues) +{ + const char* argv[] = {"", "-h=TRUE", "--info=true"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + //EXPECT_TRUE(parser.get("help")); + //EXPECT_TRUE(parser.get("h")); + EXPECT_TRUE(parser.get("info")); + EXPECT_TRUE(parser.get("i")); + EXPECT_FALSE(parser.get("unused")); + EXPECT_FALSE(parser.get("n")); +} + +TEST(CommandLineParser, testBoolOption_FalseValues) +{ + const char* argv[] = {"", "--help=FALSE", "-i=false"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys); + EXPECT_FALSE(parser.get("help")); + EXPECT_FALSE(parser.get("h")); + EXPECT_FALSE(parser.get("info")); + EXPECT_FALSE(parser.get("i")); +} + + +static const char * const keys2 = + "{ h help | | print help }" + "{ @arg1 | default1 | param1 }" + "{ @arg2 | | param2 }" + "{ n unused | | dummy }" +; + +TEST(CommandLineParser, testPositional_noArgs) +{ + const char* argv[] = {""}; + const int argc = 1; + cv::CommandLineParser parser(argc, argv, keys2); + EXPECT_TRUE(parser.has("@arg1")); + EXPECT_FALSE(parser.has("@arg2")); + EXPECT_EQ("default1", parser.get("@arg1")); + EXPECT_EQ("default1", parser.get(0)); + + EXPECT_EQ("", parser.get("@arg2")); + EXPECT_EQ("", parser.get(1)); +} + +TEST(CommandLineParser, testPositional_default) +{ + const char* argv[] = {"", "test1", "test2"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys2); + EXPECT_TRUE(parser.has("@arg1")); + EXPECT_TRUE(parser.has("@arg2")); + EXPECT_EQ("test1", parser.get("@arg1")); + EXPECT_EQ("test2", parser.get("@arg2")); + EXPECT_EQ("test1", parser.get(0)); + EXPECT_EQ("test2", parser.get(1)); +} + +TEST(CommandLineParser, testPositional_withFlagsBefore) +{ + const char* argv[] = {"", "-h", "test1", "test2"}; + const int argc = 4; + cv::CommandLineParser parser(argc, argv, keys2); + EXPECT_TRUE(parser.has("@arg1")); + EXPECT_TRUE(parser.has("@arg2")); + EXPECT_EQ("test1", parser.get("@arg1")); + EXPECT_EQ("test2", parser.get("@arg2")); + EXPECT_EQ("test1", parser.get(0)); + EXPECT_EQ("test2", parser.get(1)); +} + +TEST(CommandLineParser, testPositional_withFlagsAfter) +{ + const char* argv[] = {"", "test1", "test2", "-h"}; + const int argc = 4; + cv::CommandLineParser parser(argc, argv, keys2); + EXPECT_TRUE(parser.has("@arg1")); + EXPECT_TRUE(parser.has("@arg2")); + EXPECT_EQ("test1", parser.get("@arg1")); + EXPECT_EQ("test2", parser.get("@arg2")); + EXPECT_EQ("test1", parser.get(0)); + EXPECT_EQ("test2", parser.get(1)); +} + +TEST(CommandLineParser, testEmptyStringValue) +{ + static const char * const keys3 = + "{ @pos0 | | empty default value }" + "{ @pos1 | | forbid empty default value }"; + + const char* argv[] = {""}; + const int argc = 1; + cv::CommandLineParser parser(argc, argv, keys3); + // EXPECT_TRUE(parser.has("@pos0")); + EXPECT_EQ("", parser.get("@pos0")); + EXPECT_TRUE(parser.check()); + + EXPECT_FALSE(parser.has("@pos1")); + parser.get(1); + EXPECT_FALSE(parser.check()); +} + +TEST(CommandLineParser, positional_regression_5074_equal_sign) +{ + static const char * const keys3 = + "{ @eq0 | | }" + "{ eq1 | | }"; + + const char* argv[] = {"", "1=0", "--eq1=1=0"}; + const int argc = 3; + cv::CommandLineParser parser(argc, argv, keys3); + EXPECT_EQ("1=0", parser.get("@eq0")); + EXPECT_EQ("1=0", parser.get(0)); + EXPECT_EQ("1=0", parser.get("eq1")); + EXPECT_TRUE(parser.check()); +} + +} // namespace diff --git a/modules/cudaarithm/src/cuda/normalize.cu b/modules/cudaarithm/src/cuda/normalize.cu index efbc94ecc..c83f2c0df 100644 --- a/modules/cudaarithm/src/cuda/normalize.cu +++ b/modules/cudaarithm/src/cuda/normalize.cu @@ -249,6 +249,10 @@ void cv::cuda::normalize(InputArray _src, OutputArray _dst, double a, double b, CV_Assert( src.channels() == 1 ); CV_Assert( mask.empty() || (mask.size() == src.size() && mask.type() == CV_8U) ); + if (dtype < 0) + { + dtype = _dst.fixedType() ? _dst.type() : src.type(); + } dtype = CV_MAT_DEPTH(dtype); const int src_depth = src.depth(); diff --git a/modules/cudaarithm/test/test_reductions.cpp b/modules/cudaarithm/test/test_reductions.cpp index 9a8854939..a0ff0dfa4 100644 --- a/modules/cudaarithm/test/test_reductions.cpp +++ b/modules/cudaarithm/test/test_reductions.cpp @@ -951,11 +951,11 @@ CUDA_TEST_P(Normalize, WithMask) cv::cuda::GpuMat dst = createMat(size, type, useRoi); dst.setTo(cv::Scalar::all(0)); - cv::cuda::normalize(loadMat(src, useRoi), dst, alpha, beta, norm_type, type, loadMat(mask, useRoi)); + cv::cuda::normalize(loadMat(src, useRoi), dst, alpha, beta, norm_type, -1, loadMat(mask, useRoi)); cv::Mat dst_gold(size, type); dst_gold.setTo(cv::Scalar::all(0)); - cv::normalize(src, dst_gold, alpha, beta, norm_type, type, mask); + cv::normalize(src, dst_gold, alpha, beta, norm_type, -1, mask); EXPECT_MAT_NEAR(dst_gold, dst, type < CV_32F ? 1.0 : 1e-4); } diff --git a/modules/cudaimgproc/src/cuda/bilateral_filter.cu b/modules/cudaimgproc/src/cuda/bilateral_filter.cu index 20d2bd9d7..f81adc7a9 100644 --- a/modules/cudaimgproc/src/cuda/bilateral_filter.cu +++ b/modules/cudaimgproc/src/cuda/bilateral_filter.cu @@ -136,7 +136,7 @@ namespace cv { namespace cuda { namespace device float sigma_color2_inv_half = -0.5f/(sigma_color * sigma_color); cudaSafeCall( cudaFuncSetCacheConfig (bilateral_kernel >, cudaFuncCachePreferL1) ); - bilateral_kernel<<>>((PtrStepSz)src, (PtrStepSz)dst, b, kernel_size, sigma_spatial2_inv_half, sigma_color2_inv_half); + bilateral_kernel<<>>((PtrStepSz)src, (PtrStepSz)dst, b, kernel_size, sigma_spatial2_inv_half, sigma_color2_inv_half); cudaSafeCall ( cudaGetLastError () ); if (stream == 0) diff --git a/modules/cudev/test/CMakeLists.txt b/modules/cudev/test/CMakeLists.txt index b3474168e..a7bd6328b 100644 --- a/modules/cudev/test/CMakeLists.txt +++ b/modules/cudev/test/CMakeLists.txt @@ -32,6 +32,10 @@ if(OCV_DEPENDENCIES_FOUND) ocv_target_link_libraries(${the_target} ${test_deps} ${OPENCV_LINKER_LIBS} ${CUDA_LIBRARIES}) add_dependencies(opencv_tests ${the_target}) + set_target_properties(${the_target} PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL}") + set_source_files_properties(${OPENCV_TEST_${the_module}_SOURCES} ${${the_target}_pch} + PROPERTIES LABELS "${OPENCV_MODULE_${the_module}_LABEL};AccuracyTest") + # Additional target properties set_target_properties(${the_target} PROPERTIES DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" @@ -42,9 +46,7 @@ if(OCV_DEPENDENCIES_FOUND) set_target_properties(${the_target} PROPERTIES FOLDER "tests accuracy") endif() - enable_testing() - get_target_property(LOC ${the_target} LOCATION) - add_test(${the_target} "${LOC}") + ocv_add_test_from_target("${the_target}" "Accuracy" "${the_target}") if(INSTALL_TESTS) install(TARGETS ${the_target} RUNTIME DESTINATION ${OPENCV_TEST_INSTALL_PATH} COMPONENT tests) diff --git a/modules/features2d/src/agast.cpp b/modules/features2d/src/agast.cpp index cd58ac278..95c74fbee 100644 --- a/modules/features2d/src/agast.cpp +++ b/modules/features2d/src/agast.cpp @@ -7511,19 +7511,22 @@ Ptr AgastFeatureDetector::create( int threshold, bool nonm void AGAST(InputArray _img, std::vector& keypoints, int threshold, bool nonmax_suppression, int type) { + + std::vector kpts; + // detect switch(type) { case AgastFeatureDetector::AGAST_5_8: - AGAST_5_8(_img, keypoints, threshold); + AGAST_5_8(_img, kpts, threshold); break; case AgastFeatureDetector::AGAST_7_12d: - AGAST_7_12d(_img, keypoints, threshold); + AGAST_7_12d(_img, kpts, threshold); break; case AgastFeatureDetector::AGAST_7_12s: - AGAST_7_12s(_img, keypoints, threshold); + AGAST_7_12s(_img, kpts, threshold); break; case AgastFeatureDetector::OAST_9_16: - OAST_9_16(_img, keypoints, threshold); + OAST_9_16(_img, kpts, threshold); break; } @@ -7534,7 +7537,7 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo makeAgastOffsets(pixel_, (int)img.step, type); std::vector::iterator kpt; - for(kpt = keypoints.begin(); kpt != keypoints.end(); kpt++) + for(kpt = kpts.begin(); kpt != kpts.end(); kpt++) { switch(type) { case AgastFeatureDetector::AGAST_5_8: @@ -7555,20 +7558,21 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo break; } } + // suppression if(nonmax_suppression) { size_t j; size_t curr_idx; size_t lastRow = 0, next_lastRow = 0; - size_t num_Corners = keypoints.size(); + size_t num_Corners = kpts.size(); size_t lastRowCorner_ind = 0, next_lastRowCorner_ind = 0; std::vector nmsFlags; std::vector::iterator currCorner_nms; std::vector::const_iterator currCorner; - currCorner = keypoints.begin(); + currCorner = kpts.begin(); nmsFlags.resize((int)num_Corners); @@ -7593,11 +7597,11 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo if(lastRow + 1 == currCorner->pt.y) { // find the corner above the current one - while( (keypoints[lastRowCorner_ind].pt.x < currCorner->pt.x) - && (keypoints[lastRowCorner_ind].pt.y == lastRow) ) + while( (kpts[lastRowCorner_ind].pt.x < currCorner->pt.x) + && (kpts[lastRowCorner_ind].pt.y == lastRow) ) lastRowCorner_ind++; - if( (keypoints[lastRowCorner_ind].pt.x == currCorner->pt.x) + if( (kpts[lastRowCorner_ind].pt.x == currCorner->pt.x) && (lastRowCorner_ind != curr_idx) ) { size_t w = lastRowCorner_ind; @@ -7605,7 +7609,7 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo while(nmsFlags[w] != -1) w = nmsFlags[w]; - if(keypoints[curr_idx].response < keypoints[w].response) + if(kpts[curr_idx].response < kpts[w].response) nmsFlags[curr_idx] = (int)w; else nmsFlags[w] = (int)curr_idx; @@ -7614,8 +7618,8 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo // check left t = (int)curr_idx - 1; - if( (curr_idx != 0) && (keypoints[t].pt.y == currCorner->pt.y) - && (keypoints[t].pt.x + 1 == currCorner->pt.x) ) + if( (curr_idx != 0) && (kpts[t].pt.y == currCorner->pt.y) + && (kpts[t].pt.x + 1 == currCorner->pt.x) ) { int currCornerMaxAbove_ind = nmsFlags[curr_idx]; // find the maximum in that area @@ -7626,7 +7630,7 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo { if((size_t)t != curr_idx) { - if ( keypoints[curr_idx].response < keypoints[t].response ) + if ( kpts[curr_idx].response < kpts[t].response ) nmsFlags[curr_idx] = t; else nmsFlags[t] = (int)curr_idx; @@ -7636,7 +7640,7 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo { if(t != currCornerMaxAbove_ind) { - if(keypoints[currCornerMaxAbove_ind].response < keypoints[t].response) + if(kpts[currCornerMaxAbove_ind].response < kpts[t].response) { nmsFlags[currCornerMaxAbove_ind] = t; nmsFlags[curr_idx] = t; @@ -7652,19 +7656,15 @@ void AGAST(InputArray _img, std::vector& keypoints, int threshold, boo currCorner++; } - // marks non-maximum corners + // collecting maximum corners for(curr_idx = 0; curr_idx < num_Corners; curr_idx++) { - if (nmsFlags[curr_idx] != -1) - keypoints[curr_idx].response = -1; - } - - // erase non-maximum corners - for (j = keypoints.size(); j > 0; j--) - { - if (keypoints[j - 1].response == -1) - keypoints.erase(keypoints.begin() + j - 1 ); + if (nmsFlags[curr_idx] == -1) + keypoints.push_back(kpts[curr_idx]); } + } else + { + keypoints = kpts; } } diff --git a/modules/features2d/src/fast.cpp b/modules/features2d/src/fast.cpp index 11c039a0c..c70a29ae1 100644 --- a/modules/features2d/src/fast.cpp +++ b/modules/features2d/src/fast.cpp @@ -262,7 +262,7 @@ static bool ocl_FAST( InputArray _img, std::vector& keypoints, UMat img = _img.getUMat(); if( img.cols < 7 || img.rows < 7 ) return false; - size_t globalsize[] = { img.cols-6, img.rows-6 }; + size_t globalsize[] = { (size_t)img.cols-6, (size_t)img.rows-6 }; ocl::Kernel fastKptKernel("FAST_findKeypoints", ocl::features2d::fast_oclsrc); if (fastKptKernel.empty()) @@ -306,7 +306,7 @@ static bool ocl_FAST( InputArray _img, std::vector& keypoints, if (fastNMSKernel.empty()) return false; - size_t globalsize_nms[] = { counter }; + size_t globalsize_nms[] = { (size_t)counter }; if( !fastNMSKernel.args(ocl::KernelArg::PtrReadOnly(kp1), ocl::KernelArg::PtrReadWrite(kp2), ocl::KernelArg::ReadOnly(img), diff --git a/modules/features2d/src/main.cpp b/modules/features2d/src/main.cpp new file mode 100644 index 000000000..127f86b26 --- /dev/null +++ b/modules/features2d/src/main.cpp @@ -0,0 +1,52 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +// +// Library initialization file +// + +#include "precomp.hpp" + +IPP_INITIALIZER_AUTO + +/* End of file. */ diff --git a/modules/features2d/src/matchers.cpp b/modules/features2d/src/matchers.cpp index 8d2f69ec8..ea0fdaa0b 100644 --- a/modules/features2d/src/matchers.cpp +++ b/modules/features2d/src/matchers.cpp @@ -97,8 +97,8 @@ static bool ocl_matchSingle(InputArray query, InputArray train, if(k.empty()) return false; - size_t globalSize[] = {(query.size().height + block_size - 1) / block_size * block_size, block_size}; - size_t localSize[] = {block_size, block_size}; + size_t globalSize[] = {((size_t)query.size().height + block_size - 1) / block_size * block_size, (size_t)block_size}; + size_t localSize[] = {(size_t)block_size, (size_t)block_size}; int idx = 0; idx = k.set(idx, ocl::KernelArg::PtrReadOnly(uquery)); @@ -197,8 +197,8 @@ static bool ocl_knnMatchSingle(InputArray query, InputArray train, UMat &trainId if(k.empty()) return false; - size_t globalSize[] = {(query_rows + block_size - 1) / block_size * block_size, block_size}; - size_t localSize[] = {block_size, block_size}; + size_t globalSize[] = {((size_t)query_rows + block_size - 1) / block_size * block_size, (size_t)block_size}; + size_t localSize[] = {(size_t)block_size, (size_t)block_size}; int idx = 0; idx = k.set(idx, ocl::KernelArg::PtrReadOnly(uquery)); @@ -306,8 +306,8 @@ static bool ocl_radiusMatchSingle(InputArray query, InputArray train, if (k.empty()) return false; - size_t globalSize[] = {(train_rows + block_size - 1) / block_size * block_size, (query_rows + block_size - 1) / block_size * block_size}; - size_t localSize[] = {block_size, block_size}; + size_t globalSize[] = {((size_t)train_rows + block_size - 1) / block_size * block_size, ((size_t)query_rows + block_size - 1) / block_size * block_size}; + size_t localSize[] = {(size_t)block_size, (size_t)block_size}; int idx = 0; idx = k.set(idx, ocl::KernelArg::PtrReadOnly(uquery)); diff --git a/modules/features2d/src/orb.cpp b/modules/features2d/src/orb.cpp index a1a245339..c9827e2c0 100644 --- a/modules/features2d/src/orb.cpp +++ b/modules/features2d/src/orb.cpp @@ -64,7 +64,7 @@ ocl_HarrisResponses(const UMat& imgbuf, UMat& responses, int nkeypoints, int blockSize, float harris_k) { - size_t globalSize[] = {nkeypoints}; + size_t globalSize[] = {(size_t)nkeypoints}; float scale = 1.f/((1 << 2) * blockSize * 255.f); float scale_sq_sq = scale * scale * scale * scale; @@ -86,7 +86,7 @@ ocl_ICAngles(const UMat& imgbuf, const UMat& layerinfo, const UMat& keypoints, UMat& responses, const UMat& umax, int nkeypoints, int half_k) { - size_t globalSize[] = {nkeypoints}; + size_t globalSize[] = {(size_t)nkeypoints}; ocl::Kernel icangle_ker("ORB_ICAngle", ocl::features2d::orb_oclsrc, "-D ORB_ANGLES"); if( icangle_ker.empty() ) @@ -106,7 +106,7 @@ ocl_computeOrbDescriptors(const UMat& imgbuf, const UMat& layerInfo, const UMat& keypoints, UMat& desc, const UMat& pattern, int nkeypoints, int dsize, int wta_k) { - size_t globalSize[] = {nkeypoints}; + size_t globalSize[] = {(size_t)nkeypoints}; ocl::Kernel desc_ker("ORB_computeDescriptor", ocl::features2d::orb_oclsrc, format("-D ORB_DESCRIPTORS -D WTA_K=%d", wta_k)); diff --git a/modules/features2d/test/test_descriptors_regression.cpp b/modules/features2d/test/test_descriptors_regression.cpp index 5ebf508d8..717cae58d 100644 --- a/modules/features2d/test/test_descriptors_regression.cpp +++ b/modules/features2d/test/test_descriptors_regression.cpp @@ -60,7 +60,7 @@ static void writeMatInBin( const Mat& mat, const string& filename ) fwrite( (void*)&mat.rows, sizeof(int), 1, f ); fwrite( (void*)&mat.cols, sizeof(int), 1, f ); fwrite( (void*)&type, sizeof(int), 1, f ); - int dataSize = (int)(mat.step * mat.rows * mat.channels()); + int dataSize = (int)(mat.step * mat.rows); fwrite( (void*)&dataSize, sizeof(int), 1, f ); fwrite( (void*)mat.ptr(), 1, dataSize, f ); fclose(f); @@ -82,13 +82,14 @@ static Mat readMatFromBin( const string& filename ) int step = dataSize / rows / CV_ELEM_SIZE(type); CV_Assert(step >= cols); - Mat m = Mat(rows, step, type).colRange(0, cols); + Mat returnMat = Mat(rows, step, type).colRange(0, cols); - size_t elements_read = fread( m.ptr(), 1, dataSize, f ); + size_t elements_read = fread( returnMat.ptr(), 1, dataSize, f ); CV_Assert(elements_read == (size_t)(dataSize)); + fclose(f); - return m; + return returnMat; } return Mat(); } diff --git a/modules/features2d/test/test_nearestneighbors.cpp b/modules/features2d/test/test_nearestneighbors.cpp index df5602520..84079fdc7 100644 --- a/modules/features2d/test/test_nearestneighbors.cpp +++ b/modules/features2d/test/test_nearestneighbors.cpp @@ -67,13 +67,13 @@ protected: virtual void run( int start_from ); virtual void createModel( const Mat& data ) = 0; virtual int findNeighbors( Mat& points, Mat& neighbors ) = 0; - virtual int checkGetPoins( const Mat& data ); + virtual int checkGetPoints( const Mat& data ); virtual int checkFindBoxed(); virtual int checkFind( const Mat& data ); virtual void releaseModel() = 0; }; -int NearestNeighborTest::checkGetPoins( const Mat& ) +int NearestNeighborTest::checkGetPoints( const Mat& ) { return cvtest::TS::OK; } @@ -127,11 +127,11 @@ int NearestNeighborTest::checkFind( const Mat& data ) void NearestNeighborTest::run( int /*start_from*/ ) { int code = cvtest::TS::OK, tempCode; Mat desc( featuresCount, dims, CV_32FC1 ); - randu( desc, Scalar(minValue), Scalar(maxValue) ); + ts->get_rng().fill( desc, RNG::UNIFORM, minValue, maxValue ); createModel( desc ); - tempCode = checkGetPoins( desc ); + tempCode = checkGetPoints( desc ); if( tempCode != cvtest::TS::OK ) { ts->printf( cvtest::TS::LOG, "bad accuracy of GetPoints \n" ); @@ -161,7 +161,7 @@ void NearestNeighborTest::run( int /*start_from*/ ) { class CV_FlannTest : public NearestNeighborTest { public: - CV_FlannTest() {} + CV_FlannTest() : NearestNeighborTest(), index(NULL) { } protected: void createIndex( const Mat& data, const IndexParams& params ); int knnSearch( Mat& points, Mat& neighbors ); @@ -172,6 +172,9 @@ protected: void CV_FlannTest::createIndex( const Mat& data, const IndexParams& params ) { + // release previously allocated index + releaseModel(); + index = new Index( data, params ); } @@ -238,7 +241,11 @@ int CV_FlannTest::radiusSearch( Mat& points, Mat& neighbors ) void CV_FlannTest::releaseModel() { - delete index; + if (index) + { + delete index; + index = NULL; + } } //--------------------------------------- diff --git a/modules/flann/include/opencv2/flann/autotuned_index.h b/modules/flann/include/opencv2/flann/autotuned_index.h index 0670d19e2..6ffb9297c 100644 --- a/modules/flann/include/opencv2/flann/autotuned_index.h +++ b/modules/flann/include/opencv2/flann/autotuned_index.h @@ -377,6 +377,7 @@ private: // evaluate kdtree for all parameter combinations for (size_t i = 0; i < FLANN_ARRAY_LEN(testTrees); ++i) { CostData cost; + cost.params["algorithm"] = FLANN_INDEX_KDTREE; cost.params["trees"] = testTrees[i]; evaluate_kdtree(cost); diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index b49b8ddde..226fc71f3 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -441,6 +441,8 @@ public: } root_ = pool_.allocate(); + std::memset(root_, 0, sizeof(KMeansNode)); + computeNodeStatistics(root_, indices_, (int)size_); computeClustering(root_, indices_, (int)size_, branching_,0); } @@ -864,11 +866,11 @@ private: variance -= distance_(centers[c], ZeroIterator(), veclen_); node->childs[c] = pool_.allocate(); + std::memset(node->childs[c], 0, sizeof(KMeansNode)); node->childs[c]->radius = radiuses[c]; node->childs[c]->pivot = centers[c]; node->childs[c]->variance = variance; node->childs[c]->mean_radius = mean_radius; - node->childs[c]->indices = NULL; computeClustering(node->childs[c],indices+start, end-start, branching, level+1); start=end; } diff --git a/modules/hal/include/opencv2/hal.hpp b/modules/hal/include/opencv2/hal.hpp index 95d1ac66c..9d448757d 100644 --- a/modules/hal/include/opencv2/hal.hpp +++ b/modules/hal/include/opencv2/hal.hpp @@ -49,10 +49,21 @@ /** @defgroup hal Hardware Acceleration Layer + @{ + @defgroup hal_intrin Universal intrinsics + @{ + @defgroup hal_intrin_impl Private implementation helpers + @} + @defgroup hal_utils Platform-dependent utils + @} */ + namespace cv { namespace hal { +//! @addtogroup hal +//! @{ + namespace Error { enum @@ -93,6 +104,8 @@ void sqrt(const double* src, double* dst, int len); void invSqrt(const float* src, float* dst, int len); void invSqrt(const double* src, double* dst, int len); +//! @} + }} //cv::hal #endif //__OPENCV_HAL_HPP__ diff --git a/modules/hal/include/opencv2/hal/defs.h b/modules/hal/include/opencv2/hal/defs.h index 1c30073a0..f7d5f3556 100644 --- a/modules/hal/include/opencv2/hal/defs.h +++ b/modules/hal/include/opencv2/hal/defs.h @@ -45,6 +45,9 @@ #ifndef __OPENCV_DEF_H__ #define __OPENCV_DEF_H__ +//! @addtogroup hal_utils +//! @{ + #if !defined _CRT_SECURE_NO_DEPRECATE && defined _MSC_VER && _MSC_VER > 1300 # define _CRT_SECURE_NO_DEPRECATE /* to avoid multiple Visual Studio warnings */ #endif @@ -335,9 +338,6 @@ Cv64suf; # include "tegra_round.hpp" #endif -//! @addtogroup core_utils -//! @{ - #if CV_VFP // 1. general scheme #define ARM_ROUND(_value, _asm_string) \ @@ -567,15 +567,19 @@ CV_INLINE int cvIsInf( float value ) return (ieee754.u & 0x7fffffff) == 0x7f800000; } +//! @} + #include namespace cv { +//! @addtogroup hal_utils +//! @{ + /////////////// saturate_cast (used in image & signal processing) /////////////////// -/** - Template function for accurate conversion from one primitive type to another. +/** @brief Template function for accurate conversion from one primitive type to another. The functions saturate_cast resemble the standard C++ cast operations, such as static_cast\() and others. They perform an efficient and accurate conversion from one primitive type to another @@ -618,8 +622,6 @@ template static inline _Tp saturate_cast(int64 v) { return _Tp( /** @overload */ template static inline _Tp saturate_cast(uint64 v) { return _Tp(v); } -//! @cond IGNORED - template<> inline uchar saturate_cast(schar v) { return (uchar)std::max((int)v, 0); } template<> inline uchar saturate_cast(ushort v) { return (uchar)std::min((unsigned)v, (unsigned)UCHAR_MAX); } template<> inline uchar saturate_cast(int v) { return (uchar)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); } @@ -664,12 +666,10 @@ template<> inline int saturate_cast(double v) { return cvRound(v) template<> inline unsigned saturate_cast(float v) { return cvRound(v); } template<> inline unsigned saturate_cast(double v) { return cvRound(v); } -//! @endcond +//! @} } #endif // __cplusplus -//! @} core_utils - #endif //__OPENCV_HAL_H__ diff --git a/modules/hal/include/opencv2/hal/intrin.hpp b/modules/hal/include/opencv2/hal/intrin.hpp index 767c5780d..c8d59c964 100644 --- a/modules/hal/include/opencv2/hal/intrin.hpp +++ b/modules/hal/include/opencv2/hal/intrin.hpp @@ -48,6 +48,7 @@ #include #include #include +#include "opencv2/hal/defs.h" #define OPENCV_HAL_ADD(a, b) ((a) + (b)) #define OPENCV_HAL_AND(a, b) ((a) & (b)) @@ -59,6 +60,10 @@ // access from within opencv code more accessible namespace cv { +//! @addtogroup hal_intrin +//! @{ + +//! @cond IGNORED template struct V_TypeTraits { typedef _Tp int_type; @@ -82,6 +87,7 @@ template<> struct V_TypeTraits typedef int sum_type; typedef ushort w_type; + typedef unsigned q_type; enum { delta = 128, shift = 8 }; @@ -99,6 +105,7 @@ template<> struct V_TypeTraits typedef int sum_type; typedef short w_type; + typedef int q_type; enum { delta = 128, shift = 8 }; @@ -265,8 +272,22 @@ template<> struct V_TypeTraits } }; +template struct V_SIMD128Traits +{ + enum { nlanes = 16 / sizeof(T) }; +}; + +//! @endcond + +//! @} + } +#ifdef CV_DOXYGEN +# undef CV_SSE2 +# undef CV_NEON +#endif + #if CV_SSE2 #include "opencv2/hal/intrin_sse.hpp" @@ -281,12 +302,19 @@ template<> struct V_TypeTraits #endif +//! @addtogroup hal_intrin +//! @{ + #ifndef CV_SIMD128 +//! Set to 1 if current compiler supports vector extensions (NEON or SSE is enabled) #define CV_SIMD128 0 #endif #ifndef CV_SIMD128_64F +//! Set to 1 if current intrinsics implementation supports 64-bit float vectors #define CV_SIMD128_64F 0 #endif +//! @} + #endif diff --git a/modules/hal/include/opencv2/hal/intrin_cpp.hpp b/modules/hal/include/opencv2/hal/intrin_cpp.hpp index 683305cc2..e1b1044a3 100644 --- a/modules/hal/include/opencv2/hal/intrin_cpp.hpp +++ b/modules/hal/include/opencv2/hal/intrin_cpp.hpp @@ -45,25 +45,233 @@ #ifndef __OPENCV_HAL_INTRIN_CPP_HPP__ #define __OPENCV_HAL_INTRIN_CPP_HPP__ +#include +#include + namespace cv { +/** @addtogroup hal_intrin + +"Universal intrinsics" is a types and functions set intended to simplify vectorization of code on +different platforms. Currently there are two supported SIMD extensions: __SSE/SSE2__ on x86 +architectures and __NEON__ on ARM architectures, both allow working with 128 bit registers +containing packed values of different types. In case when there is no SIMD extension available +during compilation, fallback C++ implementation of intrinsics will be chosen and code will work as +expected although it could be slower. + +### Types + +There are several types representing 128-bit register as a vector of packed values, each type is +implemented as a structure based on a one SIMD register. + +- cv::v_uint8x16 and cv::v_int8x16: sixteen 8-bit integer values (unsigned/signed) - char +- cv::v_uint16x8 and cv::v_int16x8: eight 16-bit integer values (unsigned/signed) - short +- cv::v_uint32x4 and cv::v_int32x4: four 32-bit integer values (unsgined/signed) - int +- cv::v_uint64x2 and cv::v_int64x2: two 64-bit integer values (unsigned/signed) - int64 +- cv::v_float32x4: four 32-bit floating point values (signed) - float +- cv::v_float64x2: two 64-bit floating point valies (signed) - double + +@note +cv::v_float64x2 is not implemented in NEON variant, if you want to use this type, don't forget to +check the CV_SIMD128_64F preprocessor definition: +@code +#if CV_SIMD128_64F +//... +#endif +@endcode + +### Load and store operations + +These operations allow to set contents of the register explicitly or by loading it from some memory +block and to save contents of the register to memory block. + +- Constructors: +@ref v_reg::v_reg(const _Tp *ptr) "from memory", +@ref v_reg::v_reg(_Tp s0, _Tp s1) "from two values", ... +- Other create methods: +@ref v_setall_s8, @ref v_setall_u8, ..., +@ref v_setzero_u8, @ref v_setzero_s8, ... +- Memory operations: +@ref v_load, @ref v_load_aligned, @ref v_load_halves, +@ref v_store, @ref v_store_aligned, +@ref v_store_high, @ref v_store_low + +### Value reordering + +These operations allow to reorder or recombine elements in one or multiple vectors. + +- Interleave, deinterleave (3 and 4 channels): @ref v_load_deinterleave, @ref v_store_interleave +- Expand: @ref v_load_expand, @ref v_load_expand_q, @ref v_expand +- Pack: @ref v_pack, @ref v_pack_u, @ref v_rshr_pack, @ref v_rshr_pack_u, +@ref v_pack_store, @ref v_pack_u_store, @ref v_rshr_pack_store, @ref v_rshr_pack_u_store +- Recombine: @ref v_zip, @ref v_recombine, @ref v_combine_low, @ref v_combine_high +- Extract: @ref v_extract + + +### Arithmetic, bitwise and comparison operations + +Element-wise binary and unary operations. + +- Arithmetics: +@ref operator+(const v_reg &a, const v_reg &b) "+", +@ref operator-(const v_reg &a, const v_reg &b) "-", +@ref operator*(const v_reg &a, const v_reg &b) "*", +@ref operator/(const v_reg &a, const v_reg &b) "/", +@ref v_mul_expand + +- Non-saturating arithmetics: @ref v_add_wrap, @ref v_sub_wrap + +- Bitwise shifts: +@ref operator<<(const v_reg &a, int s) "<<", +@ref operator>>(const v_reg &a, int s) ">>", +@ref v_shl, @ref v_shr + +- Bitwise logic: +@ref operator&(const v_reg &a, const v_reg &b) "&", +@ref operator|(const v_reg &a, const v_reg &b) "|", +@ref operator^(const v_reg &a, const v_reg &b) "^", +@ref operator~(const v_reg &a) "~" + +- Comparison: +@ref operator>(const v_reg &a, const v_reg &b) ">", +@ref operator>=(const v_reg &a, const v_reg &b) ">=", +@ref operator<(const v_reg &a, const v_reg &b) "<", +@ref operator<=(const v_reg &a, const v_reg &b) "<=", +@ref operator==(const v_reg &a, const v_reg &b) "==", +@ref operator!=(const v_reg &a, const v_reg &b) "!=" + +- min/max: @ref v_min, @ref v_max + +### Reduce and mask + +Most of these operations return only one value. + +- Reduce: @ref v_reduce_min, @ref v_reduce_max, @ref v_reduce_sum +- Mask: @ref v_signmask, @ref v_check_all, @ref v_check_any, @ref v_select + +### Other math + +- Some frequent operations: @ref v_sqrt, @ref v_invsqrt, @ref v_magnitude, @ref v_sqr_magnitude +- Absolute values: @ref v_abs, @ref v_absdiff + +### Conversions + +Different type conversions and casts: + +- Rounding: @ref v_round, @ref v_floor, @ref v_ceil, @ref v_trunc, +- To float: @ref v_cvt_f32, @ref v_cvt_f64 +- Reinterpret: @ref v_reinterpret_as_u8, @ref v_reinterpret_as_s8, ... + +### Matrix operations + +In these operations vectors represent matrix rows/columns: @ref v_dotprod, @ref v_matmul, @ref v_transpose4x4 + +### Usability + +Most operations are implemented only for some subset of the available types, following matrices +shows the applicability of different operations to the types. + +Regular integers: + +| Operations\\Types | uint 8x16 | int 8x16 | uint 16x8 | int 16x8 | uint 32x4 | int 32x4 | +|-------------------|:-:|:-:|:-:|:-:|:-:|:-:| +|load, store | x | x | x | x | x | x | +|interleave | x | x | x | x | x | x | +|expand | x | x | x | x | x | x | +|expand_q | x | x | | | | | +|add, sub | x | x | x | x | x | x | +|add_wrap, sub_wrap | x | x | x | x | | | +|mul | | | x | x | x | x | +|mul_expand | | | x | x | x | | +|compare | x | x | x | x | x | x | +|shift | | | x | x | x | x | +|dotprod | | | | x | | | +|logical | x | x | x | x | x | x | +|min, max | x | x | x | x | x | x | +|absdiff | x | x | x | x | x | x | +|reduce | | | | | x | x | +|mask | x | x | x | x | x | x | +|pack | x | x | x | x | x | x | +|pack_u | x | | x | | | | +|unpack | x | x | x | x | x | x | +|extract | x | x | x | x | x | x | +|cvt_flt32 | | | | | | x | +|cvt_flt64 | | | | | | x | +|transpose4x4 | | | | | x | x | + +Big integers: + +| Operations\\Types | uint 64x2 | int 64x2 | +|-------------------|:-:|:-:| +|load, store | x | x | +|add, sub | x | x | +|shift | x | x | +|logical | x | x | +|extract | x | x | + +Floating point: + +| Operations\\Types | float 32x4 | float 64x2 | +|-------------------|:-:|:-:| +|load, store | x | x | +|interleave | x | | +|add, sub | x | x | +|mul | x | x | +|div | x | x | +|compare | x | x | +|min, max | x | x | +|absdiff | x | x | +|reduce | x | | +|mask | x | x | +|unpack | x | x | +|cvt_flt32 | | x | +|cvt_flt64 | x | | +|sqrt, abs | x | x | +|float math | x | x | +|transpose4x4 | x | | + + + @{ */ + template struct v_reg { +//! @cond IGNORED typedef _Tp lane_type; typedef v_reg::int_type, n> int_vec; typedef v_reg::abs_type, n> abs_vec; enum { nlanes = n }; +// !@endcond + /** @brief Constructor + + Initializes register with data from memory + @param ptr pointer to memory block with data for register */ explicit v_reg(const _Tp* ptr) { for( int i = 0; i < n; i++ ) s[i] = ptr[i]; } + + /** @brief Constructor + + Initializes register with two 64-bit values */ v_reg(_Tp s0, _Tp s1) { s[0] = s0; s[1] = s1; } + + /** @brief Constructor + + Initializes register with four 32-bit values */ v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3) { s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; } + + /** @brief Constructor + + Initializes register with eight 16-bit values */ v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3, _Tp s4, _Tp s5, _Tp s6, _Tp s7) { s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; s[4] = s4; s[5] = s5; s[6] = s6; s[7] = s7; } + + /** @brief Constructor + + Initializes register with sixteen 8-bit values */ v_reg(_Tp s0, _Tp s1, _Tp s2, _Tp s3, _Tp s4, _Tp s5, _Tp s6, _Tp s7, _Tp s8, _Tp s9, _Tp s10, _Tp s11, @@ -75,15 +283,31 @@ template struct v_reg s[12] = s12; s[13] = s13; s[14] = s14; s[15] = s15; } + /** @brief Default constructor + + Does not initialize anything*/ v_reg() {} + + /** @brief Copy constructor */ v_reg(const v_reg<_Tp, n> & r) { for( int i = 0; i < n; i++ ) s[i] = r.s[i]; } + /** @brief Access first value - _Tp get(const int i) const { return s[i]; } + Returns value of the first lane according to register type, for example: + @code{.cpp} + v_int32x4 r(1, 2, 3, 4); + int v = r.get0(); // returns 1 + v_uint64x2 r(1, 2); + uint64_t v = r.get0(); // returns 1 + @endcode + */ _Tp get0() const { return s[0]; } + +//! @cond IGNORED + _Tp get(const int i) const { return s[i]; } v_reg<_Tp, n> high() const { v_reg<_Tp, n> c; @@ -116,13 +340,37 @@ template struct v_reg { size_t bytes = std::min(sizeof(_Tp2)*n2, sizeof(_Tp)*n); v_reg<_Tp2, n2> c; - memcpy(&c.s[0], &s[0], bytes); + std::memcpy(&c.s[0], &s[0], bytes); return c; } _Tp s[n]; +//! @endcond }; +/** @brief Sixteen 8-bit unsigned integer values */ +typedef v_reg v_uint8x16; +/** @brief Sixteen 8-bit signed integer values */ +typedef v_reg v_int8x16; +/** @brief Eight 16-bit unsigned integer values */ +typedef v_reg v_uint16x8; +/** @brief Eight 16-bit signed integer values */ +typedef v_reg v_int16x8; +/** @brief Four 32-bit unsigned integer values */ +typedef v_reg v_uint32x4; +/** @brief Four 32-bit signed integer values */ +typedef v_reg v_int32x4; +/** @brief Four 32-bit floating point values (single precision) */ +typedef v_reg v_float32x4; +/** @brief Two 64-bit floating point values (double precision) */ +typedef v_reg v_float64x2; +/** @brief Two 64-bit unsigned integer values */ +typedef v_reg v_uint64x2; +/** @brief Two 64-bit signed integer values */ +typedef v_reg v_int64x2; + +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_BIN_OP(bin_op) \ template inline v_reg<_Tp, n> \ operator bin_op (const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ @@ -140,11 +388,28 @@ template inline v_reg<_Tp, n>& \ return a; \ } +/** @brief Add values + +For all types. */ OPENCV_HAL_IMPL_BIN_OP(+) + +/** @brief Subtract values + +For all types. */ OPENCV_HAL_IMPL_BIN_OP(-) + +/** @brief Multiply values + +For 16- and 32-bit integer types and floating types. */ OPENCV_HAL_IMPL_BIN_OP(*) + +/** @brief Divide values + +For floating types only. */ OPENCV_HAL_IMPL_BIN_OP(/) +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_BIT_OP(bit_op) \ template inline v_reg<_Tp, n> operator bit_op \ (const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ @@ -166,10 +431,24 @@ template inline v_reg<_Tp, n>& operator \ return a; \ } +/** @brief Bitwise AND + +Only for integer types. */ OPENCV_HAL_IMPL_BIT_OP(&) + +/** @brief Bitwise OR + +Only for integer types. */ OPENCV_HAL_IMPL_BIT_OP(|) + +/** @brief Bitwise XOR + +Only for integer types.*/ OPENCV_HAL_IMPL_BIT_OP(^) +/** @brief Bitwise NOT + +Only for integer types.*/ template inline v_reg<_Tp, n> operator ~ (const v_reg<_Tp, n>& a) { v_reg<_Tp, n> c; @@ -178,6 +457,8 @@ template inline v_reg<_Tp, n> operator ~ (const v_reg<_Tp, return c; } +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_MATH_FUNC(func, cfunc, _Tp2) \ template inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a) \ { \ @@ -187,27 +468,59 @@ template inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a) return c; \ } +/** @brief Square root of elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_sqrt, std::sqrt, _Tp) + +//! @cond IGNORED OPENCV_HAL_IMPL_MATH_FUNC(v_sin, std::sin, _Tp) OPENCV_HAL_IMPL_MATH_FUNC(v_cos, std::cos, _Tp) OPENCV_HAL_IMPL_MATH_FUNC(v_exp, std::exp, _Tp) OPENCV_HAL_IMPL_MATH_FUNC(v_log, std::log, _Tp) +//! @endcond + +/** @brief Absolute value of elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_abs, (typename V_TypeTraits<_Tp>::abs_type)std::abs, typename V_TypeTraits<_Tp>::abs_type) + +/** @brief Round elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_round, cvRound, int) + +/** @brief Floor elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_floor, cvFloor, int) + +/** @brief Ceil elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_ceil, cvCeil, int) + +/** @brief Truncate elements + +Only for floating point types.*/ OPENCV_HAL_IMPL_MATH_FUNC(v_trunc, int, int) -#define OPENCV_HAL_IMPL_MINMAX_FUNC(func, hfunc, cfunc) \ +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_MINMAX_FUNC(func, cfunc) \ template inline v_reg<_Tp, n> func(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ { \ v_reg<_Tp, n> c; \ for( int i = 0; i < n; i++ ) \ c.s[i] = cfunc(a.s[i], b.s[i]); \ return c; \ -} \ -template inline _Tp hfunc(const v_reg<_Tp, n>& a) \ +} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(func, cfunc) \ +template inline _Tp func(const v_reg<_Tp, n>& a) \ { \ _Tp c = a.s[0]; \ for( int i = 1; i < n; i++ ) \ @@ -215,9 +528,49 @@ template inline _Tp hfunc(const v_reg<_Tp, n>& a) \ return c; \ } -OPENCV_HAL_IMPL_MINMAX_FUNC(v_min, v_reduce_min, std::min) -OPENCV_HAL_IMPL_MINMAX_FUNC(v_max, v_reduce_max, std::max) +/** @brief Choose min values for each pair +Scheme: +@code +{A1 A2 ...} +{B1 B2 ...} +-------------- +{min(A1,B1) min(A2,B2) ...} +@endcode +For all types except 64-bit integer. */ +OPENCV_HAL_IMPL_MINMAX_FUNC(v_min, std::min) + +/** @brief Choose max values for each pair + +Scheme: +@code +{A1 A2 ...} +{B1 B2 ...} +-------------- +{max(A1,B1) max(A2,B2) ...} +@endcode +For all types except 64-bit integer. */ +OPENCV_HAL_IMPL_MINMAX_FUNC(v_max, std::max) + +/** @brief Find one min value + +Scheme: +@code +{A1 A2 A3 ...} => min(A1,A2,A3,...) +@endcode +For 32-bit integer and 32-bit floating point types. */ +OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_min, std::min) + +/** @brief Find one max value + +Scheme: +@code +{A1 A2 A3 ...} => max(A1,A2,A3,...) +@endcode +For 32-bit integer and 32-bit floating point types. */ +OPENCV_HAL_IMPL_REDUCE_MINMAX_FUNC(v_reduce_max, std::max) + +//! @cond IGNORED template inline void v_minmax( const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, v_reg<_Tp, n>& minval, v_reg<_Tp, n>& maxval ) @@ -228,8 +581,10 @@ inline void v_minmax( const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, maxval.s[i] = std::max(a.s[i], b.s[i]); } } +//! @endcond - +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_CMP_OP(cmp_op) \ template \ inline v_reg<_Tp, n> operator cmp_op(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ @@ -241,13 +596,38 @@ inline v_reg<_Tp, n> operator cmp_op(const v_reg<_Tp, n>& a, const v_reg<_Tp, n> return c; \ } +/** @brief Less-than comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(<) + +/** @brief Greater-than comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(>) + +/** @brief Less-than or equal comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(<=) + +/** @brief Greater-than or equal comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(>=) + +/** @brief Equal comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(==) + +/** @brief Not equal comparison + +For all types except 64-bit integer values. */ OPENCV_HAL_IMPL_CMP_OP(!=) +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_ADD_SUB_OP(func, bin_op, cast_op, _Tp2) \ template \ inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ @@ -259,10 +639,73 @@ inline v_reg<_Tp2, n> func(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) \ return c; \ } -OPENCV_HAL_IMPL_ADD_SUB_OP(v_add_wrap, +, (_Tp), _Tp) -OPENCV_HAL_IMPL_ADD_SUB_OP(v_sub_wrap, -, (_Tp), _Tp) -OPENCV_HAL_IMPL_ADD_SUB_OP(v_absdiff, -, (rtype)std::abs, typename V_TypeTraits<_Tp>::abs_type) +/** @brief Add values without saturation +For 8- and 16-bit integer values. */ +OPENCV_HAL_IMPL_ADD_SUB_OP(v_add_wrap, +, (_Tp), _Tp) + +/** @brief Subtract values without saturation + +For 8- and 16-bit integer values. */ +OPENCV_HAL_IMPL_ADD_SUB_OP(v_sub_wrap, -, (_Tp), _Tp) + +//! @cond IGNORED +template inline T _absdiff(T a, T b) +{ + return a > b ? a - b : b - a; +} +//! @endcond + +/** @brief Absolute difference + +Returns \f$ |a - b| \f$ converted to corresponding unsigned type. +Example: +@code{.cpp} +v_int32x4 a, b; // {1, 2, 3, 4} and {4, 3, 2, 1} +v_uint32x4 c = v_absdiff(a, b); // result is {3, 1, 1, 3} +@endcode +For 8-, 16-, 32-bit integer source types. */ +template +inline v_reg::abs_type, n> v_absdiff(const v_reg<_Tp, n>& a, const v_reg<_Tp, n> & b) +{ + typedef typename V_TypeTraits<_Tp>::abs_type rtype; + v_reg c; + const rtype mask = std::numeric_limits<_Tp>::is_signed ? (1 << (sizeof(rtype)*8 - 1)) : 0; + for( int i = 0; i < n; i++ ) + { + rtype ua = a.s[i] ^ mask; + rtype ub = b.s[i] ^ mask; + c.s[i] = _absdiff(ua, ub); + } + return c; +} + +/** @overload + +For 32-bit floating point values */ +inline v_float32x4 v_absdiff(const v_float32x4& a, const v_float32x4& b) +{ + v_float32x4 c; + for( int i = 0; i < c.nlanes; i++ ) + c.s[i] = _absdiff(a.s[i], b.s[i]); + return c; +} + +/** @overload + +For 64-bit floating point values */ +inline v_float64x2 v_absdiff(const v_float64x2& a, const v_float64x2& b) +{ + v_float64x2 c; + for( int i = 0; i < c.nlanes; i++ ) + c.s[i] = _absdiff(a.s[i], b.s[i]); + return c; +} + +/** @brief Inversed square root + +Returns \f$ 1/sqrt(a) \f$ +For floating point types only. */ template inline v_reg<_Tp, n> v_invsqrt(const v_reg<_Tp, n>& a) { @@ -272,6 +715,10 @@ inline v_reg<_Tp, n> v_invsqrt(const v_reg<_Tp, n>& a) return c; } +/** @brief Magnitude + +Returns \f$ sqrt(a^2 + b^2) \f$ +For floating point types only. */ template inline v_reg<_Tp, n> v_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { @@ -281,7 +728,10 @@ inline v_reg<_Tp, n> v_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) return c; } +/** @brief Square of the magnitude +Returns \f$ a^2 + b^2 \f$ +For floating point types only. */ template inline v_reg<_Tp, n> v_sqr_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { @@ -291,6 +741,10 @@ inline v_reg<_Tp, n> v_sqr_magnitude(const v_reg<_Tp, n>& a, const v_reg<_Tp, n> return c; } +/** @brief Multiply and add + +Returns \f$ a*b + c \f$ +For floating point types only. */ template inline v_reg<_Tp, n> v_muladd(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c) @@ -301,6 +755,18 @@ inline v_reg<_Tp, n> v_muladd(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, return d; } +/** @brief Dot product of elements + +Multiply values in two registers and sum adjacent result pairs. +Scheme: +@code + {A1 A2 ...} // 16-bit +x {B1 B2 ...} // 16-bit +------------- +{A1B1+A2B2 ...} // 32-bit +@endcode +Implemented only for 16-bit signed source type (v_int16x8). +*/ template inline v_reg::w_type, n/2> v_dotprod(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { @@ -311,6 +777,25 @@ template inline v_reg::w_type, n return c; } +/** @brief Multiply and expand + +Multiply values two registers and store results in two registers with wider pack type. +Scheme: +@code + {A B C D} // 32-bit +x {E F G H} // 32-bit +--------------- +{AE BF} // 64-bit + {CG DH} // 64-bit +@endcode +Example: +@code{.cpp} +v_uint32x4 a, b; // {1,2,3,4} and {2,2,2,2} +v_uint64x2 c, d; // results +v_mul_expand(a, b, c, d); // c, d = {2,4}, {6, 8} +@endcode +Implemented only for 16- and unsigned 32-bit source types (v_int16x8, v_uint16x8, v_uint32x4). +*/ template inline void v_mul_expand(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, v_reg::w_type, n/2>& c, v_reg::w_type, n/2>& d) @@ -318,11 +803,12 @@ template inline void v_mul_expand(const v_reg<_Tp, n>& a, c typedef typename V_TypeTraits<_Tp>::w_type w_type; for( int i = 0; i < (n/2); i++ ) { - c.s[i] = (w_type)a.s[i]*b.s[i]*2; + c.s[i] = (w_type)a.s[i]*b.s[i]; d.s[i] = (w_type)a.s[i+(n/2)]*b.s[i+(n/2)]; } } +//! @cond IGNORED template inline void v_hsum(const v_reg<_Tp, n>& a, v_reg::w_type, n/2>& c) { @@ -332,7 +818,10 @@ template inline void v_hsum(const v_reg<_Tp, n>& a, c.s[i] = (w_type)a.s[i*2] + a.s[i*2+1]; } } +//! @endcond +//! @brief Helper macro +//! @ingroup hal_intrin_impl #define OPENCV_HAL_IMPL_SHIFT_OP(shift_op) \ template inline v_reg<_Tp, n> operator shift_op(const v_reg<_Tp, n>& a, int imm) \ { \ @@ -342,9 +831,23 @@ template inline v_reg<_Tp, n> operator shift_op(const v_reg return c; \ } +/** @brief Bitwise shift left + +For 16-, 32- and 64-bit integer values. */ OPENCV_HAL_IMPL_SHIFT_OP(<<) + +/** @brief Bitwise shift right + +For 16-, 32- and 64-bit integer values. */ OPENCV_HAL_IMPL_SHIFT_OP(>>) +/** @brief Sum packed values + +Scheme: +@code +{A1 A2 A3 ...} => sum{A1,A2,A3,...} +@endcode +For 32-bit integer and 32-bit floating point types.*/ template inline typename V_TypeTraits<_Tp>::sum_type v_reduce_sum(const v_reg<_Tp, n>& a) { typename V_TypeTraits<_Tp>::sum_type c = a.s[0]; @@ -353,6 +856,15 @@ template inline typename V_TypeTraits<_Tp>::sum_type v_redu return c; } +/** @brief Get negative values mask + +Returned value is a bit mask with bits set to 1 on places corresponding to negative packed values indexes. +Example: +@code{.cpp} +v_int32x4 r; // set to {-1, -1, 1, 1} +int mask = v_signmask(r); // mask = 3 <== 00000000 00000000 00000000 00000011 +@endcode +For all types except 64-bit. */ template inline int v_signmask(const v_reg<_Tp, n>& a) { int mask = 0; @@ -361,6 +873,10 @@ template inline int v_signmask(const v_reg<_Tp, n>& a) return mask; } +/** @brief Check if all packed values are less than zero + +Unsigned values will be casted to signed: `uchar 254 => char -2`. +For all types except 64-bit. */ template inline bool v_check_all(const v_reg<_Tp, n>& a) { for( int i = 0; i < n; i++ ) @@ -369,6 +885,10 @@ template inline bool v_check_all(const v_reg<_Tp, n>& a) return true; } +/** @brief Check if any of packed values is less than zero + +Unsigned values will be casted to signed: `uchar 254 => char -2`. +For all types except 64-bit. */ template inline bool v_check_any(const v_reg<_Tp, n>& a) { for( int i = 0; i < n; i++ ) @@ -377,15 +897,36 @@ template inline bool v_check_any(const v_reg<_Tp, n>& a) return false; } +/** @brief Bitwise select + +Return value will be built by combining values a and b using the following scheme: +If the i-th bit in _mask_ is 1 + select i-th bit from _a_ +else + select i-th bit from _b_ */ template inline v_reg<_Tp, n> v_select(const v_reg<_Tp, n>& mask, const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { + typedef V_TypeTraits<_Tp> Traits; + typedef typename Traits::int_type int_type; v_reg<_Tp, n> c; for( int i = 0; i < n; i++ ) - c.s[i] = V_TypeTraits<_Tp>::reinterpret_int(mask.s[i]) < 0 ? b.s[i] : a.s[i]; + { + int_type m = Traits::reinterpret_int(mask.s[i]); + c.s[i] = Traits::reinterpret_from_int((Traits::reinterpret_int(a.s[i]) & m) + | (Traits::reinterpret_int(b.s[i]) & ~m)); + } return c; } +/** @brief Expand values to the wider pack type + +Copy contents of register to two registers with 2x wider pack type. +Scheme: +@code + int32x4 int64x2 int64x2 +{A B C D} ==> {A B} , {C D} +@endcode */ template inline void v_expand(const v_reg<_Tp, n>& a, v_reg::w_type, n/2>& b0, v_reg::w_type, n/2>& b1) @@ -397,6 +938,7 @@ template inline void v_expand(const v_reg<_Tp, n>& a, } } +//! @cond IGNORED template inline v_reg::int_type, n> v_reinterpret_as_int(const v_reg<_Tp, n>& a) { @@ -414,7 +956,19 @@ template inline v_reg::uint_type c.s[i] = V_TypeTraits<_Tp>::reinterpret_uint(a.s[i]); return c; } +//! @endcond +/** @brief Interleave two vectors + +Scheme: +@code + {A1 A2 A3 A4} + {B1 B2 B3 B4} +--------------- + {A1 B1 A2 B2} and {A3 B3 A4 B4} +@endcode +For all types except 64-bit. +*/ template inline void v_zip( const v_reg<_Tp, n>& a0, const v_reg<_Tp, n>& a1, v_reg<_Tp, n>& b0, v_reg<_Tp, n>& b1 ) { @@ -431,50 +985,102 @@ template inline void v_zip( const v_reg<_Tp, n>& a0, const } } -template inline v_reg<_Tp, n> v_load(const _Tp* ptr) +/** @brief Load register contents from memory + +@param ptr pointer to memory block with data +@return register object + +@note Returned type will be detected from passed pointer type, for example uchar ==> cv::v_uint8x16, int ==> cv::v_int32x4, etc. + */ +template +inline v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes> v_load(const _Tp* ptr) { - return v_reg<_Tp, n>(ptr); + return v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes>(ptr); } -template inline v_reg<_Tp, n> v_load_aligned(const _Tp* ptr) +/** @brief Load register contents from memory (aligned) + +similar to cv::v_load, but source memory block should be aligned (to 16-byte boundary) + */ +template +inline v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes> v_load_aligned(const _Tp* ptr) { - return v_reg<_Tp, n>(ptr); + return v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes>(ptr); } -template inline void v_load_halves(const _Tp* loptr, const _Tp* hiptr) +/** @brief Load register contents from two memory blocks + +@param loptr memory block containing data for first half (0..n/2) +@param hiptr memory block containing data for second half (n/2..n) + +@code{.cpp} +int lo[2] = { 1, 2 }, hi[2] = { 3, 4 }; +v_int32x4 r = v_load_halves(lo, hi); +@endcode + */ +template +inline v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes> v_load_halves(const _Tp* loptr, const _Tp* hiptr) { - v_reg<_Tp, n> c; - for( int i = 0; i < n/2; i++ ) + v_reg<_Tp, V_SIMD128Traits<_Tp>::nlanes> c; + for( int i = 0; i < c.nlanes/2; i++ ) { c.s[i] = loptr[i]; - c.s[i+n/2] = hiptr[i]; + c.s[i+c.nlanes/2] = hiptr[i]; } return c; } -template inline v_reg::w_type, n> v_load_expand(const _Tp* ptr) +/** @brief Load register contents from memory with double expand + +Same as cv::v_load, but result pack type will be 2x wider than memory type. + +@code{.cpp} +short buf[4] = {1, 2, 3, 4}; // type is int16 +v_int32x4 r = v_load_expand(buf); // r = {1, 2, 3, 4} - type is int32 +@endcode +For 8-, 16-, 32-bit integer source types. */ +template +inline v_reg::w_type, V_SIMD128Traits<_Tp>::nlanes / 2> +v_load_expand(const _Tp* ptr) { typedef typename V_TypeTraits<_Tp>::w_type w_type; - v_reg c; - for( int i = 0; i < n; i++ ) + v_reg::nlanes> c; + for( int i = 0; i < c.nlanes; i++ ) { c.s[i] = ptr[i]; } return c; } -template inline v_reg::w_type>::w_type, n> v_load_expand_q(const _Tp* ptr) +/** @brief Load register contents from memory with quad expand + +Same as cv::v_load_expand, but result type is 4 times wider than source. +@code{.cpp} +char buf[4] = {1, 2, 3, 4}; // type is int8 +v_int32x4 r = v_load_q(buf); // r = {1, 2, 3, 4} - type is int32 +@endcode +For 8-bit integer source types. */ +template +inline v_reg::q_type, V_SIMD128Traits<_Tp>::nlanes / 4> +v_load_expand_q(const _Tp* ptr) { - typedef typename V_TypeTraits::w_type>::w_type w_type; - v_reg c; - for( int i = 0; i < n; i++ ) + typedef typename V_TypeTraits<_Tp>::q_type q_type; + v_reg::nlanes> c; + for( int i = 0; i < c.nlanes; i++ ) { c.s[i] = ptr[i]; } return c; } +/** @brief Load and deinterleave (4 channels) + +Load data from memory deinterleave and store to 4 registers. +Scheme: +@code +{A1 B1 C1 D1 A2 B2 C2 D2 ...} ==> {A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...}, {D1 D2 ...} +@endcode +For all types except 64-bit. */ template inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, v_reg<_Tp, n>& b, v_reg<_Tp, n>& c) { @@ -487,6 +1093,14 @@ template inline void v_load_deinterleave(const _Tp* ptr, v_ } } +/** @brief Load and deinterleave (3 channels) + +Load data from memory deinterleave and store to 3 registers. +Scheme: +@code +{A1 B1 C1 A2 B2 C2 ...} ==> {A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...} +@endcode +For all types except 64-bit. */ template inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, v_reg<_Tp, n>& b, v_reg<_Tp, n>& c, @@ -502,6 +1116,14 @@ inline void v_load_deinterleave(const _Tp* ptr, v_reg<_Tp, n>& a, } } +/** @brief Interleave and store (3 channels) + +Interleave and store data from 3 registers to memory. +Scheme: +@code +{A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...}, {D1 D2 ...} ==> {A1 B1 C1 D1 A2 B2 C2 D2 ...} +@endcode +For all types except 64-bit. */ template inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c) @@ -515,6 +1137,14 @@ inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, } } +/** @brief Interleave and store (4 channels) + +Interleave and store data from 4 registers to memory. +Scheme: +@code +{A1 A2 ...}, {B1 B2 ...}, {C1 C2 ...}, {D1 D2 ...} ==> {A1 B1 C1 D1 A2 B2 C2 D2 ...} +@endcode +For all types except 64-bit. */ template inline void v_store_interleave( _Tp* ptr, const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, const v_reg<_Tp, n>& c, const v_reg<_Tp, n>& d) @@ -529,6 +1159,14 @@ template inline void v_store_interleave( _Tp* ptr, const v_ } } +/** @brief Store data to memory + +Store register contents to memory. +Scheme: +@code + REG {A B C D} ==> MEM {A B C D} +@endcode +Pointer can be unaligned. */ template inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a) { @@ -536,6 +1174,13 @@ inline void v_store(_Tp* ptr, const v_reg<_Tp, n>& a) ptr[i] = a.s[i]; } +/** @brief Store data to memory (lower half) + +Store lower half of register contents to memory. +Scheme: +@code + REG {A B C D} ==> MEM {A B} +@endcode */ template inline void v_store_low(_Tp* ptr, const v_reg<_Tp, n>& a) { @@ -543,6 +1188,13 @@ inline void v_store_low(_Tp* ptr, const v_reg<_Tp, n>& a) ptr[i] = a.s[i]; } +/** @brief Store data to memory (higher half) + +Store higher half of register contents to memory. +Scheme: +@code + REG {A B C D} ==> MEM {C D} +@endcode */ template inline void v_store_high(_Tp* ptr, const v_reg<_Tp, n>& a) { @@ -550,6 +1202,14 @@ inline void v_store_high(_Tp* ptr, const v_reg<_Tp, n>& a) ptr[i] = a.s[i+(n/2)]; } +/** @brief Store data to memory (aligned) + +Store register contents to memory. +Scheme: +@code + REG {A B C D} ==> MEM {A B C D} +@endcode +Pointer __should__ be aligned by 16-byte boundary. */ template inline void v_store_aligned(_Tp* ptr, const v_reg<_Tp, n>& a) { @@ -557,6 +1217,16 @@ inline void v_store_aligned(_Tp* ptr, const v_reg<_Tp, n>& a) ptr[i] = a.s[i]; } +/** @brief Combine vector from first elements of two vectors + +Scheme: +@code + {A1 A2 A3 A4} + {B1 B2 B3 B4} +--------------- + {A1 A2 B1 B2} +@endcode +For all types except 64-bit. */ template inline v_reg<_Tp, n> v_combine_low(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { @@ -569,6 +1239,16 @@ inline v_reg<_Tp, n> v_combine_low(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& return c; } +/** @brief Combine vector from last elements of two vectors + +Scheme: +@code + {A1 A2 A3 A4} + {B1 B2 B3 B4} +--------------- + {A3 A4 B3 B4} +@endcode +For all types except 64-bit. */ template inline v_reg<_Tp, n> v_combine_high(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { @@ -581,6 +1261,12 @@ inline v_reg<_Tp, n> v_combine_high(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& return c; } +/** @brief Combine two vectors from lower and higher parts of two other vectors + +@code{.cpp} +low = cv::v_combine_low(a, b); +high = cv::v_combine_high(a, b); +@endcode */ template inline void v_recombine(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, v_reg<_Tp, n>& low, v_reg<_Tp, n>& high) @@ -594,18 +1280,41 @@ inline void v_recombine(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b, } } +/** @brief Vector extract + +Scheme: +@code + {A1 A2 A3 A4} + {B1 B2 B3 B4} +======================== +shift = 1 {A2 A3 A4 B1} +shift = 2 {A3 A4 B1 B2} +shift = 3 {A4 B1 B2 B3} +@endcode +Restriction: 0 <= shift < nlanes + +Usage: +@code +v_int32x4 a, b, c; +c = v_extract<2>(a, b); +@endcode +For integer types only. */ template inline v_reg<_Tp, n> v_extract(const v_reg<_Tp, n>& a, const v_reg<_Tp, n>& b) { v_reg<_Tp, n> r; + const int shift = n - s; int i = 0; - for (; i < s; ++i) - r.s[i] = a.s[i+n-s]; + for (; i < shift; ++i) + r.s[i] = a.s[i+s]; for (; i < n; ++i) - r.s[i] = b.s[i-s]; + r.s[i] = b.s[i-shift]; return r; } +/** @brief Round + +Rounds each value. Input type is float vector ==> output type is int vector.*/ template inline v_reg v_round(const v_reg& a) { v_reg c; @@ -614,6 +1323,9 @@ template inline v_reg v_round(const v_reg& a) return c; } +/** @brief Floor + +Floor each value. Input type is float vector ==> output type is int vector.*/ template inline v_reg v_floor(const v_reg& a) { v_reg c; @@ -622,6 +1334,9 @@ template inline v_reg v_floor(const v_reg& a) return c; } +/** @brief Ceil + +Ceil each value. Input type is float vector ==> output type is int vector.*/ template inline v_reg v_ceil(const v_reg& a) { v_reg c; @@ -630,6 +1345,9 @@ template inline v_reg v_ceil(const v_reg& a) return c; } +/** @brief Trunc + +Truncate each value. Input type is float vector ==> output type is int vector.*/ template inline v_reg v_trunc(const v_reg& a) { v_reg c; @@ -638,6 +1356,7 @@ template inline v_reg v_trunc(const v_reg& a) return c; } +/** @overload */ template inline v_reg v_round(const v_reg& a) { v_reg c; @@ -649,6 +1368,7 @@ template inline v_reg v_round(const v_reg& a) return c; } +/** @overload */ template inline v_reg v_floor(const v_reg& a) { v_reg c; @@ -660,6 +1380,7 @@ template inline v_reg v_floor(const v_reg& a) return c; } +/** @overload */ template inline v_reg v_ceil(const v_reg& a) { v_reg c; @@ -671,6 +1392,7 @@ template inline v_reg v_ceil(const v_reg& a) return c; } +/** @overload */ template inline v_reg v_trunc(const v_reg& a) { v_reg c; @@ -682,6 +1404,9 @@ template inline v_reg v_trunc(const v_reg& a) return c; } +/** @brief Convert to float + +Supported input type is cv::v_int32x4. */ template inline v_reg v_cvt_f32(const v_reg& a) { v_reg c; @@ -690,6 +1415,9 @@ template inline v_reg v_cvt_f32(const v_reg& a) return c; } +/** @brief Convert to double + +Supported input type is cv::v_int32x4. */ template inline v_reg v_cvt_f64(const v_reg& a) { v_reg c; @@ -698,6 +1426,9 @@ template inline v_reg v_cvt_f64(const v_reg& a) return c; } +/** @brief Convert to double + +Supported input type is cv::v_float32x4. */ template inline v_reg v_cvt_f64(const v_reg& a) { v_reg c; @@ -706,6 +1437,21 @@ template inline v_reg v_cvt_f64(const v_reg& a) return c; } +/** @brief Transpose 4x4 matrix + +Scheme: +@code +a0 {A1 A2 A3 A4} +a1 {B1 B2 B3 B4} +a2 {C1 C2 C3 C4} +a3 {D1 D2 D3 D4} +=============== +b0 {A1 B1 C1 D1} +b1 {A2 B2 C2 D2} +b2 {A3 B3 C3 D3} +b3 {A4 B4 C4 D4} +@endcode +*/ template inline void v_transpose4x4( v_reg<_Tp, 4>& a0, const v_reg<_Tp, 4>& a1, const v_reg<_Tp, 4>& a2, const v_reg<_Tp, 4>& a3, @@ -718,41 +1464,105 @@ inline void v_transpose4x4( v_reg<_Tp, 4>& a0, const v_reg<_Tp, 4>& a1, b3 = v_reg<_Tp, 4>(a0.s[3], a1.s[3], a2.s[3], a3.s[3]); } -typedef v_reg v_uint8x16; -typedef v_reg v_int8x16; -typedef v_reg v_uint16x8; -typedef v_reg v_int16x8; -typedef v_reg v_uint32x4; -typedef v_reg v_int32x4; -typedef v_reg v_float32x4; -typedef v_reg v_float32x8; -typedef v_reg v_float64x2; -typedef v_reg v_uint64x2; -typedef v_reg v_int64x2; +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_INIT_ZERO(_Tpvec, _Tp, suffix) \ +inline _Tpvec v_setzero_##suffix() { return _Tpvec::zero(); } -#define OPENCV_HAL_IMPL_C_INIT(_Tpvec, _Tp, suffix) \ -inline _Tpvec v_setzero_##suffix() { return _Tpvec::zero(); } \ -inline _Tpvec v_setall_##suffix(_Tp val) { return _Tpvec::all(val); } \ +//! @name Init with zero +//! @{ +//! @brief Create new vector with zero elements +OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint8x16, uchar, u8) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_int8x16, schar, s8) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint16x8, ushort, u16) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_int16x8, short, s16) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_int32x4, int, s32) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_float32x4, float, f32) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_float64x2, double, f64) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_uint64x2, uint64, u64) +OPENCV_HAL_IMPL_C_INIT_ZERO(v_int64x2, int64, s64) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_INIT_VAL(_Tpvec, _Tp, suffix) \ +inline _Tpvec v_setall_##suffix(_Tp val) { return _Tpvec::all(val); } + +//! @name Init with value +//! @{ +//! @brief Create new vector with elements set to a specific value +OPENCV_HAL_IMPL_C_INIT_VAL(v_uint8x16, uchar, u8) +OPENCV_HAL_IMPL_C_INIT_VAL(v_int8x16, schar, s8) +OPENCV_HAL_IMPL_C_INIT_VAL(v_uint16x8, ushort, u16) +OPENCV_HAL_IMPL_C_INIT_VAL(v_int16x8, short, s16) +OPENCV_HAL_IMPL_C_INIT_VAL(v_uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_C_INIT_VAL(v_int32x4, int, s32) +OPENCV_HAL_IMPL_C_INIT_VAL(v_float32x4, float, f32) +OPENCV_HAL_IMPL_C_INIT_VAL(v_float64x2, double, f64) +OPENCV_HAL_IMPL_C_INIT_VAL(v_uint64x2, uint64, u64) +OPENCV_HAL_IMPL_C_INIT_VAL(v_int64x2, int64, s64) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_REINTERPRET(_Tpvec, _Tp, suffix) \ template inline _Tpvec \ v_reinterpret_as_##suffix(const v_reg<_Tp0, n0>& a) \ -{ return a.template reinterpret_as<_Tp, _Tpvec::nlanes>(a); } +{ return a.template reinterpret_as<_Tp, _Tpvec::nlanes>(); } -OPENCV_HAL_IMPL_C_INIT(v_uint8x16, uchar, u8) -OPENCV_HAL_IMPL_C_INIT(v_int8x16, schar, s8) -OPENCV_HAL_IMPL_C_INIT(v_uint16x8, ushort, u16) -OPENCV_HAL_IMPL_C_INIT(v_int16x8, short, s16) -OPENCV_HAL_IMPL_C_INIT(v_uint32x4, unsigned, u32) -OPENCV_HAL_IMPL_C_INIT(v_int32x4, int, s32) -OPENCV_HAL_IMPL_C_INIT(v_float32x4, float, f32) -OPENCV_HAL_IMPL_C_INIT(v_float64x2, double, f64) -OPENCV_HAL_IMPL_C_INIT(v_uint64x2, uint64, u64) -OPENCV_HAL_IMPL_C_INIT(v_uint64x2, int64, s64) +//! @name Reinterpret +//! @{ +//! @brief Convert vector to different type without modifying underlying data. +OPENCV_HAL_IMPL_C_REINTERPRET(v_uint8x16, uchar, u8) +OPENCV_HAL_IMPL_C_REINTERPRET(v_int8x16, schar, s8) +OPENCV_HAL_IMPL_C_REINTERPRET(v_uint16x8, ushort, u16) +OPENCV_HAL_IMPL_C_REINTERPRET(v_int16x8, short, s16) +OPENCV_HAL_IMPL_C_REINTERPRET(v_uint32x4, unsigned, u32) +OPENCV_HAL_IMPL_C_REINTERPRET(v_int32x4, int, s32) +OPENCV_HAL_IMPL_C_REINTERPRET(v_float32x4, float, f32) +OPENCV_HAL_IMPL_C_REINTERPRET(v_float64x2, double, f64) +OPENCV_HAL_IMPL_C_REINTERPRET(v_uint64x2, uint64, u64) +OPENCV_HAL_IMPL_C_REINTERPRET(v_int64x2, int64, s64) +//! @} -#define OPENCV_HAL_IMPL_C_SHIFT(_Tpvec, _Tp) \ +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_SHIFTL(_Tpvec, _Tp) \ template inline _Tpvec v_shl(const _Tpvec& a) \ -{ return a << n; } \ +{ return a << n; } + +//! @name Left shift +//! @{ +//! @brief Shift left +OPENCV_HAL_IMPL_C_SHIFTL(v_uint16x8, ushort) +OPENCV_HAL_IMPL_C_SHIFTL(v_int16x8, short) +OPENCV_HAL_IMPL_C_SHIFTL(v_uint32x4, unsigned) +OPENCV_HAL_IMPL_C_SHIFTL(v_int32x4, int) +OPENCV_HAL_IMPL_C_SHIFTL(v_uint64x2, uint64) +OPENCV_HAL_IMPL_C_SHIFTL(v_int64x2, int64) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_SHIFTR(_Tpvec, _Tp) \ template inline _Tpvec v_shr(const _Tpvec& a) \ -{ return a >> n; } \ +{ return a >> n; } + +//! @name Right shift +//! @{ +//! @brief Shift right +OPENCV_HAL_IMPL_C_SHIFTR(v_uint16x8, ushort) +OPENCV_HAL_IMPL_C_SHIFTR(v_int16x8, short) +OPENCV_HAL_IMPL_C_SHIFTR(v_uint32x4, unsigned) +OPENCV_HAL_IMPL_C_SHIFTR(v_int32x4, int) +OPENCV_HAL_IMPL_C_SHIFTR(v_uint64x2, uint64) +OPENCV_HAL_IMPL_C_SHIFTR(v_int64x2, int64) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_RSHIFTR(_Tpvec, _Tp) \ template inline _Tpvec v_rshr(const _Tpvec& a) \ { \ _Tpvec c; \ @@ -761,15 +1571,20 @@ template inline _Tpvec v_rshr(const _Tpvec& a) \ return c; \ } -OPENCV_HAL_IMPL_C_SHIFT(v_uint16x8, ushort) -OPENCV_HAL_IMPL_C_SHIFT(v_int16x8, short) -OPENCV_HAL_IMPL_C_SHIFT(v_uint32x4, unsigned) -OPENCV_HAL_IMPL_C_SHIFT(v_int32x4, int) -OPENCV_HAL_IMPL_C_SHIFT(v_uint64x2, uint64) -OPENCV_HAL_IMPL_C_SHIFT(v_int64x2, int64) +//! @name Rounding shift +//! @{ +//! @brief Rounding shift right +OPENCV_HAL_IMPL_C_RSHIFTR(v_uint16x8, ushort) +OPENCV_HAL_IMPL_C_RSHIFTR(v_int16x8, short) +OPENCV_HAL_IMPL_C_RSHIFTR(v_uint32x4, unsigned) +OPENCV_HAL_IMPL_C_RSHIFTR(v_int32x4, int) +OPENCV_HAL_IMPL_C_RSHIFTR(v_uint64x2, uint64) +OPENCV_HAL_IMPL_C_RSHIFTR(v_int64x2, int64) +//! @} - -#define OPENCV_HAL_IMPL_C_PACK(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \ +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_PACK(_Tpvec, _Tpnvec, _Tpn, pack_suffix) \ inline _Tpnvec v_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \ { \ _Tpnvec c; \ @@ -779,7 +1594,30 @@ inline _Tpnvec v_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \ c.s[i+_Tpvec::nlanes] = saturate_cast<_Tpn>(b.s[i]); \ } \ return c; \ -} \ +} + +//! @name Pack +//! @{ +//! @brief Pack values from two vectors to one +//! +//! Return vector type have twice more elements than input vector types. Variant with _u_ suffix also +//! converts to corresponding unsigned type. +//! +//! - pack: for 16-, 32- and 64-bit integer input types +//! - pack_u: for 16- and 32-bit signed integer input types +OPENCV_HAL_IMPL_C_PACK(v_uint16x8, v_uint8x16, uchar, pack) +OPENCV_HAL_IMPL_C_PACK(v_int16x8, v_int8x16, schar, pack) +OPENCV_HAL_IMPL_C_PACK(v_uint32x4, v_uint16x8, ushort, pack) +OPENCV_HAL_IMPL_C_PACK(v_int32x4, v_int16x8, short, pack) +OPENCV_HAL_IMPL_C_PACK(v_uint64x2, v_uint32x4, unsigned, pack) +OPENCV_HAL_IMPL_C_PACK(v_int64x2, v_int32x4, int, pack) +OPENCV_HAL_IMPL_C_PACK(v_int16x8, v_uint8x16, uchar, pack_u) +OPENCV_HAL_IMPL_C_PACK(v_int32x4, v_uint16x8, ushort, pack_u) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_RSHR_PACK(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \ template inline _Tpnvec v_rshr_##pack_suffix(const _Tpvec& a, const _Tpvec& b) \ { \ _Tpnvec c; \ @@ -789,27 +1627,98 @@ template inline _Tpnvec v_rshr_##pack_suffix(const _Tpvec& a, const _Tpve c.s[i+_Tpvec::nlanes] = saturate_cast<_Tpn>((b.s[i] + ((_Tp)1 << (n - 1))) >> n); \ } \ return c; \ -} \ +} + +//! @name Pack with rounding shift +//! @{ +//! @brief Pack values from two vectors to one with rounding shift +//! +//! Values from the input vectors will be shifted right by _n_ bits with rounding, converted to narrower +//! type and returned in the result vector. Variant with _u_ suffix converts to unsigned type. +//! +//! - pack: for 16-, 32- and 64-bit integer input types +//! - pack_u: for 16- and 32-bit signed integer input types +OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint16x8, ushort, v_uint8x16, uchar, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_int16x8, short, v_int8x16, schar, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint32x4, unsigned, v_uint16x8, ushort, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_int32x4, int, v_int16x8, short, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_uint64x2, uint64, v_uint32x4, unsigned, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_int64x2, int64, v_int32x4, int, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_int16x8, short, v_uint8x16, uchar, pack_u) +OPENCV_HAL_IMPL_C_RSHR_PACK(v_int32x4, int, v_uint16x8, ushort, pack_u) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_PACK_STORE(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \ inline void v_##pack_suffix##_store(_Tpn* ptr, const _Tpvec& a) \ { \ for( int i = 0; i < _Tpvec::nlanes; i++ ) \ ptr[i] = saturate_cast<_Tpn>(a.s[i]); \ -} \ +} + +//! @name Pack and store +//! @{ +//! @brief Store values from the input vector into memory with pack +//! +//! Values will be stored into memory with saturating conversion to narrower type. +//! Variant with _u_ suffix converts to corresponding unsigned type. +//! +//! - pack: for 16-, 32- and 64-bit integer input types +//! - pack_u: for 16- and 32-bit signed integer input types +OPENCV_HAL_IMPL_C_PACK_STORE(v_uint16x8, ushort, v_uint8x16, uchar, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_int16x8, short, v_int8x16, schar, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_uint32x4, unsigned, v_uint16x8, ushort, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_int32x4, int, v_int16x8, short, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_uint64x2, uint64, v_uint32x4, unsigned, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_int64x2, int64, v_int32x4, int, pack) +OPENCV_HAL_IMPL_C_PACK_STORE(v_int16x8, short, v_uint8x16, uchar, pack_u) +OPENCV_HAL_IMPL_C_PACK_STORE(v_int32x4, int, v_uint16x8, ushort, pack_u) +//! @} + +//! @brief Helper macro +//! @ingroup hal_intrin_impl +#define OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(_Tpvec, _Tp, _Tpnvec, _Tpn, pack_suffix) \ template inline void v_rshr_##pack_suffix##_store(_Tpn* ptr, const _Tpvec& a) \ { \ for( int i = 0; i < _Tpvec::nlanes; i++ ) \ ptr[i] = saturate_cast<_Tpn>((a.s[i] + ((_Tp)1 << (n - 1))) >> n); \ } -OPENCV_HAL_IMPL_C_PACK(v_uint16x8, ushort, v_uint8x16, uchar, pack) -OPENCV_HAL_IMPL_C_PACK(v_int16x8, short, v_int8x16, schar, pack) -OPENCV_HAL_IMPL_C_PACK(v_int16x8, short, v_uint8x16, uchar, pack_u) -OPENCV_HAL_IMPL_C_PACK(v_uint32x4, unsigned, v_uint16x8, ushort, pack) -OPENCV_HAL_IMPL_C_PACK(v_int32x4, int, v_int16x8, short, pack) -OPENCV_HAL_IMPL_C_PACK(v_int32x4, int, v_uint16x8, ushort, pack_u) -OPENCV_HAL_IMPL_C_PACK(v_uint64x2, uint64, v_uint32x4, unsigned, pack) -OPENCV_HAL_IMPL_C_PACK(v_int64x2, int64, v_int32x4, int, pack) +//! @name Pack and store with rounding shift +//! @{ +//! @brief Store values from the input vector into memory with pack +//! +//! Values will be shifted _n_ bits right with rounding, converted to narrower type and stored into +//! memory. Variant with _u_ suffix converts to unsigned type. +//! +//! - pack: for 16-, 32- and 64-bit integer input types +//! - pack_u: for 16- and 32-bit signed integer input types +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint16x8, ushort, v_uint8x16, uchar, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int16x8, short, v_int8x16, schar, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint32x4, unsigned, v_uint16x8, ushort, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int32x4, int, v_int16x8, short, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_uint64x2, uint64, v_uint32x4, unsigned, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int64x2, int64, v_int32x4, int, pack) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int16x8, short, v_uint8x16, uchar, pack_u) +OPENCV_HAL_IMPL_C_RSHR_PACK_STORE(v_int32x4, int, v_uint16x8, ushort, pack_u) +//! @} +/** @brief Matrix multiplication + +Scheme: +@code +{A0 A1 A2 A3} |V0| +{B0 B1 B2 B3} |V1| +{C0 C1 C2 C3} |V2| +{D0 D1 D2 D3} x |V3| +==================== +{R0 R1 R2 R3}, where: +R0 = A0V0 + A1V1 + A2V2 + A3V3, +R1 = B0V0 + B1V1 + B2V2 + B3V3 +... +@endcode +*/ inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0, const v_float32x4& m1, const v_float32x4& m2, const v_float32x4& m3) @@ -820,6 +1729,8 @@ inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0, v.s[0]*m0.s[3] + v.s[1]*m1.s[3] + v.s[2]*m2.s[3] + v.s[3]*m3.s[3]); } +//! @} + } #endif diff --git a/modules/hal/include/opencv2/hal/intrin_neon.hpp b/modules/hal/include/opencv2/hal/intrin_neon.hpp index e326696d6..d53971f96 100644 --- a/modules/hal/include/opencv2/hal/intrin_neon.hpp +++ b/modules/hal/include/opencv2/hal/intrin_neon.hpp @@ -48,6 +48,8 @@ namespace cv { +//! @cond IGNORED + #define CV_SIMD128 1 struct v_uint8x16 @@ -278,14 +280,15 @@ void v_rshr_##pack##_store(_Tp* ptr, const _Tpwvec& a) \ } OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_uint16x8, u16, pack, n) -OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_int16x8, s16, pack_u, un) OPENCV_HAL_IMPL_NEON_PACK(v_int8x16, schar, int8x8_t, s8, v_int16x8, s16, pack, n) OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_uint32x4, u32, pack, n) -OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_int32x4, s32, pack_u, un) OPENCV_HAL_IMPL_NEON_PACK(v_int16x8, short, int16x4_t, s16, v_int32x4, s32, pack, n) OPENCV_HAL_IMPL_NEON_PACK(v_uint32x4, unsigned, uint32x2_t, u32, v_uint64x2, u64, pack, n) OPENCV_HAL_IMPL_NEON_PACK(v_int32x4, int, int32x2_t, s32, v_int64x2, s64, pack, n) +OPENCV_HAL_IMPL_NEON_PACK(v_uint8x16, uchar, uint8x8_t, u8, v_int16x8, s16, pack_u, un) +OPENCV_HAL_IMPL_NEON_PACK(v_uint16x8, ushort, uint16x4_t, u16, v_int32x4, s32, pack_u, un) + inline v_float32x4 v_matmul(const v_float32x4& v, const v_float32x4& m0, const v_float32x4& m1, const v_float32x4& m2, const v_float32x4& m3) @@ -374,7 +377,7 @@ inline v_int32x4 v_dotprod(const v_int16x8& a, const v_int16x8& b) { int32x4_t c = vmull_s16(vget_low_s16(a.val), vget_low_s16(b.val)); int32x4_t d = vmull_s16(vget_high_s16(a.val), vget_high_s16(b.val)); - int32x4x2_t cd = vtrnq_s32(c, d); + int32x4x2_t cd = vuzpq_s32(c, d); return v_int32x4(vaddq_s32(cd.val[0], cd.val[1])); } @@ -497,6 +500,16 @@ OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint16x8, v_absdiff, vabdq_u16) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_uint32x4, v_absdiff, vabdq_u32) OPENCV_HAL_IMPL_NEON_BIN_FUNC(v_float32x4, v_absdiff, vabdq_f32) +#define OPENCV_HAL_IMPL_NEON_BIN_FUNC2(_Tpvec, _Tpvec2, cast, func, intrin) \ +inline _Tpvec2 func(const _Tpvec& a, const _Tpvec& b) \ +{ \ + return _Tpvec2(cast(intrin(a.val, b.val))); \ +} + +OPENCV_HAL_IMPL_NEON_BIN_FUNC2(v_int8x16, v_uint8x16, vreinterpretq_u8_s8, v_absdiff, vabdq_s8) +OPENCV_HAL_IMPL_NEON_BIN_FUNC2(v_int16x8, v_uint16x8, vreinterpretq_u16_s16, v_absdiff, vabdq_s16) +OPENCV_HAL_IMPL_NEON_BIN_FUNC2(v_int32x4, v_uint32x4, vreinterpretq_u32_s32, v_absdiff, vabdq_s32) + inline v_float32x4 v_magnitude(const v_float32x4& a, const v_float32x4& b) { v_float32x4 x(vmlaq_f32(vmulq_f32(a.val, a.val), b.val, b.val)); @@ -641,13 +654,13 @@ inline bool v_check_all(const v_float32x4& a) { return v_check_all(v_reinterpret_as_u32(a)); } inline bool v_check_any(const v_int8x16& a) -{ return v_check_all(v_reinterpret_as_u8(a)); } +{ return v_check_any(v_reinterpret_as_u8(a)); } inline bool v_check_any(const v_int16x8& a) -{ return v_check_all(v_reinterpret_as_u16(a)); } +{ return v_check_any(v_reinterpret_as_u16(a)); } inline bool v_check_any(const v_int32x4& a) -{ return v_check_all(v_reinterpret_as_u32(a)); } +{ return v_check_any(v_reinterpret_as_u32(a)); } inline bool v_check_any(const v_float32x4& a) -{ return v_check_all(v_reinterpret_as_u32(a)); } +{ return v_check_any(v_reinterpret_as_u32(a)); } #define OPENCV_HAL_IMPL_NEON_SELECT(_Tpvec, suffix, usuffix) \ inline _Tpvec v_select(const _Tpvec& mask, const _Tpvec& a, const _Tpvec& b) \ @@ -678,6 +691,8 @@ OPENCV_HAL_IMPL_NEON_EXPAND(v_uint8x16, v_uint16x8, uchar, u8) OPENCV_HAL_IMPL_NEON_EXPAND(v_int8x16, v_int16x8, schar, s8) OPENCV_HAL_IMPL_NEON_EXPAND(v_uint16x8, v_uint32x4, ushort, u16) OPENCV_HAL_IMPL_NEON_EXPAND(v_int16x8, v_int32x4, short, s16) +OPENCV_HAL_IMPL_NEON_EXPAND(v_uint32x4, v_uint64x2, uint, u32) +OPENCV_HAL_IMPL_NEON_EXPAND(v_int32x4, v_int64x2, int, s32) inline v_uint32x4 v_load_expand_q(const uchar* ptr) { @@ -840,6 +855,8 @@ inline v_float32x4 v_cvt_f32(const v_int32x4& a) return v_float32x4(vcvtq_f32_s32(a.val)); } +//! @endcond + } #endif diff --git a/modules/hal/include/opencv2/hal/intrin_sse.hpp b/modules/hal/include/opencv2/hal/intrin_sse.hpp index 0c30f7d5b..e237ccd93 100644 --- a/modules/hal/include/opencv2/hal/intrin_sse.hpp +++ b/modules/hal/include/opencv2/hal/intrin_sse.hpp @@ -51,6 +51,8 @@ namespace cv { +//! @cond IGNORED + struct v_uint8x16 { typedef uchar lane_type; @@ -296,6 +298,11 @@ OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_int32x4, s32) OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_uint64x2, u64) OPENCV_HAL_IMPL_SSE_INIT_FROM_FLT(v_int64x2, s64) +inline v_float32x4 v_reinterpret_as_f32(const v_float32x4& a) {return a; } +inline v_float64x2 v_reinterpret_as_f64(const v_float64x2& a) {return a; } +inline v_float32x4 v_reinterpret_as_f32(const v_float64x2& a) {return v_float32x4(_mm_castpd_ps(a.val)); } +inline v_float64x2 v_reinterpret_as_f64(const v_float32x4& a) {return v_float64x2(_mm_castps_pd(a.val)); } + //////////////// PACK /////////////// inline v_uint8x16 v_pack(const v_uint16x8& a, const v_uint16x8& b) { @@ -430,6 +437,17 @@ inline void v_pack_u_store(ushort* ptr, const v_int32x4& a) _mm_storel_epi64((__m128i*)ptr, r); } +template inline +v_uint16x8 v_rshr_pack_u(const v_int32x4& a, const v_int32x4& b) +{ + __m128i delta = _mm_set1_epi32(1 << (n-1)), delta32 = _mm_set1_epi32(32768); + __m128i a1 = _mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(a.val, delta), n), delta32); + __m128i a2 = _mm_sub_epi16(_mm_packs_epi32(a1, a1), _mm_set1_epi16(-32768)); + __m128i b1 = _mm_sub_epi32(_mm_srai_epi32(_mm_add_epi32(b.val, delta), n), delta32); + __m128i b2 = _mm_sub_epi16(_mm_packs_epi32(b1, b1), _mm_set1_epi16(-32768)); + return v_uint16x8(_mm_unpacklo_epi64(a2, b2)); +} + template inline void v_rshr_pack_u_store(ushort* ptr, const v_int32x4& a) { @@ -460,7 +478,7 @@ void v_rshr_pack_store(short* ptr, const v_int32x4& a) { __m128i delta = _mm_set1_epi32(1 << (n-1)); __m128i a1 = _mm_srai_epi32(_mm_add_epi32(a.val, delta), n); - _mm_storel_epi64((__m128i*)ptr, a1); + _mm_storel_epi64((__m128i*)ptr, _mm_packs_epi32(a1, a1)); } @@ -469,7 +487,7 @@ inline v_uint32x4 v_pack(const v_uint64x2& a, const v_uint64x2& b) { __m128i v0 = _mm_unpacklo_epi32(a.val, b.val); // a0 a1 0 0 __m128i v1 = _mm_unpackhi_epi32(a.val, b.val); // b0 b1 0 0 - return v_uint32x4(_mm_unpacklo_epi64(v0, v1)); + return v_uint32x4(_mm_unpacklo_epi32(v0, v1)); } inline void v_pack_store(unsigned* ptr, const v_uint64x2& a) @@ -483,7 +501,7 @@ inline v_int32x4 v_pack(const v_int64x2& a, const v_int64x2& b) { __m128i v0 = _mm_unpacklo_epi32(a.val, b.val); // a0 a1 0 0 __m128i v1 = _mm_unpackhi_epi32(a.val, b.val); // b0 b1 0 0 - return v_int32x4(_mm_unpacklo_epi64(v0, v1)); + return v_int32x4(_mm_unpacklo_epi32(v0, v1)); } inline void v_pack_store(int* ptr, const v_int64x2& a) @@ -501,7 +519,7 @@ v_uint32x4 v_rshr_pack(const v_uint64x2& a, const v_uint64x2& b) __m128i b1 = _mm_srli_epi64(_mm_add_epi64(b.val, delta2.val), n); __m128i v0 = _mm_unpacklo_epi32(a1, b1); // a0 a1 0 0 __m128i v1 = _mm_unpackhi_epi32(a1, b1); // b0 b1 0 0 - return v_uint32x4(_mm_unpacklo_epi64(v0, v1)); + return v_uint32x4(_mm_unpacklo_epi32(v0, v1)); } template inline @@ -534,7 +552,7 @@ v_int32x4 v_rshr_pack(const v_int64x2& a, const v_int64x2& b) __m128i b1 = v_srai_epi64(_mm_add_epi64(b.val, delta2.val), n); __m128i v0 = _mm_unpacklo_epi32(a1, b1); // a0 a1 0 0 __m128i v1 = _mm_unpackhi_epi32(a1, b1); // b0 b1 0 0 - return v_int32x4(_mm_unpacklo_epi64(v0, v1)); + return v_int32x4(_mm_unpacklo_epi32(v0, v1)); } template inline @@ -630,8 +648,8 @@ inline void v_mul_expand(const v_int16x8& a, const v_int16x8& b, { __m128i v0 = _mm_mullo_epi16(a.val, b.val); __m128i v1 = _mm_mulhi_epi16(a.val, b.val); - c.val = _mm_unpacklo_epi32(v0, v1); - d.val = _mm_unpackhi_epi32(v0, v1); + c.val = _mm_unpacklo_epi16(v0, v1); + d.val = _mm_unpackhi_epi16(v0, v1); } inline void v_mul_expand(const v_uint16x8& a, const v_uint16x8& b, @@ -639,8 +657,8 @@ inline void v_mul_expand(const v_uint16x8& a, const v_uint16x8& b, { __m128i v0 = _mm_mullo_epi16(a.val, b.val); __m128i v1 = _mm_mulhi_epu16(a.val, b.val); - c.val = _mm_unpacklo_epi32(v0, v1); - d.val = _mm_unpackhi_epi32(v0, v1); + c.val = _mm_unpacklo_epi16(v0, v1); + d.val = _mm_unpackhi_epi16(v0, v1); } inline void v_mul_expand(const v_uint32x4& a, const v_uint32x4& b, @@ -869,6 +887,18 @@ inline _Tpuvec v_absdiff(const _Tpsvec& a, const _Tpsvec& b) \ OPENCV_HAL_IMPL_SSE_ABSDIFF_8_16(v_uint8x16, v_int8x16, 8, (int)0x80808080) OPENCV_HAL_IMPL_SSE_ABSDIFF_8_16(v_uint16x8, v_int16x8, 16, (int)0x80008000) +inline v_uint32x4 v_absdiff(const v_uint32x4& a, const v_uint32x4& b) +{ + return v_max(a, b) - v_min(a, b); +} + +inline v_uint32x4 v_absdiff(const v_int32x4& a, const v_int32x4& b) +{ + __m128i d = _mm_sub_epi32(a.val, b.val); + __m128i m = _mm_cmpgt_epi32(b.val, a.val); + return v_uint32x4(_mm_sub_epi32(_mm_xor_si128(d, m), m)); +} + #define OPENCV_HAL_IMPL_SSE_MISC_FLT_OP(_Tpvec, _Tp, _Tpreg, suffix, absmask_vec) \ inline _Tpvec v_absdiff(const _Tpvec& a, const _Tpvec& b) \ { \ @@ -1047,8 +1077,8 @@ OPENCV_HAL_IMPL_SSE_SELECT(v_uint16x8, si128) OPENCV_HAL_IMPL_SSE_SELECT(v_int16x8, si128) OPENCV_HAL_IMPL_SSE_SELECT(v_uint32x4, si128) OPENCV_HAL_IMPL_SSE_SELECT(v_int32x4, si128) -OPENCV_HAL_IMPL_SSE_SELECT(v_uint64x2, si128) -OPENCV_HAL_IMPL_SSE_SELECT(v_int64x2, si128) +// OPENCV_HAL_IMPL_SSE_SELECT(v_uint64x2, si128) +// OPENCV_HAL_IMPL_SSE_SELECT(v_int64x2, si128) OPENCV_HAL_IMPL_SSE_SELECT(v_float32x4, ps) OPENCV_HAL_IMPL_SSE_SELECT(v_float64x2, pd) @@ -1257,7 +1287,7 @@ inline void v_load_deinterleave(const uchar* ptr, v_uint8x16& a, v_uint8x16& b, __m128i v0 = _mm_unpacklo_epi8(u0, u2); // a0 a8 b0 b8 ... __m128i v1 = _mm_unpackhi_epi8(u0, u2); // a2 a10 b2 b10 ... __m128i v2 = _mm_unpacklo_epi8(u1, u3); // a4 a12 b4 b12 ... - __m128i v3 = _mm_unpackhi_epi8(u1, u3); // a6 a14 b4 b14 ... + __m128i v3 = _mm_unpackhi_epi8(u1, u3); // a6 a14 b6 b14 ... u0 = _mm_unpacklo_epi8(v0, v2); // a0 a4 a8 a12 ... u1 = _mm_unpacklo_epi8(v1, v3); // a2 a6 a10 a14 ... @@ -1266,13 +1296,13 @@ inline void v_load_deinterleave(const uchar* ptr, v_uint8x16& a, v_uint8x16& b, v0 = _mm_unpacklo_epi8(u0, u1); // a0 a2 a4 a6 ... v1 = _mm_unpacklo_epi8(u2, u3); // a1 a3 a5 a7 ... - v2 = _mm_unpackhi_epi8(u0, u1); // b0 b2 b4 b6 ... - v3 = _mm_unpackhi_epi8(u2, u3); // b1 b3 b5 b7 ... + v2 = _mm_unpackhi_epi8(u0, u1); // c0 c2 c4 c6 ... + v3 = _mm_unpackhi_epi8(u2, u3); // c1 c3 c5 c7 ... a.val = _mm_unpacklo_epi8(v0, v1); - b.val = _mm_unpacklo_epi8(v2, v3); - c.val = _mm_unpackhi_epi8(v0, v1); - d.val = _mm_unpacklo_epi8(v2, v3); + b.val = _mm_unpackhi_epi8(v0, v1); + c.val = _mm_unpacklo_epi8(v2, v3); + d.val = _mm_unpackhi_epi8(v2, v3); } inline void v_load_deinterleave(const ushort* ptr, v_uint16x8& a, v_uint16x8& b, v_uint16x8& c) @@ -1560,6 +1590,8 @@ inline v_float64x2 v_cvt_f64(const v_float32x4& a) return v_float64x2(_mm_cvtps_pd(a.val)); } +//! @endcond + } #endif diff --git a/modules/hal/test/test_intrin.cpp b/modules/hal/test/test_intrin.cpp new file mode 100644 index 000000000..681fe3fd0 --- /dev/null +++ b/modules/hal/test/test_intrin.cpp @@ -0,0 +1,864 @@ +#include "test_intrin_utils.hpp" +#include + +using namespace cv; + +template struct TheTest +{ + typedef typename R::lane_type LaneType; + + TheTest & test_loadstore() + { + AlignedData data; + AlignedData out; + + // check if addresses are aligned and unaligned respectively + EXPECT_EQ((size_t)0, (size_t)&data.a.d % 16); + EXPECT_NE((size_t)0, (size_t)&data.u.d % 16); + EXPECT_EQ((size_t)0, (size_t)&out.a.d % 16); + EXPECT_NE((size_t)0, (size_t)&out.u.d % 16); + + // check some initialization methods + R r1 = data.a; + R r2 = v_load(data.u.d); + R r3 = v_load_aligned(data.a.d); + R r4(r2); + EXPECT_EQ(data.a[0], r1.get0()); + EXPECT_EQ(data.u[0], r2.get0()); + EXPECT_EQ(data.a[0], r3.get0()); + EXPECT_EQ(data.u[0], r4.get0()); + + // check some store methods + out.u.clear(); + out.a.clear(); + v_store(out.u.d, r1); + v_store_aligned(out.a.d, r2); + EXPECT_EQ(data.a, out.a); + EXPECT_EQ(data.u, out.u); + + // check more store methods + Data d, res(0); + R r5 = d; + v_store_high(res.mid(), r5); + v_store_low(res.d, r5); + EXPECT_EQ(d, res); + + // check halves load correctness + res.clear(); + R r6 = v_load_halves(d.d, d.mid()); + v_store(res.d, r6); + EXPECT_EQ(d, res); + + // zero, all + Data resZ = RegTrait::zero(); + Data resV = RegTrait::all(8); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ((LaneType)0, resZ[i]); + EXPECT_EQ((LaneType)8, resV[i]); + } + + // reinterpret_as + v_uint8x16 vu8 = v_reinterpret_as_u8(r1); out.a.clear(); v_store((uchar*)out.a.d, vu8); EXPECT_EQ(data.a, out.a); + v_int8x16 vs8 = v_reinterpret_as_s8(r1); out.a.clear(); v_store((schar*)out.a.d, vs8); EXPECT_EQ(data.a, out.a); + v_uint16x8 vu16 = v_reinterpret_as_u16(r1); out.a.clear(); v_store((ushort*)out.a.d, vu16); EXPECT_EQ(data.a, out.a); + v_int16x8 vs16 = v_reinterpret_as_s16(r1); out.a.clear(); v_store((short*)out.a.d, vs16); EXPECT_EQ(data.a, out.a); + v_uint32x4 vu32 = v_reinterpret_as_u32(r1); out.a.clear(); v_store((unsigned*)out.a.d, vu32); EXPECT_EQ(data.a, out.a); + v_int32x4 vs32 = v_reinterpret_as_s32(r1); out.a.clear(); v_store((int*)out.a.d, vs32); EXPECT_EQ(data.a, out.a); + v_uint64x2 vu64 = v_reinterpret_as_u64(r1); out.a.clear(); v_store((uint64*)out.a.d, vu64); EXPECT_EQ(data.a, out.a); + v_int64x2 vs64 = v_reinterpret_as_s64(r1); out.a.clear(); v_store((int64*)out.a.d, vs64); EXPECT_EQ(data.a, out.a); + v_float32x4 vf32 = v_reinterpret_as_f32(r1); out.a.clear(); v_store((float*)out.a.d, vf32); EXPECT_EQ(data.a, out.a); +#if CV_SIMD128_64F + v_float64x2 vf64 = v_reinterpret_as_f64(r1); out.a.clear(); v_store((double*)out.a.d, vf64); EXPECT_EQ(data.a, out.a); +#endif + + return *this; + } + + TheTest & test_interleave() + { + Data data1, data2, data3, data4; + data2 += 20; + data3 += 40; + data4 += 60; + + + R a = data1, b = data2, c = data3; + R d = data1, e = data2, f = data3, g = data4; + + LaneType buf3[R::nlanes * 3]; + LaneType buf4[R::nlanes * 4]; + + v_store_interleave(buf3, a, b, c); + v_store_interleave(buf4, d, e, f, g); + + Data z(0); + a = b = c = d = e = f = g = z; + + v_load_deinterleave(buf3, a, b, c); + v_load_deinterleave(buf4, d, e, f, g); + + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(data1, Data(a)); + EXPECT_EQ(data2, Data(b)); + EXPECT_EQ(data3, Data(c)); + + EXPECT_EQ(data1, Data(d)); + EXPECT_EQ(data2, Data(e)); + EXPECT_EQ(data3, Data(f)); + EXPECT_EQ(data4, Data(g)); + } + + return *this; + } + + // v_expand and v_load_expand + TheTest & test_expand() + { + typedef typename RegTrait::w_reg Rx2; + Data dataA; + R a = dataA; + + Data resB = v_load_expand(dataA.d); + + Rx2 c, d; + v_expand(a, c, d); + + Data resC = c, resD = d; + const int n = Rx2::nlanes; + for (int i = 0; i < n; ++i) + { + EXPECT_EQ(dataA[i], resB[i]); + EXPECT_EQ(dataA[i], resC[i]); + EXPECT_EQ(dataA[i + n], resD[i]); + } + + return *this; + } + + TheTest & test_expand_q() + { + typedef typename RegTrait::q_reg Rx4; + Data data; + Data out = v_load_expand_q(data.d); + const int n = Rx4::nlanes; + for (int i = 0; i < n; ++i) + EXPECT_EQ(data[i], out[i]); + + return *this; + } + + TheTest & test_addsub() + { + Data dataA, dataB; + dataB.reverse(); + R a = dataA, b = dataB; + + Data resC = a + b, resD = a - b; + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(saturate_cast(dataA[i] + dataB[i]), resC[i]); + EXPECT_EQ(saturate_cast(dataA[i] - dataB[i]), resD[i]); + } + + return *this; + } + + TheTest & test_addsub_wrap() + { + Data dataA, dataB; + dataB.reverse(); + R a = dataA, b = dataB; + + Data resC = v_add_wrap(a, b), + resD = v_sub_wrap(a, b); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ((LaneType)(dataA[i] + dataB[i]), resC[i]); + EXPECT_EQ((LaneType)(dataA[i] - dataB[i]), resD[i]); + } + return *this; + } + + TheTest & test_mul() + { + Data dataA, dataB; + dataB.reverse(); + R a = dataA, b = dataB; + + Data resC = a * b; + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] * dataB[i], resC[i]); + } + + return *this; + } + + TheTest & test_div() + { + Data dataA, dataB; + dataB.reverse(); + R a = dataA, b = dataB; + + Data resC = a / b; + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] / dataB[i], resC[i]); + } + + return *this; + } + + TheTest & test_mul_expand() + { + typedef typename RegTrait::w_reg Rx2; + Data dataA, dataB(2); + R a = dataA, b = dataB; + Rx2 c, d; + + v_mul_expand(a, b, c, d); + + Data resC = c, resD = d; + const int n = R::nlanes / 2; + for (int i = 0; i < n; ++i) + { + EXPECT_EQ((typename Rx2::lane_type)dataA[i] * dataB[i], resC[i]); + EXPECT_EQ((typename Rx2::lane_type)dataA[i + n] * dataB[i + n], resD[i]); + } + + return *this; + } + + template + TheTest & test_shift() + { + Data dataA; + R a = dataA; + + Data resB = a << s, resC = v_shl(a), resD = a >> s, resE = v_shr(a); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] << s, resB[i]); + EXPECT_EQ(dataA[i] << s, resC[i]); + EXPECT_EQ(dataA[i] >> s, resD[i]); + EXPECT_EQ(dataA[i] >> s, resE[i]); + } + return *this; + } + + TheTest & test_cmp() + { + Data dataA, dataB; + dataB.reverse(); + dataB += 1; + R a = dataA, b = dataB; + + Data resC = (a == b); + Data resD = (a != b); + Data resE = (a > b); + Data resF = (a >= b); + Data resG = (a < b); + Data resH = (a <= b); + + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] == dataB[i], resC[i] != 0); + EXPECT_EQ(dataA[i] != dataB[i], resD[i] != 0); + EXPECT_EQ(dataA[i] > dataB[i], resE[i] != 0); + EXPECT_EQ(dataA[i] >= dataB[i], resF[i] != 0); + EXPECT_EQ(dataA[i] < dataB[i], resG[i] != 0); + EXPECT_EQ(dataA[i] <= dataB[i], resH[i] != 0); + } + return *this; + } + + TheTest & test_dot_prod() + { + typedef typename RegTrait::w_reg Rx2; + Data dataA, dataB(2); + R a = dataA, b = dataB; + + Data res = v_dotprod(a, b); + + const int n = R::nlanes / 2; + for (int i = 0; i < n; ++i) + { + EXPECT_EQ(dataA[i*2] * dataB[i*2] + dataA[i*2 + 1] * dataB[i*2 + 1], res[i]); + } + return *this; + } + + TheTest & test_logic() + { + Data dataA, dataB(2); + R a = dataA, b = dataB; + + Data resC = a & b, resD = a | b, resE = a ^ b, resF = ~a; + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] & dataB[i], resC[i]); + EXPECT_EQ(dataA[i] | dataB[i], resD[i]); + EXPECT_EQ(dataA[i] ^ dataB[i], resE[i]); + EXPECT_EQ((LaneType)~dataA[i], resF[i]); + } + + return *this; + } + + TheTest & test_sqrt_abs() + { + Data dataA, dataD; + dataD *= -1.0; + R a = dataA, d = dataD; + + Data resB = v_sqrt(a), resC = v_invsqrt(a), resE = v_abs(d); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_FLOAT_EQ((float)std::sqrt(dataA[i]), (float)resB[i]); + EXPECT_FLOAT_EQ(1/(float)std::sqrt(dataA[i]), (float)resC[i]); + EXPECT_FLOAT_EQ((float)abs(dataA[i]), (float)resE[i]); + } + + return *this; + } + + TheTest & test_min_max() + { + Data dataA, dataB; + dataB.reverse(); + R a = dataA, b = dataB; + + Data resC = v_min(a, b), resD = v_max(a, b); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(std::min(dataA[i], dataB[i]), resC[i]); + EXPECT_EQ(std::max(dataA[i], dataB[i]), resD[i]); + } + + return *this; + } + + TheTest & test_absdiff() + { + typedef typename RegTrait::u_reg Ru; + typedef typename Ru::lane_type u_type; + Data dataA(std::numeric_limits::max()), + dataB(std::numeric_limits::min()); + dataA[0] = (LaneType)-1; + dataB[0] = 1; + dataA[1] = 2; + dataB[1] = (LaneType)-2; + R a = dataA, b = dataB; + Data resC = v_absdiff(a, b); + const u_type mask = std::numeric_limits::is_signed ? (u_type)(1 << (sizeof(u_type)*8 - 1)) : 0; + for (int i = 0; i < Ru::nlanes; ++i) + { + u_type uA = dataA[i] ^ mask; + u_type uB = dataB[i] ^ mask; + EXPECT_EQ(uA > uB ? uA - uB : uB - uA, resC[i]); + } + return *this; + } + + TheTest & test_float_absdiff() + { + Data dataA(std::numeric_limits::max()), + dataB(std::numeric_limits::min()); + dataA[0] = -1; + dataB[0] = 1; + dataA[1] = 2; + dataB[1] = -2; + R a = dataA, b = dataB; + Data resC = v_absdiff(a, b); + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i] > dataB[i] ? dataA[i] - dataB[i] : dataB[i] - dataA[i], resC[i]); + } + return *this; + } + + TheTest & test_reduce() + { + Data dataA; + R a = dataA; + EXPECT_EQ((LaneType)1, v_reduce_min(a)); + EXPECT_EQ((LaneType)R::nlanes, v_reduce_max(a)); + EXPECT_EQ((LaneType)(1 + R::nlanes)*2, v_reduce_sum(a)); + return *this; + } + + TheTest & test_mask() + { + Data dataA, dataB, dataC, dataD(1), dataE(2); + dataA[1] *= (LaneType)-1; + dataC *= (LaneType)-1; + R a = dataA, b = dataB, c = dataC, d = dataD, e = dataE; + + int m = v_signmask(a); + EXPECT_EQ(2, m); + + EXPECT_EQ(false, v_check_all(a)); + EXPECT_EQ(false, v_check_all(b)); + EXPECT_EQ(true, v_check_all(c)); + + EXPECT_EQ(true, v_check_any(a)); + EXPECT_EQ(false, v_check_any(b)); + EXPECT_EQ(true, v_check_any(c)); + + typedef V_TypeTraits Traits; + typedef typename Traits::int_type int_type; + + R f = v_select(b, d, e); + Data resF = f; + for (int i = 0; i < R::nlanes; ++i) + { + int_type m2 = Traits::reinterpret_int(dataB[i]); + EXPECT_EQ((Traits::reinterpret_int(dataD[i]) & m2) + | (Traits::reinterpret_int(dataE[i]) & ~m2), + Traits::reinterpret_int(resF[i])); + } + + return *this; + } + + template + TheTest & test_pack() + { + typedef typename RegTrait::w_reg Rx2; + typedef typename Rx2::lane_type w_type; + Data dataA, dataB; + dataA += std::numeric_limits::is_signed ? -10 : 10; + dataB *= 10; + Rx2 a = dataA, b = dataB; + + Data resC = v_pack(a, b); + Data resD = v_rshr_pack(a, b); + + Data resE(0); + v_pack_store(resE.d, b); + + Data resF(0); + v_rshr_pack_store(resF.d, b); + + const int n = Rx2::nlanes; + const w_type add = (w_type)1 << (s - 1); + for (int i = 0; i < n; ++i) + { + EXPECT_EQ(saturate_cast(dataA[i]), resC[i]); + EXPECT_EQ(saturate_cast(dataB[i]), resC[i + n]); + EXPECT_EQ(saturate_cast((dataA[i] + add) >> s), resD[i]); + EXPECT_EQ(saturate_cast((dataB[i] + add) >> s), resD[i + n]); + EXPECT_EQ(saturate_cast(dataB[i]), resE[i]); + EXPECT_EQ((LaneType)0, resE[i + n]); + EXPECT_EQ(saturate_cast((dataB[i] + add) >> s), resF[i]); + EXPECT_EQ((LaneType)0, resF[i + n]); + } + return *this; + } + + template + TheTest & test_pack_u() + { + typedef typename RegTrait::w_reg Rx2; + typedef typename RegTrait::int_reg Ri2; + typedef typename Ri2::lane_type w_type; + + Data dataA, dataB; + dataA += -10; + dataB *= 10; + Ri2 a = dataA, b = dataB; + + Data resC = v_pack_u(a, b); + Data resD = v_rshr_pack_u(a, b); + + Data resE(0); + v_pack_u_store(resE.d, b); + + Data resF(0); + v_rshr_pack_u_store(resF.d, b); + + const int n = Ri2::nlanes; + const w_type add = (w_type)1 << (s - 1); + for (int i = 0; i < n; ++i) + { + EXPECT_EQ(saturate_cast(dataA[i]), resC[i]); + EXPECT_EQ(saturate_cast(dataB[i]), resC[i + n]); + EXPECT_EQ(saturate_cast((dataA[i] + add) >> s), resD[i]); + EXPECT_EQ(saturate_cast((dataB[i] + add) >> s), resD[i + n]); + EXPECT_EQ(saturate_cast(dataB[i]), resE[i]); + EXPECT_EQ((LaneType)0, resE[i + n]); + EXPECT_EQ(saturate_cast((dataB[i] + add) >> s), resF[i]); + EXPECT_EQ((LaneType)0, resF[i + n]); + } + return *this; + } + + TheTest & test_unpack() + { + Data dataA, dataB; + dataB *= 10; + R a = dataA, b = dataB; + + R c, d, e, f, lo, hi; + v_zip(a, b, c, d); + v_recombine(a, b, e, f); + lo = v_combine_low(a, b); + hi = v_combine_high(a, b); + + Data resC = c, resD = d, resE = e, resF = f, resLo = lo, resHi = hi; + + const int n = R::nlanes/2; + for (int i = 0; i < n; ++i) + { + EXPECT_EQ(dataA[i], resC[i*2]); + EXPECT_EQ(dataB[i], resC[i*2+1]); + EXPECT_EQ(dataA[i+n], resD[i*2]); + EXPECT_EQ(dataB[i+n], resD[i*2+1]); + + EXPECT_EQ(dataA[i], resE[i]); + EXPECT_EQ(dataB[i], resE[i+n]); + EXPECT_EQ(dataA[i+n], resF[i]); + EXPECT_EQ(dataB[i+n], resF[i+n]); + + EXPECT_EQ(dataA[i], resLo[i]); + EXPECT_EQ(dataB[i], resLo[i+n]); + EXPECT_EQ(dataA[i+n], resHi[i]); + EXPECT_EQ(dataB[i+n], resHi[i+n]); + } + + return *this; + } + + template + TheTest & test_extract() + { + Data dataA, dataB; + dataB *= 10; + R a = dataA, b = dataB; + + Data resC = v_extract(a, b); + + for (int i = 0; i < R::nlanes; ++i) + { + if (i + s >= R::nlanes) + EXPECT_EQ(dataB[i - R::nlanes + s], resC[i]); + else + EXPECT_EQ(dataA[i + s], resC[i]); + } + + return *this; + } + + TheTest & test_float_math() + { + typedef typename RegTrait::int_reg Ri; + Data data1, data2, data3; + data1 *= 1.1; + data2 += 10; + R a1 = data1, a2 = data2, a3 = data3; + + Data resB = v_round(a1), + resC = v_trunc(a1), + resD = v_floor(a1), + resE = v_ceil(a1); + + Data resF = v_magnitude(a1, a2), + resG = v_sqr_magnitude(a1, a2), + resH = v_muladd(a1, a2, a3); + + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(cvRound(data1[i]), resB[i]); + EXPECT_EQ((typename Ri::lane_type)data1[i], resC[i]); + EXPECT_EQ(cvFloor(data1[i]), resD[i]); + EXPECT_EQ(cvCeil(data1[i]), resE[i]); + + EXPECT_DOUBLE_EQ(std::sqrt(data1[i]*data1[i] + data2[i]*data2[i]), resF[i]); + EXPECT_DOUBLE_EQ(data1[i]*data1[i] + data2[i]*data2[i], resG[i]); + EXPECT_DOUBLE_EQ(data1[i]*data2[i] + data3[i], resH[i]); + } + + return *this; + } + + TheTest & test_float_cvt32() + { + typedef v_float32x4 Rt; + Data dataA; + dataA *= 1.1; + R a = dataA; + Rt b = v_cvt_f32(a); + Data resB = b; + int n = std::min(Rt::nlanes, R::nlanes); + for (int i = 0; i < n; ++i) + { + EXPECT_EQ((typename Rt::lane_type)dataA[i], resB[i]); + } + return *this; + } + + TheTest & test_float_cvt64() + { +#if CV_SIMD128_64F + typedef v_float64x2 Rt; + Data dataA; + dataA *= 1.1; + R a = dataA; + Rt b = v_cvt_f64(a); + Data resB = b; + int n = std::min(Rt::nlanes, R::nlanes); + for (int i = 0; i < n; ++i) + { + EXPECT_EQ((typename Rt::lane_type)dataA[i], resB[i]); + } +#endif + return *this; + } + + TheTest & test_matmul() + { + Data dataV, dataA, dataB, dataC, dataD; + dataB.reverse(); + dataC += 2; + dataD *= 0.3; + R v = dataV, a = dataA, b = dataB, c = dataC, d = dataD; + + Data res = v_matmul(v, a, b, c, d); + for (int i = 0; i < R::nlanes; ++i) + { + LaneType val = dataV[0] * dataA[i] + + dataV[1] * dataB[i] + + dataV[2] * dataC[i] + + dataV[3] * dataD[i]; + EXPECT_DOUBLE_EQ(val, res[i]); + } + return *this; + } + + TheTest & test_transpose() + { + Data dataA, dataB, dataC, dataD; + dataB *= 5; + dataC *= 10; + dataD *= 15; + R a = dataA, b = dataB, c = dataC, d = dataD; + R e, f, g, h; + v_transpose4x4(a, b, c, d, + e, f, g, h); + + Data res[4] = {e, f, g, h}; + for (int i = 0; i < R::nlanes; ++i) + { + EXPECT_EQ(dataA[i], res[i][0]); + EXPECT_EQ(dataB[i], res[i][1]); + EXPECT_EQ(dataC[i], res[i][2]); + EXPECT_EQ(dataD[i], res[i][3]); + } + return *this; + } + +}; + + +//============= 8-bit integer ===================================================================== + +TEST(hal_intrin, uint8x16) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_expand_q() + .test_addsub() + .test_addsub_wrap() + .test_cmp() + .test_logic() + .test_min_max() + .test_absdiff() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<3>().test_pack<8>() + .test_pack_u<1>().test_pack_u<2>().test_pack_u<3>().test_pack_u<8>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<8>().test_extract<15>() + ; +} + +TEST(hal_intrin, int8x16) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_expand_q() + .test_addsub() + .test_addsub_wrap() + .test_cmp() + .test_logic() + .test_min_max() + .test_absdiff() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<3>().test_pack<8>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<8>().test_extract<15>() + ; +} + +//============= 16-bit integer ===================================================================== + +TEST(hal_intrin, uint16x8) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_addsub() + .test_addsub_wrap() + .test_mul() + .test_mul_expand() + .test_cmp() + .test_shift<1>() + .test_shift<8>() + .test_logic() + .test_min_max() + .test_absdiff() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<7>().test_pack<16>() + .test_pack_u<1>().test_pack_u<2>().test_pack_u<7>().test_pack_u<16>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<4>().test_extract<7>() + ; +} + +TEST(hal_intrin, int16x8) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_addsub() + .test_addsub_wrap() + .test_mul() + .test_mul_expand() + .test_cmp() + .test_shift<1>() + .test_shift<8>() + .test_dot_prod() + .test_logic() + .test_min_max() + .test_absdiff() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<7>().test_pack<16>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<4>().test_extract<7>() + ; +} + +//============= 32-bit integer ===================================================================== + +TEST(hal_intrin, uint32x4) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_addsub() + .test_mul() + .test_mul_expand() + .test_cmp() + .test_shift<1>() + .test_shift<8>() + .test_logic() + .test_min_max() + .test_absdiff() + .test_reduce() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<15>().test_pack<32>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<2>().test_extract<3>() + .test_transpose() + ; +} + +TEST(hal_intrin, int32x4) { + TheTest() + .test_loadstore() + .test_interleave() + .test_expand() + .test_addsub() + .test_mul() + .test_cmp() + .test_shift<1>().test_shift<8>() + .test_logic() + .test_min_max() + .test_absdiff() + .test_reduce() + .test_mask() + .test_pack<1>().test_pack<2>().test_pack<15>().test_pack<32>() + .test_unpack() + .test_extract<0>().test_extract<1>().test_extract<2>().test_extract<3>() + .test_float_cvt32() + .test_float_cvt64() + .test_transpose() + ; +} + +//============= 64-bit integer ===================================================================== + +TEST(hal_intrin, uint64x2) { + TheTest() + .test_loadstore() + .test_addsub() + .test_shift<1>().test_shift<8>() + .test_logic() + .test_extract<0>().test_extract<1>() + ; +} + +TEST(hal_intrin, int64x2) { + TheTest() + .test_loadstore() + .test_addsub() + .test_shift<1>().test_shift<8>() + .test_logic() + .test_extract<0>().test_extract<1>() + ; +} + +//============= Floating point ===================================================================== + +TEST(hal_intrin, float32x4) { + TheTest() + .test_loadstore() + .test_interleave() + .test_addsub() + .test_mul() + .test_div() + .test_cmp() + .test_sqrt_abs() + .test_min_max() + .test_float_absdiff() + .test_reduce() + .test_mask() + .test_unpack() + .test_float_math() + .test_float_cvt64() + .test_matmul() + .test_transpose() + ; +} + +#if CV_SIMD128_64F +TEST(hal_intrin, float64x2) { + TheTest() + .test_loadstore() + .test_addsub() + .test_mul() + .test_div() + .test_cmp() + .test_sqrt_abs() + .test_min_max() + .test_float_absdiff() + .test_mask() + .test_unpack() + .test_float_math() + .test_float_cvt32() + ; +} +#endif diff --git a/modules/hal/test/test_intrin_utils.hpp b/modules/hal/test/test_intrin_utils.hpp new file mode 100644 index 000000000..47473ae46 --- /dev/null +++ b/modules/hal/test/test_intrin_utils.hpp @@ -0,0 +1,234 @@ +#ifndef _TEST_UTILS_HPP_ +#define _TEST_UTILS_HPP_ + +#include "opencv2/hal/intrin.hpp" +#include "opencv2/ts.hpp" +#include +#include + +template struct Data; +template struct initializer; + +template <> struct initializer<16> +{ + template static R init(const Data & d) + { + return R(d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + } +}; + +template <> struct initializer<8> +{ + template static R init(const Data & d) + { + return R(d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7]); + } +}; + +template <> struct initializer<4> +{ + template static R init(const Data & d) + { + return R(d[0], d[1], d[2], d[3]); + } +}; + +template <> struct initializer<2> +{ + template static R init(const Data & d) + { + return R(d[0], d[1]); + } +}; + +//================================================================================================== + +template struct Data +{ + typedef typename R::lane_type LaneType; + Data() + { + for (int i = 0; i < R::nlanes; ++i) + d[i] = (LaneType)(i + 1); + } + Data(LaneType val) + { + fill(val); + } + Data(const R & r) + { + *this = r; + } + operator R () + { + return initializer().init(*this); + } + Data & operator=(const R & r) + { + v_store(d, r); + return *this; + } + template Data & operator*=(T m) + { + for (int i = 0; i < R::nlanes; ++i) + d[i] *= (LaneType)m; + return *this; + } + template Data & operator+=(T m) + { + for (int i = 0; i < R::nlanes; ++i) + d[i] += (LaneType)m; + return *this; + } + void fill(LaneType val) + { + for (int i = 0; i < R::nlanes; ++i) + d[i] = val; + } + void reverse() + { + for (int i = 0; i < R::nlanes / 2; ++i) + std::swap(d[i], d[R::nlanes - i - 1]); + } + const LaneType & operator[](int i) const + { + CV_Assert(i >= 0 && i < R::nlanes); + return d[i]; + } + LaneType & operator[](int i) + { + CV_Assert(i >= 0 && i < R::nlanes); + return d[i]; + } + const LaneType * mid() const + { + return d + R::nlanes / 2; + } + LaneType * mid() + { + return d + R::nlanes / 2; + } + bool operator==(const Data & other) const + { + for (int i = 0; i < R::nlanes; ++i) + if (d[i] != other.d[i]) + return false; + return true; + } + void clear() + { + fill(0); + } + bool isZero() const + { + return isValue(0); + } + bool isValue(uchar val) const + { + for (int i = 0; i < R::nlanes; ++i) + if (d[i] != val) + return false; + return true; + } + + LaneType d[R::nlanes]; +}; + +template struct AlignedData +{ + Data CV_DECL_ALIGNED(16) a; // aligned + char dummy; + Data u; // unaligned +}; + +template std::ostream & operator<<(std::ostream & out, const Data & d) +{ + out << "{ "; + for (int i = 0; i < R::nlanes; ++i) + { + // out << std::hex << +V_TypeTraits::reinterpret_int(d.d[i]); + out << +d.d[i]; + if (i + 1 < R::nlanes) + out << ", "; + } + out << " }"; + return out; +} + +//================================================================================================== + +template struct RegTrait; + +template <> struct RegTrait { + typedef cv::v_uint16x8 w_reg; + typedef cv::v_uint32x4 q_reg; + typedef cv::v_uint8x16 u_reg; + static cv::v_uint8x16 zero() { return cv::v_setzero_u8(); } + static cv::v_uint8x16 all(uchar val) { return cv::v_setall_u8(val); } +}; +template <> struct RegTrait { + typedef cv::v_int16x8 w_reg; + typedef cv::v_int32x4 q_reg; + typedef cv::v_uint8x16 u_reg; + static cv::v_int8x16 zero() { return cv::v_setzero_s8(); } + static cv::v_int8x16 all(schar val) { return cv::v_setall_s8(val); } +}; + +template <> struct RegTrait { + typedef cv::v_uint32x4 w_reg; + typedef cv::v_int16x8 int_reg; + typedef cv::v_uint16x8 u_reg; + static cv::v_uint16x8 zero() { return cv::v_setzero_u16(); } + static cv::v_uint16x8 all(ushort val) { return cv::v_setall_u16(val); } +}; + +template <> struct RegTrait { + typedef cv::v_int32x4 w_reg; + typedef cv::v_uint16x8 u_reg; + static cv::v_int16x8 zero() { return cv::v_setzero_s16(); } + static cv::v_int16x8 all(short val) { return cv::v_setall_s16(val); } +}; + +template <> struct RegTrait { + typedef cv::v_uint64x2 w_reg; + typedef cv::v_int32x4 int_reg; + typedef cv::v_uint32x4 u_reg; + static cv::v_uint32x4 zero() { return cv::v_setzero_u32(); } + static cv::v_uint32x4 all(unsigned val) { return cv::v_setall_u32(val); } +}; + +template <> struct RegTrait { + typedef cv::v_int64x2 w_reg; + typedef cv::v_uint32x4 u_reg; + static cv::v_int32x4 zero() { return cv::v_setzero_s32(); } + static cv::v_int32x4 all(int val) { return cv::v_setall_s32(val); } +}; + +template <> struct RegTrait { + static cv::v_uint64x2 zero() { return cv::v_setzero_u64(); } + static cv::v_uint64x2 all(uint64 val) { return cv::v_setall_u64(val); } +}; + +template <> struct RegTrait { + static cv::v_int64x2 zero() { return cv::v_setzero_s64(); } + static cv::v_int64x2 all(int64 val) { return cv::v_setall_s64(val); } +}; + +template <> struct RegTrait { + typedef cv::v_int32x4 int_reg; + typedef cv::v_float32x4 u_reg; + static cv::v_float32x4 zero() { return cv::v_setzero_f32(); } + static cv::v_float32x4 all(float val) { return cv::v_setall_f32(val); } +}; + +#if CV_SIMD128_64F +template <> struct RegTrait { + typedef cv::v_int32x4 int_reg; + typedef cv::v_float64x2 u_reg; + static cv::v_float64x2 zero() { return cv::v_setzero_f64(); } + static cv::v_float64x2 all(double val) { return cv::v_setall_f64(val); } +}; + +#endif + +#endif diff --git a/modules/hal/test/test_main.cpp b/modules/hal/test/test_main.cpp new file mode 100644 index 000000000..d337a5ba7 --- /dev/null +++ b/modules/hal/test/test_main.cpp @@ -0,0 +1,3 @@ +#include "opencv2/ts.hpp" + +CV_TEST_MAIN("cv") diff --git a/modules/hal/test/test_precomp.hpp b/modules/hal/test/test_precomp.hpp new file mode 100644 index 000000000..387b7ba2b --- /dev/null +++ b/modules/hal/test/test_precomp.hpp @@ -0,0 +1,11 @@ +#ifndef __OPENCV_HAL_TEST_PRECOMP_HPP__ +#define __OPENCV_HAL_TEST_PRECOMP_HPP__ + +#include +#include +#include "opencv2/ts.hpp" +#include "opencv2/hal.hpp" +#include "opencv2/hal/defs.h" +#include "opencv2/hal/intrin.hpp" + +#endif diff --git a/modules/highgui/include/opencv2/highgui.hpp b/modules/highgui/include/opencv2/highgui.hpp index 54dbe7c91..41bd8aff8 100644 --- a/modules/highgui/include/opencv2/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui.hpp @@ -82,42 +82,44 @@ It provides easy interface to: See below the example used to generate the figure: @code int main(int argc, char *argv[]) + { + int value = 50; int value2 = 0; - cvNamedWindow("main1",CV_WINDOW_NORMAL); - cvNamedWindow("main2",CV_WINDOW_AUTOSIZE | CV_GUI_NORMAL); - cvCreateTrackbar( "track1", "main1", &value, 255, NULL);//OK tested - char* nameb1 = "button1"; - char* nameb2 = "button2"; - cvCreateButton(nameb1,callbackButton,nameb1,CV_CHECKBOX,1); + namedWindow("main1",WINDOW_NORMAL); + namedWindow("main2",WINDOW_AUTOSIZE | CV_GUI_NORMAL); + createTrackbar( "track1", "main1", &value, 255, NULL); - cvCreateButton(nameb2,callbackButton,nameb2,CV_CHECKBOX,0); - cvCreateTrackbar( "track2", NULL, &value2, 255, NULL); - cvCreateButton("button5",callbackButton1,NULL,CV_RADIOBOX,0); - cvCreateButton("button6",callbackButton2,NULL,CV_RADIOBOX,1); + String nameb1 = "button1"; + String nameb2 = "button2"; - cvSetMouseCallback( "main2",on_mouse,NULL ); + createButton(nameb1,callbackButton,&nameb1,QT_CHECKBOX,1); + createButton(nameb2,callbackButton,NULL,QT_CHECKBOX,0); + createTrackbar( "track2", NULL, &value2, 255, NULL); + createButton("button5",callbackButton1,NULL,QT_RADIOBOX,0); + createButton("button6",callbackButton2,NULL,QT_RADIOBOX,1); - IplImage* img1 = cvLoadImage("files/flower.jpg"); - IplImage* img2 = cvCreateImage(cvGetSize(img1),8,3); - CvCapture* video = cvCaptureFromFile("files/hockey.avi"); - IplImage* img3 = cvCreateImage(cvGetSize(cvQueryFrame(video)),8,3); + setMouseCallback( "main2",on_mouse,NULL ); - while(cvWaitKey(33) != 27) + Mat img1 = imread("files/flower.jpg"); + VideoCapture video; + video.open("files/hockey.avi"); + + Mat img2,img3; + + while( waitKey(33) != 27 ) { - cvAddS(img1,cvScalarAll(value),img2); - cvAddS(cvQueryFrame(video),cvScalarAll(value2),img3); - cvShowImage("main1",img2); - cvShowImage("main2",img3); + img1.convertTo(img2,-1,1,value); + video >> img3; + + imshow("main1",img2); + imshow("main2",img3); } - cvDestroyAllWindows(); - cvReleaseImage(&img1); - cvReleaseImage(&img2); - cvReleaseImage(&img3); - cvReleaseCapture(&video); + destroyAllWindows(); + return 0; } @endcode @@ -140,7 +142,7 @@ It provides easy interface to: cv::Mat image = cv::imread("Assets/sample.jpg"); cv::Mat converted = cv::Mat(image.rows, image.cols, CV_8UC4); - cvtColor(image, converted, CV_BGR2BGRA); + cv::cvtColor(image, converted, COLOR_BGR2BGRA); cv::imshow(windowName, converted); // this will create window if it hasn't been created before int state = 42; @@ -174,79 +176,100 @@ namespace cv //! Flags for cv::namedWindow enum WindowFlags { - WINDOW_NORMAL = 0x00000000, //!< the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size - WINDOW_AUTOSIZE = 0x00000001, //!< the user cannot resize the window, the size is constrainted by the image displayed - WINDOW_OPENGL = 0x00001000, //!< window with opengl support + WINDOW_NORMAL = 0x00000000, //!< the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size. + WINDOW_AUTOSIZE = 0x00000001, //!< the user cannot resize the window, the size is constrainted by the image displayed. + WINDOW_OPENGL = 0x00001000, //!< window with opengl support. - WINDOW_FULLSCREEN = 1, //!< change the window to fullscreen - WINDOW_FREERATIO = 0x00000100, //!< the image expends as much as it can (no ratio constraint) - WINDOW_KEEPRATIO = 0x00000000 //!< the ratio of the image is respected + WINDOW_FULLSCREEN = 1, //!< change the window to fullscreen. + WINDOW_FREERATIO = 0x00000100, //!< the image expends as much as it can (no ratio constraint). + WINDOW_KEEPRATIO = 0x00000000 //!< the ratio of the image is respected. }; //! Flags for cv::setWindowProperty / cv::getWindowProperty enum WindowPropertyFlags { - WND_PROP_FULLSCREEN = 0, //!< fullscreen property (can be WINDOW_NORMAL or WINDOW_FULLSCREEN) - WND_PROP_AUTOSIZE = 1, //!< autosize property (can be WINDOW_NORMAL or WINDOW_AUTOSIZE) - WND_PROP_ASPECT_RATIO = 2, //!< window's aspect ration (can be set to WINDOW_FREERATIO or WINDOW_KEEPRATIO); - WND_PROP_OPENGL = 3 //!< opengl support + WND_PROP_FULLSCREEN = 0, //!< fullscreen property (can be WINDOW_NORMAL or WINDOW_FULLSCREEN). + WND_PROP_AUTOSIZE = 1, //!< autosize property (can be WINDOW_NORMAL or WINDOW_AUTOSIZE). + WND_PROP_ASPECT_RATIO = 2, //!< window's aspect ration (can be set to WINDOW_FREERATIO or WINDOW_KEEPRATIO). + WND_PROP_OPENGL = 3 //!< opengl support. }; -enum { EVENT_MOUSEMOVE = 0, - EVENT_LBUTTONDOWN = 1, - EVENT_RBUTTONDOWN = 2, - EVENT_MBUTTONDOWN = 3, - EVENT_LBUTTONUP = 4, - EVENT_RBUTTONUP = 5, - EVENT_MBUTTONUP = 6, - EVENT_LBUTTONDBLCLK = 7, - EVENT_RBUTTONDBLCLK = 8, - EVENT_MBUTTONDBLCLK = 9, - EVENT_MOUSEWHEEL = 10, - EVENT_MOUSEHWHEEL = 11 +//! Mouse Events see cv::MouseCallback +enum MouseEventTypes { + EVENT_MOUSEMOVE = 0, //!< indicates that the mouse pointer has moved over the window. + EVENT_LBUTTONDOWN = 1, //!< indicates that the left mouse button is pressed. + EVENT_RBUTTONDOWN = 2, //!< indicates that the right mouse button is pressed. + EVENT_MBUTTONDOWN = 3, //!< indicates that the middle mouse button is pressed. + EVENT_LBUTTONUP = 4, //!< indicates that left mouse button is released. + EVENT_RBUTTONUP = 5, //!< indicates that right mouse button is released. + EVENT_MBUTTONUP = 6, //!< indicates that middle mouse button is released. + EVENT_LBUTTONDBLCLK = 7, //!< indicates that left mouse button is double clicked. + EVENT_RBUTTONDBLCLK = 8, //!< indicates that right mouse button is double clicked. + EVENT_MBUTTONDBLCLK = 9, //!< indicates that middle mouse button is double clicked. + EVENT_MOUSEWHEEL = 10,//!< positive and negative values mean forward and backward scrolling, respectively. + EVENT_MOUSEHWHEEL = 11 //!< positive and negative values mean right and left scrolling, respectively. }; -enum { EVENT_FLAG_LBUTTON = 1, - EVENT_FLAG_RBUTTON = 2, - EVENT_FLAG_MBUTTON = 4, - EVENT_FLAG_CTRLKEY = 8, - EVENT_FLAG_SHIFTKEY = 16, - EVENT_FLAG_ALTKEY = 32 +//! Mouse Event Flags see cv::MouseCallback +enum MouseEventFlags { + EVENT_FLAG_LBUTTON = 1, //!< indicates that the left mouse button is down. + EVENT_FLAG_RBUTTON = 2, //!< indicates that the right mouse button is down. + EVENT_FLAG_MBUTTON = 4, //!< indicates that the middle mouse button is down. + EVENT_FLAG_CTRLKEY = 8, //!< indicates that CTRL Key is pressed. + EVENT_FLAG_SHIFTKEY = 16,//!< indicates that SHIFT Key is pressed. + EVENT_FLAG_ALTKEY = 32 //!< indicates that ALT Key is pressed. }; //! Qt font weight enum QtFontWeights { - QT_FONT_LIGHT = 25, //!< QFont::Light ( Weight of 25 ) - QT_FONT_NORMAL = 50, //!< QFont::Normal ( Weight of 50 ) - QT_FONT_DEMIBOLD = 63, //!< QFont::DemiBold ( Weight of 63 ) - QT_FONT_BOLD = 75, //!< QFont::Bold ( Weight of 75 ) - QT_FONT_BLACK = 87 //!< QFont::Black ( Weight of 87 ) + QT_FONT_LIGHT = 25, //!< Weight of 25 + QT_FONT_NORMAL = 50, //!< Weight of 50 + QT_FONT_DEMIBOLD = 63, //!< Weight of 63 + QT_FONT_BOLD = 75, //!< Weight of 75 + QT_FONT_BLACK = 87 //!< Weight of 87 }; //! Qt font style enum QtFontStyles { - QT_STYLE_NORMAL = 0, //!< QFont::StyleNormal - QT_STYLE_ITALIC = 1, //!< QFont::StyleItalic - QT_STYLE_OBLIQUE = 2 //!< QFont::StyleOblique + QT_STYLE_NORMAL = 0, //!< Normal font. + QT_STYLE_ITALIC = 1, //!< Italic font. + QT_STYLE_OBLIQUE = 2 //!< Oblique font. }; //! Qt "button" type enum QtButtonTypes { - QT_PUSH_BUTTON = 0, //!< Push button - QT_CHECKBOX = 1, //!< Checkbox button - QT_RADIOBOX = 2 //!< Radiobox button + QT_PUSH_BUTTON = 0, //!< Push button. + QT_CHECKBOX = 1, //!< Checkbox button. + QT_RADIOBOX = 2 //!< Radiobox button. }; - +/** @brief Callback function for mouse events. see cv::setMouseCallback +@param event one of the cv::MouseEventTypes constants. +@param x The x-coordinate of the mouse event. +@param y The y-coordinate of the mouse event. +@param flags one of the cv::MouseEventFlags constants. +@param userdata The optional parameter. + */ typedef void (*MouseCallback)(int event, int x, int y, int flags, void* userdata); + +/** @brief Callback function for Trackbar see cv::createTrackbar +@param pos current position of the specified trackbar. +@param userdata The optional parameter. + */ typedef void (*TrackbarCallback)(int pos, void* userdata); + +/** @brief Callback function defined to be called every frame. See cv::setOpenGlDrawCallback +@param userdata The optional parameter. + */ typedef void (*OpenGlDrawCallback)(void* userdata); + +/** @brief Callback function for a button created by cv::createButton +@param state current state of the button. It could be -1 for a push button, 0 or 1 for a check/radio box button. +@param userdata The optional parameter. + */ typedef void (*ButtonCallback)(int state, void* userdata); /** @brief Creates a window. -@param winname Name of the window in the window caption that may be used as a window identifier. -@param flags Flags of the window. The supported flags are: (cv::WindowFlags) - The function namedWindow creates a window that can be used as a placeholder for images and trackbars. Created windows are referred to by their names. @@ -267,14 +290,17 @@ Qt backend supports additional flags: - **CV_GUI_NORMAL or CV_GUI_EXPANDED:** CV_GUI_NORMAL is the old way to draw the window without statusbar and toolbar, whereas CV_GUI_EXPANDED is a new enhanced GUI. By default, flags == WINDOW_AUTOSIZE | WINDOW_KEEPRATIO | CV_GUI_EXPANDED + +@param winname Name of the window in the window caption that may be used as a window identifier. +@param flags Flags of the window. The supported flags are: (cv::WindowFlags) */ CV_EXPORTS_W void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE); -/** @brief Destroys a window. - -@param winname Name of the window to be destroyed. +/** @brief Destroys the specified window. The function destroyWindow destroys the window with the given name. + +@param winname Name of the window to be destroyed. */ CV_EXPORTS_W void destroyWindow(const String& winname); @@ -288,8 +314,6 @@ CV_EXPORTS_W int startWindowThread(); /** @brief Waits for a pressed key. -@param delay Delay in milliseconds. 0 is the special value that means "forever". - The function waitKey waits for a key event infinitely (when \f$\texttt{delay}\leq 0\f$ ) or for delay milliseconds, when it is positive. Since the OS has a minimum time between switching threads, the function will not wait exactly delay ms, it will wait at least delay ms, depending on what else is @@ -306,16 +330,15 @@ takes care of event processing. The function only works if there is at least one HighGUI window created and the window is active. If there are several HighGUI windows, any of them can be active. + +@param delay Delay in milliseconds. 0 is the special value that means "forever". */ CV_EXPORTS_W int waitKey(int delay = 0); /** @brief Displays an image in the specified window. -@param winname Name of the window. -@param mat Image to be shown. - The function imshow displays an image in the specified window. If the window was created with the -WINDOW_AUTOSIZE flag, the image is shown with its original size, however it is still limited by the screen resolution. +cv::WINDOW_AUTOSIZE flag, the image is shown with its original size, however it is still limited by the screen resolution. Otherwise, the image is scaled to fit the window. The function may scale the image, depending on its depth: - If the image is 8-bit unsigned, it is displayed as is. @@ -324,77 +347,81 @@ Otherwise, the image is scaled to fit the window. The function may scale the ima - If the image is 32-bit floating-point, the pixel values are multiplied by 255. That is, the value range [0,1] is mapped to [0,255]. -If window was created with OpenGL support, imshow also support ogl::Buffer , ogl::Texture2D and +If window was created with OpenGL support, cv::imshow also support ogl::Buffer , ogl::Texture2D and cuda::GpuMat as input. -If the window was not created before this function, it is assumed creating a window with WINDOW_AUTOSIZE. +If the window was not created before this function, it is assumed creating a window with cv::WINDOW_AUTOSIZE. If you need to show an image that is bigger than the screen resolution, you will need to call namedWindow("", WINDOW_NORMAL) before the imshow. @note This function should be followed by cv::waitKey function which displays the image for specified -milliseconds. Otherwise, it won't display the image. For example, cv::waitKey(0) will display the window -infinitely until any keypress (it is suitable for image display). cv::waitKey(25) will display a frame +milliseconds. Otherwise, it won't display the image. For example, **waitKey(0)** will display the window +infinitely until any keypress (it is suitable for image display). **waitKey(25)** will display a frame for 25 ms, after which display will be automatically closed. (If you put it in a loop to read videos, it will display the video frame-by-frame) @note -[Windows Backend Only] Pressing Ctrl+C will copy the image to the clipboard. +[__Windows Backend Only__] Pressing Ctrl+C will copy the image to the clipboard. -[Windows Backend Only] Pressing Ctrl+S will show a dialog to save the image. +[__Windows Backend Only__] Pressing Ctrl+S will show a dialog to save the image. +@param winname Name of the window. +@param mat Image to be shown. */ CV_EXPORTS_W void imshow(const String& winname, InputArray mat); /** @brief Resizes window to the specified size -@param winname Window name -@param width The new window width -@param height The new window height - @note - The specified window size is for the image area. Toolbars are not counted. -- Only windows created without WINDOW_AUTOSIZE flag can be resized. +- Only windows created without cv::WINDOW_AUTOSIZE flag can be resized. + +@param winname Window name. +@param width The new window width. +@param height The new window height. */ CV_EXPORTS_W void resizeWindow(const String& winname, int width, int height); /** @brief Moves window to the specified position -@param winname Window name -@param x The new x-coordinate of the window -@param y The new y-coordinate of the window +@param winname Name of the window. +@param x The new x-coordinate of the window. +@param y The new y-coordinate of the window. */ CV_EXPORTS_W void moveWindow(const String& winname, int x, int y); /** @brief Changes parameters of a window dynamically. +The function setWindowProperty enables changing properties of a window. + @param winname Name of the window. @param prop_id Window property to edit. The supported operation flags are: (cv::WindowPropertyFlags) @param prop_value New value of the window property. The supported flags are: (cv::WindowFlags) - -The function setWindowProperty enables changing properties of a window. */ CV_EXPORTS_W void setWindowProperty(const String& winname, int prop_id, double prop_value); /** @brief Updates window title +@param winname Name of the window. +@param title New title. */ CV_EXPORTS_W void setWindowTitle(const String& winname, const String& title); /** @brief Provides parameters of a window. +The function getWindowProperty returns properties of a window. + @param winname Name of the window. @param prop_id Window property to retrieve. The following operation flags are available: (cv::WindowPropertyFlags) -See setWindowProperty to know the meaning of the returned values. - -The function getWindowProperty returns properties of a window. +@sa setWindowProperty */ CV_EXPORTS_W double getWindowProperty(const String& winname, int prop_id); /** @brief Sets mouse handler for the specified window -@param winname Window name +@param winname Name of the window. @param onMouse Mouse callback. See OpenCV samples, such as , on how to specify and use the callback. @@ -402,18 +429,16 @@ use the callback. */ CV_EXPORTS void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0); -/** @brief Gets the mouse-wheel motion delta, when handling mouse-wheel events EVENT_MOUSEWHEEL and -EVENT_MOUSEHWHEEL. - -@param flags The mouse callback flags parameter. +/** @brief Gets the mouse-wheel motion delta, when handling mouse-wheel events cv::EVENT_MOUSEWHEEL and +cv::EVENT_MOUSEHWHEEL. For regular mice with a scroll-wheel, delta will be a multiple of 120. The value 120 corresponds to a one notch rotation of the wheel or the threshold for action to be taken and one such action should occur for each delta. Some high-precision mice with higher-resolution freely-rotating wheels may generate smaller values. -For EVENT_MOUSEWHEEL positive and negative values mean forward and backward scrolling, -respectively. For EVENT_MOUSEHWHEEL, where available, positive and negative values mean right and +For cv::EVENT_MOUSEWHEEL positive and negative values mean forward and backward scrolling, +respectively. For cv::EVENT_MOUSEHWHEEL, where available, positive and negative values mean right and left scrolling, respectively. With the C API, the macro CV_GET_WHEEL_DELTA(flags) can be used alternatively. @@ -421,11 +446,25 @@ With the C API, the macro CV_GET_WHEEL_DELTA(flags) can be used alternatively. @note Mouse-wheel events are currently supported only on Windows. + +@param flags The mouse callback flags parameter. */ CV_EXPORTS int getMouseWheelDelta(int flags); /** @brief Creates a trackbar and attaches it to the specified window. +The function createTrackbar creates a trackbar (a slider or range control) with the specified name +and range, assigns a variable value to be a position synchronized with the trackbar and specifies +the callback function onChange to be called on the trackbar position change. The created trackbar is +displayed in the specified window winname. + +@note + +[__Qt Backend Only__] winname can be empty (or NULL) if the trackbar should be attached to the +control panel. + +Clicking the label of each trackbar enables editing the trackbar values manually. + @param trackbarname Name of the created trackbar. @param winname Name of the window that will be used as a parent of the created trackbar. @param value Optional pointer to an integer variable whose value reflects the position of the @@ -437,19 +476,6 @@ position and the second parameter is the user data (see the next parameter). If the NULL pointer, no callbacks are called, but only value is updated. @param userdata User data that is passed as is to the callback. It can be used to handle trackbar events without using global variables. - -The function createTrackbar creates a trackbar (a slider or range control) with the specified name -and range, assigns a variable value to be a position synchronized with the trackbar and specifies -the callback function onChange to be called on the trackbar position change. The created trackbar is -displayed in the specified window winname. - -@note - -**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar should be attached to the -control panel. - -Clicking the label of each trackbar enables editing the trackbar values manually. - */ CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname, int* value, int count, @@ -458,63 +484,77 @@ CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname, /** @brief Returns the trackbar position. -@param trackbarname Name of the trackbar. -@param winname Name of the window that is the parent of the trackbar. - The function returns the current position of the specified trackbar. @note -**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar is attached to the control +[__Qt Backend Only__] winname can be empty (or NULL) if the trackbar is attached to the control panel. +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of the trackbar. */ CV_EXPORTS_W int getTrackbarPos(const String& trackbarname, const String& winname); /** @brief Sets the trackbar position. -@param trackbarname Name of the trackbar. -@param winname Name of the window that is the parent of trackbar. -@param pos New position. - The function sets the position of the specified trackbar in the specified window. @note -**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar is attached to the control +[__Qt Backend Only__] winname can be empty (or NULL) if the trackbar is attached to the control panel. + +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of trackbar. +@param pos New position. */ CV_EXPORTS_W void setTrackbarPos(const String& trackbarname, const String& winname, int pos); /** @brief Sets the trackbar maximum position. -@param trackbarname Name of the trackbar. -@param winname Name of the window that is the parent of trackbar. -@param maxval New maximum position. - The function sets the maximum position of the specified trackbar in the specified window. @note -**[Qt Backend Only]** winname can be empty (or NULL) if the trackbar is attached to the control +[__Qt Backend Only__] winname can be empty (or NULL) if the trackbar is attached to the control panel. + +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of trackbar. +@param maxval New maximum position. */ CV_EXPORTS_W void setTrackbarMax(const String& trackbarname, const String& winname, int maxval); +/** @brief Sets the trackbar minimum position. + +The function sets the minimum position of the specified trackbar in the specified window. + +@note + +[__Qt Backend Only__] winname can be empty (or NULL) if the trackbar is attached to the control +panel. + +@param trackbarname Name of the trackbar. +@param winname Name of the window that is the parent of trackbar. +@param minval New maximum position. + */ +CV_EXPORTS_W void setTrackbarMin(const String& trackbarname, const String& winname, int minval); + //! @addtogroup highgui_opengl OpenGL support //! @{ +/** @brief Displays OpenGL 2D texture in the specified window. + +@param winname Name of the window. +@param tex OpenGL 2D texture data. + */ CV_EXPORTS void imshow(const String& winname, const ogl::Texture2D& tex); /** @brief Sets a callback function to be called to draw on top of displayed image. -@param winname Name of the window. -@param onOpenGlDraw Pointer to the function to be called every frame. This function should be -prototyped as void Foo(void\*) . -@param userdata Pointer passed to the callback function. *(Optional)* - The function setOpenGlDrawCallback can be used to draw 3D data on the window. See the example of -callback function below: : +callback function below: @code void on_opengl(void* param) { @@ -545,18 +585,23 @@ callback function below: : } } @endcode + +@param winname Name of the window. +@param onOpenGlDraw Pointer to the function to be called every frame. This function should be +prototyped as void Foo(void\*) . +@param userdata Pointer passed to the callback function.(__Optional__) */ CV_EXPORTS void setOpenGlDrawCallback(const String& winname, OpenGlDrawCallback onOpenGlDraw, void* userdata = 0); /** @brief Sets the specified window as current OpenGL context. -@param winname Window name +@param winname Name of the window. */ CV_EXPORTS void setOpenGlContext(const String& winname); -/** @brief Force window to redraw its context and call draw callback ( setOpenGlDrawCallback ). +/** @brief Force window to redraw its context and call draw callback ( See cv::setOpenGlDrawCallback ). -@param winname Window name +@param winname Name of the window. */ CV_EXPORTS void updateWindow(const String& winname); @@ -564,102 +609,103 @@ CV_EXPORTS void updateWindow(const String& winname); //! @addtogroup highgui_qt //! @{ -// Only for Qt +/** @brief QtFont available only for Qt. See cv::fontQt + */ struct QtFont { - const char* nameFont; // Qt: nameFont - Scalar color; // Qt: ColorFont -> cvScalar(blue_component, green_component, red_component[, alpha_component]) - int font_face; // Qt: bool italic - const int* ascii; // font data and metrics + const char* nameFont; //!< Name of the font + Scalar color; //!< Color of the font. Scalar(blue_component, green_component, red_component[, alpha_component]) + int font_face; //!< See cv::QtFontStyles + const int* ascii; //!< font data and metrics const int* greek; const int* cyrillic; float hscale, vscale; - float shear; // slope coefficient: 0 - normal, >0 - italic - int thickness; // Qt: weight - float dx; // horizontal interval between letters - int line_type; // Qt: PointSize + float shear; //!< slope coefficient: 0 - normal, >0 - italic + int thickness; //!< See cv::QtFontWeights + float dx; //!< horizontal interval between letters + int line_type; //!< PointSize }; /** @brief Creates the font to draw a text on an image. +The function fontQt creates a cv::QtFont object. This cv::QtFont is not compatible with putText . + +A basic usage of this function is the following: : +@code + QtFont font = fontQt("Times"); + addText( img1, "Hello World !", Point(50,50), font); +@endcode + @param nameFont Name of the font. The name should match the name of a system font (such as *Times*). If the font is not found, a default one is used. @param pointSize Size of the font. If not specified, equal zero or negative, the point size of the font is set to a system-dependent default value. Generally, this is 12 points. -@param color Color of the font in BGRA where A = 255 is fully transparent. Use the macro CV _ RGB +@param color Color of the font in BGRA where A = 255 is fully transparent. Use the macro CV_RGB for simplicity. -@param weight Font weight. Available operation flags are : (cv::QtFontWeights) You can also specify a positive integer for better control. -@param style Font style. The following operation flags are available: (cv::QtFontStyles) +@param weight Font weight. Available operation flags are : cv::QtFontWeights You can also specify a positive integer for better control. +@param style Font style. Available operation flags are : cv::QtFontStyles @param spacing Spacing between characters. It can be negative or positive. - -The function fontQt creates a QtFont object. This QtFont is not compatible with putText . - -A basic usage of this function is the following: : -@code - QtFont font = fontQt(''Times''); - addText( img1, ``Hello World !'', Point(50,50), font); -@endcode */ CV_EXPORTS QtFont fontQt(const String& nameFont, int pointSize = -1, Scalar color = Scalar::all(0), int weight = QT_FONT_NORMAL, int style = QT_STYLE_NORMAL, int spacing = 0); -/** @brief Creates the font to draw a text on an image. +/** @brief Draws a text on the image. + +The function addText draws *text* on the image *img* using a specific font *font* (see example cv::fontQt +) @param img 8-bit 3-channel image where the text should be drawn. @param text Text to write on an image. @param org Point(x,y) where the text should start on an image. @param font Font to use to draw a text. - -The function addText draws *text* on an image *img* using a specific font *font* (see example cv::fontQt -) */ CV_EXPORTS void addText( const Mat& img, const String& text, Point org, const QtFont& font); /** @brief Displays a text on a window image as an overlay for a specified duration. +The function displayOverlay displays useful information/tips on top of the window for a certain +amount of time *delayms*. The function does not modify the image, displayed in the window, that is, +after the specified delay the original content of the window is restored. + @param winname Name of the window. @param text Overlay text to write on a window image. @param delayms The period (in milliseconds), during which the overlay text is displayed. If this function is called before the previous overlay text timed out, the timer is restarted and the text is updated. If this value is zero, the text never disappears. - -The function displayOverlay displays useful information/tips on top of the window for a certain -amount of time *delayms*. The function does not modify the image, displayed in the window, that is, -after the specified delay the original content of the window is restored. */ CV_EXPORTS void displayOverlay(const String& winname, const String& text, int delayms = 0); /** @brief Displays a text on the window statusbar during the specified period of time. +The function displayStatusBar displays useful information/tips on top of the window for a certain +amount of time *delayms* . This information is displayed on the window statusbar (the window must be +created with the CV_GUI_EXPANDED flags). + @param winname Name of the window. @param text Text to write on the window statusbar. @param delayms Duration (in milliseconds) to display the text. If this function is called before the previous text timed out, the timer is restarted and the text is updated. If this value is zero, the text never disappears. - -The function displayStatusBar displays useful information/tips on top of the window for a certain -amount of time *delayms* . This information is displayed on the window statusbar (the window must be -created with the CV_GUI_EXPANDED flags). */ CV_EXPORTS void displayStatusBar(const String& winname, const String& text, int delayms = 0); /** @brief Saves parameters of the specified window. -@param windowName Name of the window. - The function saveWindowParameters saves size, location, flags, trackbars value, zoom and panning -location of the window window_name . +location of the window windowName. + +@param windowName Name of the window. */ CV_EXPORTS void saveWindowParameters(const String& windowName); /** @brief Loads parameters of the specified window. -@param windowName Name of the window. - The function loadWindowParameters loads size, location, flags, trackbars value, zoom and panning -location of the window window_name . +location of the window windowName. + +@param windowName Name of the window. */ CV_EXPORTS void loadWindowParameters(const String& windowName); @@ -669,21 +715,11 @@ CV_EXPORTS void stopLoop(); /** @brief Attaches a button to the control panel. -@param bar_name - Name of the button. -@param on_change Pointer to the function to be called every time the button changes its state. -This function should be prototyped as void Foo(int state,\*void); . *state* is the current state -of the button. It could be -1 for a push button, 0 or 1 for a check/radio box button. -@param userdata Pointer passed to the callback function. -@param type Optional type of the button. Available types are: (cv::QtButtonTypes) -@param initial_button_state Default state of the button. Use for checkbox and radiobox. Its -value could be 0 or 1. *(Optional)* - The function createButton attaches a button to the control panel. Each button is added to a buttonbar to the right of the last button. A new buttonbar is created if nothing was attached to the control panel before, or if the last element attached to the control panel was a trackbar. -See below various examples of the createButton function call: : +See below various examples of the cv::createButton function call: : @code createButton(NULL,callbackButton);//create a push button "button 0", that will call callbackButton. createButton("button2",callbackButton,NULL,QT_CHECKBOX,0); @@ -691,6 +727,15 @@ See below various examples of the createButton function call: : createButton("button5",callbackButton1,NULL,QT_RADIOBOX); createButton("button6",callbackButton2,NULL,QT_PUSH_BUTTON,1); @endcode + +@param bar_name Name of the button. +@param on_change Pointer to the function to be called every time the button changes its state. +This function should be prototyped as void Foo(int state,\*void); . *state* is the current state +of the button. It could be -1 for a push button, 0 or 1 for a check/radio box button. +@param userdata Pointer passed to the callback function. +@param type Optional type of the button. Available types are: (cv::QtButtonTypes) +@param initial_button_state Default state of the button. Use for checkbox and radiobox. Its +value could be 0 or 1. (__Optional__) */ CV_EXPORTS int createButton( const String& bar_name, ButtonCallback on_change, void* userdata = 0, int type = QT_PUSH_BUTTON, diff --git a/modules/highgui/include/opencv2/highgui/highgui_c.h b/modules/highgui/include/opencv2/highgui/highgui_c.h index 46d4c9549..47fdb84a4 100644 --- a/modules/highgui/include/opencv2/highgui/highgui_c.h +++ b/modules/highgui/include/opencv2/highgui/highgui_c.h @@ -166,6 +166,7 @@ CVAPI(int) cvCreateTrackbar2( const char* trackbar_name, const char* window_name CVAPI(int) cvGetTrackbarPos( const char* trackbar_name, const char* window_name ); CVAPI(void) cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos ); CVAPI(void) cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval); +CVAPI(void) cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval); enum { diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index 03d446dd0..c879c4130 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -216,6 +216,11 @@ void cv::setTrackbarMax(const String& trackbarName, const String& winName, int m cvSetTrackbarMax(trackbarName.c_str(), winName.c_str(), maxval); } +void cv::setTrackbarMin(const String& trackbarName, const String& winName, int minval) +{ + cvSetTrackbarMin(trackbarName.c_str(), winName.c_str(), minval); +} + int cv::getTrackbarPos( const String& trackbarName, const String& winName ) { return cvGetTrackbarPos(trackbarName.c_str(), winName.c_str()); @@ -589,6 +594,11 @@ CV_IMPL void cvSetTrackbarMax(const char*, const char*, int) CV_NO_GUI_ERROR( "cvSetTrackbarMax" ); } +CV_IMPL void cvSetTrackbarMin(const char*, const char*, int) +{ + CV_NO_GUI_ERROR( "cvSetTrackbarMin" ); +} + CV_IMPL void* cvGetWindowHandle( const char* ) { CV_NO_GUI_ERROR( "cvGetWindowHandle" ); diff --git a/modules/highgui/src/window_QT.cpp b/modules/highgui/src/window_QT.cpp index a01dcd342..925bc222d 100644 --- a/modules/highgui/src/window_QT.cpp +++ b/modules/highgui/src/window_QT.cpp @@ -664,12 +664,29 @@ CV_IMPL void cvSetTrackbarMax(const char* name_bar, const char* window_name, int QPointer t = icvFindTrackBarByName(name_bar, window_name); if (t) { + int minval = t->slider->minimum(); + maxval = (maxval>minval)?maxval:minval; t->slider->setMaximum(maxval); } } } +CV_IMPL void cvSetTrackbarMin(const char* name_bar, const char* window_name, int minval) +{ + if (minval >= 0) + { + QPointer t = icvFindTrackBarByName(name_bar, window_name); + if (t) + { + int maxval = t->slider->maximum(); + minval = (maxvalslider->setMinimum(minval); + } + } +} + + /* assign callback for mouse events */ CV_IMPL void cvSetMouseCallback(const char* window_name, CvMouseCallback on_mouse, void* param) { diff --git a/modules/highgui/src/window_QT.h b/modules/highgui/src/window_QT.h index 20cd4142a..c0769dcc9 100644 --- a/modules/highgui/src/window_QT.h +++ b/modules/highgui/src/window_QT.h @@ -73,7 +73,6 @@ #include #include #include -#include #include #include #include diff --git a/modules/highgui/src/window_cocoa.mm b/modules/highgui/src/window_cocoa.mm index 56baded39..4ab1e360e 100644 --- a/modules/highgui/src/window_cocoa.mm +++ b/modules/highgui/src/window_cocoa.mm @@ -62,6 +62,7 @@ CV_IMPL void cvSetMouseCallback( const char* name, CvMouseCallback function, voi CV_IMPL int cvGetTrackbarPos( const char* trackbar_name, const char* window_name ) {return 0;} CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name, int pos) {} CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval) {} +CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) {} CV_IMPL void* cvGetWindowHandle( const char* name ) {return NULL;} CV_IMPL const char* cvGetWindowName( void* window_handle ) {return NULL;} CV_IMPL int cvNamedWindow( const char* name, int flags ) {return 0; } @@ -426,7 +427,7 @@ CV_IMPL void cvSetTrackbarPos(const char* trackbar_name, const char* window_name CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name, int maxval) { - CV_FUNCNAME("cvSetTrackbarPos"); + CV_FUNCNAME("cvSetTrackbarMax"); CVWindow *window = nil; CVSlider *slider = nil; @@ -445,6 +446,8 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]]; if(slider) { if(maxval >= 0) { + int minval = [[slider slider] minValue]; + maxval = (minval>maxval)?minval:maxval; [[slider slider] setMaxValue:maxval]; } } @@ -454,6 +457,37 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name __END__; } +CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) +{ + CV_FUNCNAME("cvSetTrackbarMin"); + + CVWindow *window = nil; + CVSlider *slider = nil; + NSAutoreleasePool* localpool5 = nil; + + __BEGIN__; + if(trackbar_name == NULL || window_name == NULL) + CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name" ); + + if (localpool5 != nil) [localpool5 drain]; + localpool5 = [[NSAutoreleasePool alloc] init]; + + window = cvGetWindow(window_name); + if(window) { + slider = [[window sliders] valueForKey:[NSString stringWithFormat:@"%s", trackbar_name]]; + if(slider) { + if(minval >= 0) { + int maxval = [[slider slider] maxValue]; + minval = (minvaloriginal_image != NULL) { - *minimal_width = image_widget->flags & CV_WINDOW_AUTOSIZE ? + *minimal_width = (image_widget->flags & CV_WINDOW_AUTOSIZE) != CV_WINDOW_AUTOSIZE ? gdk_window_get_width(gtk_widget_get_window(widget)) : image_widget->original_image->cols; } else { @@ -270,7 +270,7 @@ cvImageWidget_get_preferred_height (GtkWidget *widget, gint *minimal_height, gin CvImageWidget * image_widget = CV_IMAGE_WIDGET( widget ); if(image_widget->original_image != NULL) { - *minimal_height = image_widget->flags & CV_WINDOW_AUTOSIZE ? + *minimal_height = (image_widget->flags & CV_WINDOW_AUTOSIZE) != CV_WINDOW_AUTOSIZE ? gdk_window_get_height(gtk_widget_get_window(widget)) : image_widget->original_image->rows; } else { @@ -508,6 +508,7 @@ typedef struct CvTrackbar int* data; int pos; int maxval; + int minval; CvTrackbarCallback notify; CvTrackbarCallback2 notify2; void* userdata; @@ -1607,7 +1608,7 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name trackbar = icvFindTrackbarByName(window, trackbar_name); if (trackbar) { - trackbar->maxval = maxval; + trackbar->maxval = (trackbar->minval>maxval)?trackbar->minval:maxval; CV_LOCK_MUTEX(); @@ -1622,6 +1623,43 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name } +CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) +{ + CV_FUNCNAME("cvSetTrackbarMin"); + + __BEGIN__; + + if (minval >= 0) + { + CvWindow* window = 0; + CvTrackbar* trackbar = 0; + + if (trackbar_name == 0 || window_name == 0) + { + CV_ERROR( CV_StsNullPtr, "NULL trackbar or window name"); + } + + window = icvFindWindowByName( window_name ); + if (window) + { + trackbar = icvFindTrackbarByName(window, trackbar_name); + if (trackbar) + { + trackbar->minval = (minvalmaxval)?minval:trackbar->maxval; + + CV_LOCK_MUTEX(); + + gtk_range_set_range(GTK_RANGE(trackbar->widget), minval, trackbar->maxval); + + CV_UNLOCK_MUTEX(); + } + } + } + + __END__; +} + + CV_IMPL void* cvGetWindowHandle( const char* window_name ) { void* widget = 0; diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 08a137ab2..cadbdf706 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -138,6 +138,7 @@ typedef struct CvTrackbar int* data; int pos; int maxval; + int minval; void (*notify)(int); void (*notify2)(int, void*); void* userdata; @@ -1909,7 +1910,8 @@ static void showSaveDialog(CvWindow* window) if (GetSaveFileName(&ofn)) { - cv::Mat tmp; cv::flip(cv::Mat(sz.cy, sz.cx, CV_8UC(channels), data), tmp, 0); + cv::Mat tmp; + cv::flip(cv::Mat(sz.cy, sz.cx, CV_8UC(channels), data, (sz.cx * channels + 3) & -4), tmp, 0); cv::imwrite(szFileName, tmp); } } @@ -2324,7 +2326,7 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name if (trackbar) { // The position will be min(pos, maxval). - trackbar->maxval = maxval; + trackbar->maxval = (trackbar->minval>maxval)?trackbar->minval:maxval; SendMessage(trackbar->hwnd, TBM_SETRANGEMAX, (WPARAM)TRUE, (LPARAM)maxval); } } @@ -2334,6 +2336,38 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name } +CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) +{ + CV_FUNCNAME( "cvSetTrackbarMin" ); + + __BEGIN__; + + if (minval >= 0) + { + CvWindow* window = 0; + CvTrackbar* trackbar = 0; + if (trackbar_name == 0 || window_name == 0) + { + CV_ERROR(CV_StsNullPtr, "NULL trackbar or window name"); + } + + window = icvFindWindowByName(window_name); + if (window) + { + trackbar = icvFindTrackbarByName(window, trackbar_name); + if (trackbar) + { + // The position will be min(pos, maxval). + trackbar->minval = (minvalmaxval)?minval:trackbar->maxval; + SendMessage(trackbar->hwnd, TBM_SETRANGEMIN, (WPARAM)TRUE, (LPARAM)minval); + } + } + } + + __END__; +} + + CV_IMPL void* cvGetWindowHandle( const char* window_name ) { void* hwnd = 0; diff --git a/modules/highgui/src/window_winrt.cpp b/modules/highgui/src/window_winrt.cpp index ba81b51c6..4bd3e1ab2 100644 --- a/modules/highgui/src/window_winrt.cpp +++ b/modules/highgui/src/window_winrt.cpp @@ -170,6 +170,22 @@ CV_IMPL void cvSetTrackbarMax(const char* trackbar_name, const char* window_name } } +CV_IMPL void cvSetTrackbarMin(const char* trackbar_name, const char* window_name, int minval) +{ + CV_FUNCNAME("cvSetTrackbarMin"); + + if (minval >= 0) + { + if (trackbar_name == 0 || window_name == 0) + CV_ERROR(CV_StsNullPtr, "NULL trackbar or window name"); + + CvTrackbar* trackbar = HighguiBridge::getInstance().findTrackbarByName(trackbar_name, window_name); + + if (trackbar) + trackbar->setMinPosition(minval); + } +} + CV_IMPL int cvGetTrackbarPos(const char* trackbar_name, const char* window_name) { int pos = -1; diff --git a/modules/highgui/src/window_winrt_bridge.cpp b/modules/highgui/src/window_winrt_bridge.cpp index 60421d681..e0818eafb 100644 --- a/modules/highgui/src/window_winrt_bridge.cpp +++ b/modules/highgui/src/window_winrt_bridge.cpp @@ -171,12 +171,23 @@ void CvTrackbar::setPosition(double pos) void CvTrackbar::setMaxPosition(double pos) { - if (pos < 0) - pos = 0; + //slider->Minimum is initialized with 0 + if (pos < slider->Minimum) + pos = slider->Minimum; slider->Maximum = pos; } +void CvTrackbar::setMinPosition(double pos) +{ + if (pos < 0) + pos = 0; + //Min is always less than Max. + if ((pos > slider->Maximum) + pos = slider->Maximum; + slider->Minimum = pos; +} + void CvTrackbar::setSlider(Slider^ slider) { if (slider) this->slider = slider; @@ -192,6 +203,11 @@ double CvTrackbar::getMaxPosition() return slider->Maximum; } +double CvTrackbar::getMinPosition() +{ + return slider->Minimum; +} + Slider^ CvTrackbar::getSlider() { return slider; diff --git a/modules/highgui/src/window_winrt_bridge.hpp b/modules/highgui/src/window_winrt_bridge.hpp index d19dd29c8..25f4aef8e 100644 --- a/modules/highgui/src/window_winrt_bridge.hpp +++ b/modules/highgui/src/window_winrt_bridge.hpp @@ -151,6 +151,8 @@ public: void setPosition(double pos); double getMaxPosition(); void setMaxPosition(double pos); + double getMinPosition(); + void setMinPosition(double pos); Slider^ getSlider(); void setSlider(Slider^ pos); diff --git a/modules/imgcodecs/CMakeLists.txt b/modules/imgcodecs/CMakeLists.txt index 6d565217a..7b3fc0bd7 100644 --- a/modules/imgcodecs/CMakeLists.txt +++ b/modules/imgcodecs/CMakeLists.txt @@ -61,6 +61,8 @@ list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.hpp) list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/bitstrm.cpp) list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.hpp) list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/rgbe.cpp) +list(APPEND grfmt_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/jpeg_exif.hpp) +list(APPEND grfmt_srcs ${CMAKE_CURRENT_LIST_DIR}/src/jpeg_exif.cpp) source_group("Src\\grfmts" FILES ${grfmt_hdrs} ${grfmt_srcs}) diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index 04dcdb3c9..3222321e5 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -62,12 +62,18 @@ namespace cv //! Imread flags enum ImreadModes { - IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). - IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image. - IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image. - IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. - IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format. - IMREAD_LOAD_GDAL = 8 //!< If set, use the gdal driver for loading the image. + IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). + IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image. + IMREAD_COLOR = 1, //!< If set, always convert image to the 3 channel BGR color image. + IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit. + IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format. + IMREAD_LOAD_GDAL = 8, //!< If set, use the gdal driver for loading the image. + IMREAD_REDUCED_GRAYSCALE_2 = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2. + IMREAD_REDUCED_COLOR_2 = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2. + IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4. + IMREAD_REDUCED_COLOR_4 = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4. + IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8. + IMREAD_REDUCED_COLOR_8 = 65 //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8. }; //! Imwrite flags @@ -85,25 +91,31 @@ enum ImwriteFlags { IMWRITE_WEBP_QUALITY = 64 //!< For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used. }; -//! Imwrite PNG specific flags +//! Imwrite PNG specific flags used to tune the compression algorithm. +/** These flags will be modify the way of PNG image compression and will be passed to the underlying zlib processing stage. + +- The effect of IMWRITE_PNG_STRATEGY_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between IMWRITE_PNG_STRATEGY_DEFAULT and IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY. +- IMWRITE_PNG_STRATEGY_RLE is designed to be almost as fast as IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY, but give better compression for PNG image data. +- The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. +- IMWRITE_PNG_STRATEGY_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. +*/ enum ImwritePNGFlags { - IMWRITE_PNG_STRATEGY_DEFAULT = 0, - IMWRITE_PNG_STRATEGY_FILTERED = 1, - IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, - IMWRITE_PNG_STRATEGY_RLE = 3, - IMWRITE_PNG_STRATEGY_FIXED = 4 + IMWRITE_PNG_STRATEGY_DEFAULT = 0, //!< Use this value for normal data. + IMWRITE_PNG_STRATEGY_FILTERED = 1, //!< Use this value for data produced by a filter (or predictor).Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. + IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, //!< Use this value to force Huffman encoding only (no string match). + IMWRITE_PNG_STRATEGY_RLE = 3, //!< Use this value to limit match distances to one (run-length encoding). + IMWRITE_PNG_STRATEGY_FIXED = 4 //!< Using this value prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. }; /** @brief Loads an image from a file. @anchor imread -@param filename Name of file to be loaded. -@param flags Flag that can take values of @ref cv::ImreadModes - The function imread loads an image from the specified file and returns it. If the image cannot be read (because of missing file, improper permissions, unsupported or invalid format), the function -returns an empty matrix ( Mat::data==NULL ). Currently, the following file formats are supported: +returns an empty matrix ( Mat::data==NULL ). + +Currently, the following file formats are supported: - Windows bitmaps - \*.bmp, \*.dib (always supported) - JPEG files - \*.jpeg, \*.jpg, \*.jpe (see the *Notes* section) @@ -120,6 +132,7 @@ returns an empty matrix ( Mat::data==NULL ). Currently, the following file forma @note - The function determines the type of an image by the content, not by the file extension. +- In the case of color images, the decoded images will have the channels stored in **B G R** order. - On Microsoft Windows\* OS and MacOSX\*, the codecs shipped with an OpenCV image (libjpeg, libpng, libtiff, and libjasper) are used by default. So, OpenCV can always read JPEGs, PNGs, and TIFFs. On MacOSX, there is also an option to use native MacOSX image readers. But beware @@ -133,46 +146,35 @@ returns an empty matrix ( Mat::data==NULL ). Currently, the following file forma then [GDAL](http://www.gdal.org) driver will be used in order to decode the image by supporting the following formats: [Raster](http://www.gdal.org/formats_list.html), [Vector](http://www.gdal.org/ogr_formats.html). - -@note In the case of color images, the decoded images will have the channels stored in B G R order. - */ +@param filename Name of file to be loaded. +@param flags Flag that can take values of cv::ImreadModes +*/ CV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR ); -/** @brief Loads and resizes down an image from a file. -@anchor imread_reduced -@param filename Name of file to be loaded. -@param flags Flag that can take values of @ref cv::ImreadModes -@param scale_denom - */ -CV_EXPORTS_W Mat imread_reduced( const String& filename, int flags = IMREAD_COLOR, int scale_denom=1 ); - -/** @brief Loads a multi-page image from a file. (see imread for details.) +/** @brief Loads a multi-page image from a file. +The function imreadmulti loads a multi-page image from the specified file into a vector of Mat objects. @param filename Name of file to be loaded. -@param flags Flag that can take values of @ref cv::ImreadModes, default with IMREAD_ANYCOLOR. +@param flags Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR. @param mats A vector of Mat objects holding each page, if more than one. - +@sa cv::imread */ CV_EXPORTS_W bool imreadmulti(const String& filename, std::vector& mats, int flags = IMREAD_ANYCOLOR); /** @brief Saves an image to a specified file. -@param filename Name of the file. -@param img Image to be saved. -@param params Format-specific save parameters encoded as pairs, see @ref cv::ImwriteFlags -paramId_1, paramValue_1, paramId_2, paramValue_2, ... . - The function imwrite saves the image to the specified file. The image format is chosen based on the -filename extension (see imread for the list of extensions). Only 8-bit (or 16-bit unsigned (CV_16U) +filename extension (see cv::imread for the list of extensions). Only 8-bit (or 16-bit unsigned (CV_16U) in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with 'BGR' channel order) images can be saved using this function. If the format, depth or channel order is different, use -Mat::convertTo , and cvtColor to convert it before saving. Or, use the universal FileStorage I/O +Mat::convertTo , and cv::cvtColor to convert it before saving. Or, use the universal FileStorage I/O functions to save the image to XML or YAML format. It is possible to store PNG images with an alpha channel using this function. To do this, create 8-bit (or 16-bit) 4-channel image BGRA, where the alpha channel goes last. Fully transparent pixels -should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535. The sample below -shows how to create such a BGRA image and store to PNG file. It also demonstrates how to set custom +should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535. + +The sample below shows how to create such a BGRA image and store to PNG file. It also demonstrates how to set custom compression parameters : @code #include @@ -218,42 +220,44 @@ compression parameters : return 0; } @endcode - */ +@param filename Name of the file. +@param img Image to be saved. +@param params Format-specific parameters encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ... .) see cv::ImwriteFlags +*/ CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, const std::vector& params = std::vector()); -/** @overload */ -CV_EXPORTS_W Mat imdecode( InputArray buf, int flags ); - /** @brief Reads an image from a buffer in memory. +The function imdecode reads an image from the specified buffer in the memory. If the buffer is too short or +contains invalid data, the function returns an empty matrix ( Mat::data==NULL ). + +See cv::imread for the list of supported formats and flags description. + +@note In the case of color images, the decoded images will have the channels stored in **B G R** order. @param buf Input array or vector of bytes. -@param flags The same flags as in imread, see @ref cv::ImreadModes. +@param flags The same flags as in cv::imread, see cv::ImreadModes. +*/ +CV_EXPORTS_W Mat imdecode( InputArray buf, int flags ); + +/** @overload +@param buf +@param flags @param dst The optional output placeholder for the decoded matrix. It can save the image reallocations when the function is called repeatedly for images of the same size. - -The function reads an image from the specified buffer in the memory. If the buffer is too short or -contains invalid data, the empty matrix/image is returned. - -See imread for the list of supported formats and flags description. - -@note In the case of color images, the decoded images will have the channels stored in B G R order. - */ +*/ CV_EXPORTS Mat imdecode( InputArray buf, int flags, Mat* dst); /** @brief Encodes an image into a memory buffer. +The function imencode compresses the image and stores it in the memory buffer that is resized to fit the +result. See cv::imwrite for the list of supported formats and flags description. + @param ext File extension that defines the output format. @param img Image to be written. @param buf Output buffer resized to fit the compressed image. -@param params Format-specific parameters. See imwrite and @ref cv::ImwriteFlags. - -The function compresses the image and stores it in the memory buffer that is resized to fit the -result. See imwrite for the list of supported formats and flags description. - -@note cvEncodeImage returns single-row matrix of type CV_8UC1 that contains encoded image as array -of bytes. - */ +@param params Format-specific parameters. See cv::imwrite and cv::ImwriteFlags. +*/ CV_EXPORTS_W bool imencode( const String& ext, InputArray img, CV_OUT std::vector& buf, const std::vector& params = std::vector()); @@ -262,4 +266,4 @@ CV_EXPORTS_W bool imencode( const String& ext, InputArray img, } // cv -#endif //__OPENCV_IMGCODECS_HPP__ \ No newline at end of file +#endif //__OPENCV_IMGCODECS_HPP__ diff --git a/modules/imgcodecs/src/grfmt_jpeg.cpp b/modules/imgcodecs/src/grfmt_jpeg.cpp index 6502db941..6862a06eb 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.cpp +++ b/modules/imgcodecs/src/grfmt_jpeg.cpp @@ -41,6 +41,7 @@ #include "precomp.hpp" #include "grfmt_jpeg.hpp" +#include "jpeg_exif.hpp" #ifdef HAVE_JPEG @@ -177,6 +178,7 @@ JpegDecoder::JpegDecoder() m_state = 0; m_f = 0; m_buf_supported = true; + m_orientation = JPEG_ORIENTATION_TL; } @@ -253,12 +255,64 @@ bool JpegDecoder::readHeader() } } + m_orientation = getOrientation(); + if( !result ) close(); return result; } +int JpegDecoder::getOrientation() +{ + int orientation = JPEG_ORIENTATION_TL; + + ExifReader reader( m_filename ); + if( reader.parse() ) + { + orientation = reader.getTag( ORIENTATION ).field_u16;//orientation is unsigned short, so check field_u16 + } + + return orientation; +} + +void JpegDecoder::setOrientation(Mat& img) +{ + switch( m_orientation ) + { + case JPEG_ORIENTATION_TL: //0th row == visual top, 0th column == visual left-hand side + //do nothing, the image already has proper orientation + break; + case JPEG_ORIENTATION_TR: //0th row == visual top, 0th column == visual right-hand side + flip(img, img, 1); //flip horizontally + break; + case JPEG_ORIENTATION_BR: //0th row == visual bottom, 0th column == visual right-hand side + flip(img, img, -1);//flip both horizontally and vertically + break; + case JPEG_ORIENTATION_BL: //0th row == visual bottom, 0th column == visual left-hand side + flip(img, img, 0); //flip vertically + break; + case JPEG_ORIENTATION_LT: //0th row == visual left-hand side, 0th column == visual top + transpose(img, img); + break; + case JPEG_ORIENTATION_RT: //0th row == visual right-hand side, 0th column == visual top + transpose(img, img); + flip(img, img, 1); //flip horizontally + break; + case JPEG_ORIENTATION_RB: //0th row == visual right-hand side, 0th column == visual bottom + transpose(img, img); + flip(img, img, -1); //flip both horizontally and vertically + break; + case JPEG_ORIENTATION_LB: //0th row == visual left-hand side, 0th column == visual bottom + transpose(img, img); + flip(img, img, 0); //flip vertically + break; + default: + //by default the image read has normal (JPEG_ORIENTATION_TL) orientation + break; + } +} + /*************************************************************************** * following code is for supporting MJPEG image files * based on a message of Laurent Pinchart on the video4linux mailing list @@ -472,8 +526,10 @@ bool JpegDecoder::readData( Mat& img ) icvCvt_CMYK2Gray_8u_C4C1R( buffer[0], 0, data, 0, cvSize(m_width,1) ); } } + result = true; jpeg_finish_decompress( cinfo ); + setOrientation( img ); } } diff --git a/modules/imgcodecs/src/grfmt_jpeg.hpp b/modules/imgcodecs/src/grfmt_jpeg.hpp index 8455b197b..d0a0991c5 100644 --- a/modules/imgcodecs/src/grfmt_jpeg.hpp +++ b/modules/imgcodecs/src/grfmt_jpeg.hpp @@ -70,6 +70,12 @@ protected: FILE* m_f; void* m_state; + +private: + //Support for handling exif orientation tag in Jpeg file + int m_orientation; + int getOrientation(); + void setOrientation(Mat& img); }; diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index 5a5f40bb9..2f4a62bae 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -368,7 +368,7 @@ bool PngEncoder::write( const Mat& img, const std::vector& params ) { f = fopen( m_filename.c_str(), "wb" ); if( f ) - png_init_io( png_ptr, f ); + png_init_io( png_ptr, (png_FILE_p)f ); } int compression_level = -1; // Invalid value to allow setting 0-9 as valid @@ -437,7 +437,7 @@ bool PngEncoder::write( const Mat& img, const std::vector& params ) } png_destroy_write_struct( &png_ptr, &info_ptr ); - if(f) fclose( f ); + if(f) fclose( (FILE*)f ); return result; } diff --git a/modules/imgcodecs/src/jpeg_exif.cpp b/modules/imgcodecs/src/jpeg_exif.cpp new file mode 100644 index 000000000..caade4803 --- /dev/null +++ b/modules/imgcodecs/src/jpeg_exif.cpp @@ -0,0 +1,582 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "jpeg_exif.hpp" + +namespace cv +{ + +/** + * @brief ExifReader constructor + */ +ExifReader::ExifReader(std::string filename) : m_filename(filename) +{ +} + +/** + * @brief ExifReader destructor + */ +ExifReader::~ExifReader() +{ +} + +/** + * @brief Parsing the jpeg file and prepare (internally) exif directory structure + * @return true if parsing was successful and exif information exists in JpegReader object + * false in case of unsuccessful parsing + */ +bool ExifReader::parse() +{ + m_exif = getExif(); + if( !m_exif.empty() ) + { + return true; + } + return false; +} + + +/** + * @brief Get tag value by tag number + * + * @param [in] tag The tag number + * + * @return ExifEntru_t structure. Caller has to know what tag it calls in order to extract proper field from the structure ExifEntry_t + * + */ +ExifEntry_t ExifReader::getTag(const ExifTagName tag) +{ + ExifEntry_t entry; + std::map::iterator it = m_exif.find(tag); + + if( it != m_exif.end() ) + { + entry = it->second; + } + return entry; +} + + +/** + * @brief Get exif directory structure contained in jpeg file (if any) + * This is internal function and is not exposed to client + * + * @return Map where key is tag number and value is ExifEntry_t structure + */ +std::map ExifReader::getExif() +{ + const size_t markerSize = 2; + const size_t offsetToTiffHeader = 6; //bytes from Exif size field to the first TIFF header + unsigned char appMarker[markerSize]; + m_exif.erase( m_exif.begin(), m_exif.end() ); + + size_t count; + + FILE* f = fopen( m_filename.c_str(), "rb" ); + + if( !f ) + { + return m_exif; //Until this moment the map is empty + } + + bool exifFound = false; + while( ( !feof( f ) ) && !exifFound ) + { + count = fread( appMarker, sizeof(unsigned char), markerSize, f ); + if( count < markerSize ) + { + break; + } + unsigned char marker = appMarker[1]; + size_t bytesToSkip; + size_t exifSize; + switch( marker ) + { + //For all the markers just skip bytes in file pointed by followed two bytes (field size) + case SOF0: case SOF2: case DHT: case DQT: case DRI: case SOS: + case RST0: case RST1: case RST2: case RST3: case RST4: case RST5: case RST6: case RST7: + case APP0: case APP2: case APP3: case APP4: case APP5: case APP6: case APP7: case APP8: + case APP9: case APP10: case APP11: case APP12: case APP13: case APP14: case APP15: + case COM: + bytesToSkip = getFieldSize( f ); + fseek( f, static_cast( bytesToSkip - markerSize ), SEEK_CUR ); + break; + + //SOI and EOI don't have the size field after the marker + case SOI: case EOI: + break; + + case APP1: //actual Exif Marker + exifSize = getFieldSize(f); + m_data.resize( exifSize - offsetToTiffHeader ); + fseek(f, static_cast( offsetToTiffHeader ), SEEK_CUR); + count = fread( &m_data[0], sizeof( unsigned char ), exifSize - offsetToTiffHeader, f ); + exifFound = true; + break; + + default: //No other markers are expected according to standard. May be a signal of error + break; + } + } + + fclose(f); + + if( !exifFound ) + { + return m_exif; + } + + parseExif(); + + return m_exif; +} + +/** + * @brief Get the size of exif field (required to properly ready whole exif from the file) + * This is internal function and is not exposed to client + * + * @return size of exif field in the file + */ +size_t ExifReader::getFieldSize (FILE* f) const +{ + unsigned char fieldSize[2]; + size_t count = fread ( fieldSize, sizeof( char ), 2, f ); + if (count < 2) + { + return 0; + } + return ( fieldSize[0] << 8 ) + fieldSize[1]; +} + +/** + * @brief Filling m_exif member with exif directory elements + * This is internal function and is not exposed to client + * + * @return The function doesn't return any value. In case of unsiccessful parsing + * the m_exif member is not filled up + */ +void ExifReader::parseExif() +{ + m_format = getFormat(); + + if( !checkTagMark() ) + { + return; + } + + uint32_t offset = getStartOffset(); + + size_t numEntry = getNumDirEntry(); + + offset += 2; //go to start of tag fields + + for( size_t entry = 0; entry < numEntry; entry++ ) + { + ExifEntry_t exifEntry = parseExifEntry( offset ); + m_exif.insert( std::make_pair( exifEntry.tag, exifEntry ) ); + offset += tiffFieldSize; + } +} + +/** + * @brief Get endianness of exif information + * This is internal function and is not exposed to client + * + * @return INTEL, MOTO or NONE + */ +Endianess_t ExifReader::getFormat() const +{ + if( m_data[0] != m_data[1] ) + { + return NONE; + } + + if( m_data[0] == 'I' ) + { + return INTEL; + } + + if( m_data[0] == 'M' ) + { + return MOTO; + } + + return NONE; +} + +/** + * @brief Checking whether Tag Mark (0x002A) correspond to one contained in the Jpeg file + * This is internal function and is not exposed to client + * + * @return true if tag mark equals 0x002A, false otherwise + */ +bool ExifReader::checkTagMark() const +{ + uint16_t tagMark = getU16( 2 ); + + if( tagMark != tagMarkRequired ) + { + return false; + } + return true; +} + +/** + * @brief The utility function for extracting actual offset exif IFD0 info is started from + * This is internal function and is not exposed to client + * + * @return offset of IFD0 field + */ +uint32_t ExifReader::getStartOffset() const +{ + return getU32( 4 ); +} + +/** + * @brief Get the number of Directory Entries in Jpeg file + * + * @return The number of directory entries + */ +size_t ExifReader::getNumDirEntry() const +{ + return getU16( offsetNumDir ); +} + +/** + * @brief Parsing particular entry in exif directory + * This is internal function and is not exposed to client + * + * Entries are divided into 12-bytes blocks each + * Each block corresponds the following structure: + * + * +------+-------------+-------------------+------------------------+ + * | Type | Data format | Num of components | Data or offset to data | + * +======+=============+===================+========================+ + * | TTTT | ffff | NNNNNNNN | DDDDDDDD | + * +------+-------------+-------------------+------------------------+ + * + * Details can be found here: http://www.media.mit.edu/pia/Research/deepview/exif.html + * + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return ExifEntry_t structure which corresponds to particular entry + * + */ +ExifEntry_t ExifReader::parseExifEntry(const size_t offset) +{ + ExifEntry_t entry; + uint16_t tagNum = getExifTag( offset ); + entry.tag = tagNum; + + switch( tagNum ) + { + case IMAGE_DESCRIPTION: + entry.field_str = getString( offset ); + break; + case MAKE: + entry.field_str = getString( offset ); + break; + case MODEL: + entry.field_str = getString( offset ); + break; + case ORIENTATION: + entry.field_u16 = getOrientation( offset ); + break; + case XRESOLUTION: + entry.field_u_rational = getResolution( offset ); + break; + case YRESOLUTION: + entry.field_u_rational = getResolution( offset ); + break; + case RESOLUTION_UNIT: + entry.field_u16 = getResolutionUnit( offset ); + break; + case SOFTWARE: + entry.field_str = getString( offset ); + break; + case DATE_TIME: + entry.field_str = getString( offset ); + break; + case WHITE_POINT: + entry.field_u_rational = getWhitePoint( offset ); + break; + case PRIMARY_CHROMATICIES: + entry.field_u_rational = getPrimaryChromaticies( offset ); + break; + case Y_CB_CR_COEFFICIENTS: + entry.field_u_rational = getYCbCrCoeffs( offset ); + break; + case Y_CB_CR_POSITIONING: + entry.field_u16 = getYCbCrPos( offset ); + break; + case REFERENCE_BLACK_WHITE: + entry.field_u_rational = getRefBW( offset ); + break; + case COPYRIGHT: + entry.field_str = getString( offset ); + break; + case EXIF_OFFSET: + break; + default: + entry.tag = INVALID_TAG; + break; + } + return entry; +} + +/** + * @brief Get tag number from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return tag number + */ +uint16_t ExifReader::getExifTag(const size_t offset) const +{ + return getU16( offset ); +} + +/** + * @brief Get string information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return string value + */ +std::string ExifReader::getString(const size_t offset) const +{ + size_t size = getU32( offset + 4 ); + size_t dataOffset = 8; // position of data in the field + if( size > maxDataSize ) + { + dataOffset = getU32( offset + 8 ); + } + std::vector::const_iterator it = m_data.begin() + dataOffset; + std::string result( it, it + size ); //copy vector content into result + + return result; +} + +/** + * @brief Get unsigned short data from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return Unsigned short data + */ +uint16_t ExifReader::getU16(const size_t offset) const +{ + if( m_format == INTEL ) + { + return m_data[offset] + ( m_data[offset + 1] << 8 ); + } + return ( m_data[offset] << 8 ) + m_data[offset + 1]; +} + +/** + * @brief Get unsigned 32-bit data from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return Unsigned 32-bit data + */ +uint32_t ExifReader::getU32(const size_t offset) const +{ + if( m_format == INTEL ) + { + return m_data[offset] + + ( m_data[offset + 1] << 8 ) + + ( m_data[offset + 2] << 16 ) + + ( m_data[offset + 3] << 24 ); + } + + return ( m_data[offset] << 24 ) + + ( m_data[offset + 1] << 16 ) + + ( m_data[offset + 2] << 8 ) + + m_data[offset + 3]; +} + +/** + * @brief Get unsigned rational data from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return Unsigned rational data + * + * "rational" means a fractional value, it contains 2 signed/unsigned long integer value, + * and the first represents the numerator, the second, the denominator. + */ +u_rational_t ExifReader::getURational(const size_t offset) const +{ + u_rational_t result; + uint32_t numerator = getU32( offset ); + uint32_t denominator = getU32( offset + 4 ); + + return std::make_pair( numerator, denominator ); + +} + +/** + * @brief Get orientation information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return orientation number + */ +uint16_t ExifReader::getOrientation(const size_t offset) const +{ + return getU16( offset + 8 ); +} + +/** + * @brief Get resolution information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return resolution value + */ +std::vector ExifReader::getResolution(const size_t offset) const +{ + std::vector result; + uint32_t rationalOffset = getU32( offset + 8 ); + result.push_back( getURational( rationalOffset ) ); + + return result; +} + +/** + * @brief Get resolution unit from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return resolution unit value + */ +uint16_t ExifReader::getResolutionUnit(const size_t offset) const +{ + return getU16( offset + 8 ); +} + +/** + * @brief Get White Point information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return White Point value + * + * If the image uses CIE Standard Illumination D65(known as international + * standard of 'daylight'), the values are '3127/10000,3290/10000'. + */ +std::vector ExifReader::getWhitePoint(const size_t offset) const +{ + std::vector result; + uint32_t rationalOffset = getU32( offset + 8 ); + result.push_back( getURational( rationalOffset ) ); + result.push_back( getURational( rationalOffset + 8 ) ); + + return result; +} + +/** + * @brief Get Primary Chromaticies information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return vector with primary chromaticies values + * + */ +std::vector ExifReader::getPrimaryChromaticies(const size_t offset) const +{ + std::vector result; + uint32_t rationalOffset = getU32( offset + 8 ); + for( size_t i = 0; i < primaryChromaticiesComponents; i++ ) + { + result.push_back( getURational( rationalOffset ) ); + rationalOffset += 8; + } + return result; +} + +/** + * @brief Get YCbCr Coefficients information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return vector with YCbCr coefficients values + * + */ +std::vector ExifReader::getYCbCrCoeffs(const size_t offset) const +{ + std::vector result; + uint32_t rationalOffset = getU32( offset + 8 ); + for( size_t i = 0; i < ycbcrCoeffs; i++ ) + { + result.push_back( getURational( rationalOffset ) ); + rationalOffset += 8; + } + return result; +} + +/** + * @brief Get YCbCr Positioning information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return vector with YCbCr positioning value + * + */ +uint16_t ExifReader::getYCbCrPos(const size_t offset) const +{ + return getU16( offset + 8 ); +} + +/** + * @brief Get Reference Black&White point information from raw exif data + * This is internal function and is not exposed to client + * @param [in] offset Offset to entry in bytes inside raw exif data + * @return vector with reference BW points + * + * In case of YCbCr format, first 2 show black/white of Y, next 2 are Cb, + * last 2 are Cr. In case of RGB format, first 2 show black/white of R, + * next 2 are G, last 2 are B. + * + */ +std::vector ExifReader::getRefBW(const size_t offset) const +{ + const size_t rationalFieldSize = 8; + std::vector result; + uint32_t rationalOffset = getU32( offset + rationalFieldSize ); + for( size_t i = 0; i < refBWComponents; i++ ) + { + result.push_back( getURational( rationalOffset ) ); + rationalOffset += rationalFieldSize; + } + return result; +} + +} //namespace cv diff --git a/modules/imgcodecs/src/jpeg_exif.hpp b/modules/imgcodecs/src/jpeg_exif.hpp new file mode 100644 index 000000000..9ca138167 --- /dev/null +++ b/modules/imgcodecs/src/jpeg_exif.hpp @@ -0,0 +1,251 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + +#ifndef _OPENCV_JPEG_EXIF_HPP_ +#define _OPENCV_JPEG_EXIF_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +namespace cv +{ +/** + * @brief Jpeg markers that can encounter in Jpeg file + */ +enum AppMarkerTypes +{ + SOI = 0xD8, SOF0 = 0xC0, SOF2 = 0xC2, DHT = 0xC4, + DQT = 0xDB, DRI = 0xDD, SOS = 0xDA, + + RST0 = 0xD0, RST1 = 0xD1, RST2 = 0xD2, RST3 = 0xD3, + RST4 = 0xD4, RST5 = 0xD5, RST6 = 0xD6, RST7 = 0xD7, + + APP0 = 0xE0, APP1 = 0xE1, APP2 = 0xE2, APP3 = 0xE3, + APP4 = 0xE4, APP5 = 0xE5, APP6 = 0xE6, APP7 = 0xE7, + APP8 = 0xE8, APP9 = 0xE9, APP10 = 0xEA, APP11 = 0xEB, + APP12 = 0xEC, APP13 = 0xED, APP14 = 0xEE, APP15 = 0xEF, + + COM = 0xFE, EOI = 0xD9 +}; + +/** + * @brief Base Exif tags used by IFD0 (main image) + */ +enum ExifTagName +{ + IMAGE_DESCRIPTION = 0x010E, ///< Image Description: ASCII string + MAKE = 0x010F, ///< Description of manufacturer: ASCII string + MODEL = 0x0110, ///< Description of camera model: ASCII string + ORIENTATION = 0x0112, ///< Orientation of the image: unsigned short + XRESOLUTION = 0x011A, ///< Resolution of the image across X axis: unsigned rational + YRESOLUTION = 0x011B, ///< Resolution of the image across Y axis: unsigned rational + RESOLUTION_UNIT = 0x0128, ///< Resolution units. '1' no-unit, '2' inch, '3' centimeter + SOFTWARE = 0x0131, ///< Shows firmware(internal software of digicam) version number + DATE_TIME = 0x0132, ///< Date/Time of image was last modified + WHITE_POINT = 0x013E, ///< Chromaticity of white point of the image + PRIMARY_CHROMATICIES = 0x013F, ///< Chromaticity of the primaries of the image + Y_CB_CR_COEFFICIENTS = 0x0211, ///< constant to translate an image from YCbCr to RGB format + Y_CB_CR_POSITIONING = 0x0213, ///< Chroma sample point of subsampling pixel array + REFERENCE_BLACK_WHITE = 0x0214, ///< Reference value of black point/white point + COPYRIGHT = 0x8298, ///< Copyright information + EXIF_OFFSET = 0x8769, ///< Offset to Exif Sub IFD + INVALID_TAG = 0xFFFF ///< Shows that the tag was not recognized +}; + +enum Endianess_t +{ + INTEL = 0x49, + MOTO = 0x4D, + NONE = 0x00 +}; + +typedef std::pair u_rational_t; + +/** + * @brief Entry which contains possible values for different exif tags + */ +struct ExifEntry_t +{ + std::vector field_u_rational; ///< vector of rational fields + std::string field_str; ///< any kind of textual information + + float field_float; ///< Currently is not used + double field_double; ///< Currently is not used + + uint32_t field_u32; ///< Unsigned 32-bit value + int32_t field_s32; ///< Signed 32-bit value + + uint16_t tag; ///< Tag number + + uint16_t field_u16; ///< Unsigned 16-bit value + int16_t field_s16; ///< Signed 16-bit value + uint8_t field_u8; ///< Unsigned 8-bit value + int8_t field_s8; ///< Signed 8-bit value +}; + +/** + * @brief Picture orientation which may be taken from JPEG's EXIF + * Orientation usually matters when the picture is taken by + * smartphone or other camera with orientation sensor support + * Corresponds to EXIF 2.3 Specification + */ +enum JpegOrientation +{ + JPEG_ORIENTATION_TL = 1, ///< 0th row == visual top, 0th column == visual left-hand side + JPEG_ORIENTATION_TR = 2, ///< 0th row == visual top, 0th column == visual right-hand side + JPEG_ORIENTATION_BR = 3, ///< 0th row == visual bottom, 0th column == visual right-hand side + JPEG_ORIENTATION_BL = 4, ///< 0th row == visual bottom, 0th column == visual left-hand side + JPEG_ORIENTATION_LT = 5, ///< 0th row == visual left-hand side, 0th column == visual top + JPEG_ORIENTATION_RT = 6, ///< 0th row == visual right-hand side, 0th column == visual top + JPEG_ORIENTATION_RB = 7, ///< 0th row == visual right-hand side, 0th column == visual bottom + JPEG_ORIENTATION_LB = 8 ///< 0th row == visual left-hand side, 0th column == visual bottom +}; + +/** + * @brief Reading exif information from Jpeg file + * + * Usage example for getting the orientation of the image: + * + * @code + * ExifReader reader(fileName); + * if( reader.parse() ) + * { + * int orientation = reader.getTag(Orientation).field_u16; + * } + * @endcode + * + */ +class ExifReader +{ +public: + /** + * @brief ExifReader constructor. Constructs an object of exif reader + * + * @param [in]filename The name of file to look exif info in + */ + explicit ExifReader( std::string filename ); + ~ExifReader(); + + + /** + * @brief Parse the file with exif info + * + * @return true if parsing was successful and exif information exists in JpegReader object + */ + bool parse(); + + /** + * @brief Get tag info by tag number + * + * @param [in] tag The tag number + * @return ExifEntru_t structure. Caller has to know what tag it calls in order to extract proper field from the structure ExifEntry_t + */ + ExifEntry_t getTag( const ExifTagName tag ); + +private: + std::string m_filename; + std::vector m_data; + std::map m_exif; + Endianess_t m_format; + + void parseExif(); + bool checkTagMark() const; + + size_t getFieldSize ( FILE* f ) const; + size_t getNumDirEntry() const; + uint32_t getStartOffset() const; + uint16_t getExifTag( const size_t offset ) const; + uint16_t getU16( const size_t offset ) const; + uint32_t getU32( const size_t offset ) const; + uint16_t getOrientation( const size_t offset ) const; + uint16_t getResolutionUnit( const size_t offset ) const; + uint16_t getYCbCrPos( const size_t offset ) const; + + Endianess_t getFormat() const; + + ExifEntry_t parseExifEntry( const size_t offset ); + + u_rational_t getURational( const size_t offset ) const; + + std::map getExif(); + std::string getString( const size_t offset ) const; + std::vector getResolution( const size_t offset ) const; + std::vector getWhitePoint( const size_t offset ) const; + std::vector getPrimaryChromaticies( const size_t offset ) const; + std::vector getYCbCrCoeffs( const size_t offset ) const; + std::vector getRefBW( const size_t offset ) const; + +private: + static const uint16_t tagMarkRequired = 0x2A; + + //offset to the _number-of-directory-entry_ field + static const size_t offsetNumDir = 8; + + //max size of data in tag. + //'DDDDDDDD' contains the value of that Tag. If its size is over 4bytes, + //'DDDDDDDD' contains the offset to data stored address. + static const size_t maxDataSize = 4; + + //bytes per tag field + static const size_t tiffFieldSize = 12; + + //number of primary chromaticies components + static const size_t primaryChromaticiesComponents = 6; + + //number of YCbCr coefficients in field + static const size_t ycbcrCoeffs = 3; + + //number of Reference Black&White components + static const size_t refBWComponents = 6; +}; + + + +} + +#endif /* JPEG_EXIF_HPP_ */ diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 5df1ea214..70a31c37a 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -238,7 +238,7 @@ enum { LOAD_CVMAT=0, LOAD_IMAGE=1, LOAD_MAT=2 }; * */ static void* -imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_denom=1 ) +imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 ) { IplImage* image = 0; CvMat *matrix = 0; @@ -252,7 +252,7 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_d decoder = GdalDecoder().newDecoder(); }else{ #endif - decoder = findDecoder(filename); + decoder = findDecoder( filename ); #ifdef HAVE_GDAL } #endif @@ -262,11 +262,22 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_d return 0; } + int scale_denom = 1; + if( flags > IMREAD_LOAD_GDAL ) + { + if( flags & IMREAD_REDUCED_GRAYSCALE_2 ) + scale_denom = 2; + else if( flags & IMREAD_REDUCED_GRAYSCALE_4 ) + scale_denom = 4; + else if( flags & IMREAD_REDUCED_GRAYSCALE_8 ) + scale_denom = 8; + } + /// set the scale_denom in the driver decoder->setScale( scale_denom ); /// set the filename in the driver - decoder->setSource(filename); + decoder->setSource( filename ); // read the header to make sure it succeeds if( !decoder->readHeader() ) @@ -296,7 +307,7 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_d if( hdrtype == LOAD_CVMAT ) { matrix = cvCreateMat( size.height, size.width, type ); - temp = cvarrToMat(matrix); + temp = cvarrToMat( matrix ); } else { @@ -307,7 +318,7 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_d else { image = cvCreateImage( size, cvIplDepth(type), CV_MAT_CN(type) ); - temp = cvarrToMat(image); + temp = cvarrToMat( image ); } // read the image data @@ -320,10 +331,9 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0, int scale_d return 0; } - int testdecoder = decoder->setScale( scale_denom ); // if decoder is JpegDecoder then testdecoder will be 1 - if( (scale_denom > 1 ) & ( testdecoder > 1 ) ) + if( decoder->setScale( scale_denom ) > 1 ) // if decoder is JpegDecoder then decoder->setScale always returns 1 { - resize(*mat,*mat,Size(size.width/scale_denom,size.height/scale_denom)); + resize( *mat, *mat, Size( size.width / scale_denom, size.height / scale_denom ) ); } return hdrtype == LOAD_CVMAT ? (void*)matrix : @@ -421,27 +431,6 @@ Mat imread( const String& filename, int flags ) return img; } -/** - * Read an image and resize it - * - * This function merely calls the actual implementation above and returns itself. - * - * @param[in] filename File to load - * @param[in] flags Flags you wish to set. - * @param[in] scale_denom Scale value -*/ -Mat imread_reduced( const String& filename, int flags, int scale_denom ) -{ - /// create the basic container - Mat img; - - /// load the data - imread_( filename, flags, LOAD_MAT, &img, scale_denom ); - - /// return a reference to the data - return img; -} - /** * Read a multi-page image * @@ -736,4 +725,4 @@ cvEncodeImage( const char* ext, const CvArr* arr, const int* _params ) return _buf; } -/* End of file. */ \ No newline at end of file +/* End of file. */ diff --git a/modules/imgcodecs/test/test_grfmt.cpp b/modules/imgcodecs/test/test_grfmt.cpp index ae0b428ec..f305ca137 100644 --- a/modules/imgcodecs/test/test_grfmt.cpp +++ b/modules/imgcodecs/test/test_grfmt.cpp @@ -43,6 +43,7 @@ #include "test_precomp.hpp" #include +#include using namespace cv; using namespace std; @@ -118,6 +119,150 @@ TEST(Imgcodecs_imread, regression) } } +template +string to_string(T i) +{ + stringstream ss; + string s; + ss << i; + s = ss.str(); + + return s; +} + + +/** + * Test for check whether reading exif orientation tag was processed successfully or not + * The test info is the set of 8 images named testExifRotate_{1 to 8}.jpg + * The test image is the square 10x10 points divided by four sub-squares: + * (R corresponds to Red, G to Green, B to Blue, W to white) + * --------- --------- + * | R | G | | G | R | + * |-------| - (tag 1) |-------| - (tag 2) + * | B | W | | W | B | + * --------- --------- + * + * --------- --------- + * | W | B | | B | W | + * |-------| - (tag 3) |-------| - (tag 4) + * | G | R | | R | G | + * --------- --------- + * + * --------- --------- + * | R | B | | G | W | + * |-------| - (tag 5) |-------| - (tag 6) + * | G | W | | R | B | + * --------- --------- + * + * --------- --------- + * | W | G | | B | R | + * |-------| - (tag 7) |-------| - (tag 8) + * | B | R | | W | G | + * --------- --------- + * + * + * Every image contains exif field with orientation tag (0x112) + * After reading each image the corresponding matrix must be read as + * --------- + * | R | G | + * |-------| + * | B | W | + * --------- + * + */ +class CV_GrfmtJpegExifOrientationTest : public cvtest::BaseTest +{ +public: + void run(int) + { + try + { + for( int i = 1; i <= 8; ++i) + { + string fileName = "readwrite/testExifOrientation_" + to_string(i) + ".jpg"; + m_img = imread(string(ts->get_data_path()) + fileName); + if( !m_img.data ) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + } + ts->printf(cvtest::TS::LOG, "start reading image\t%s\n", fileName.c_str()); + if( !checkOrientation() ) + { + ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + } + } + + } + catch(...) + { + ts->set_failed_test_info(cvtest::TS::FAIL_EXCEPTION); + } + } +private: + bool checkOrientation(); + Mat m_img; +}; + + +bool CV_GrfmtJpegExifOrientationTest::checkOrientation() +{ + Vec3b vec; + int red = 0; + int green = 0; + int blue = 0; + + const int colorThresholdHigh = 250; + const int colorThresholdLow = 5; + + //Checking the first quadrant (with supposed red) + vec = m_img.at(2, 2); //some point inside the square + red = vec.val[2]; + green = vec.val[1]; + blue = vec.val[0]; + + ts->printf(cvtest::TS::LOG, "RED QUADRANT:\n"); + ts->printf(cvtest::TS::LOG, "Red calculated:\t\t%d\n", red); + ts->printf(cvtest::TS::LOG, "Green calculated:\t%d\n", green); + ts->printf(cvtest::TS::LOG, "Blue calculated:\t%d\n", blue); + if( red < colorThresholdHigh ) return false; + if( blue > colorThresholdLow ) return false; + if( green > colorThresholdLow ) return false; + + //Checking the second quadrant (with supposed green) + vec = m_img.at(2, 7); //some point inside the square + red = vec.val[2]; + green = vec.val[1]; + blue = vec.val[0]; + ts->printf(cvtest::TS::LOG, "GREEN QUADRANT:\n"); + ts->printf(cvtest::TS::LOG, "Red calculated:\t\t%d\n", red); + ts->printf(cvtest::TS::LOG, "Green calculated:\t%d\n", green); + ts->printf(cvtest::TS::LOG, "Blue calculated:\t%d\n", blue); + if( green < colorThresholdHigh ) return false; + if( red > colorThresholdLow ) return false; + if( blue > colorThresholdLow ) return false; + + //Checking the third quadrant (with supposed blue) + vec = m_img.at(7, 2); //some point inside the square + red = vec.val[2]; + green = vec.val[1]; + blue = vec.val[0]; + ts->printf(cvtest::TS::LOG, "BLUE QUADRANT:\n"); + ts->printf(cvtest::TS::LOG, "Red calculated:\t\t%d\n", red); + ts->printf(cvtest::TS::LOG, "Green calculated:\t%d\n", green); + ts->printf(cvtest::TS::LOG, "Blue calculated:\t%d\n", blue); + if( blue < colorThresholdHigh ) return false; + if( red > colorThresholdLow ) return false; + if( green > colorThresholdLow ) return false; + + return true; +} + +TEST(Imgcodecs_jpeg_exif, setOrientation) +{ + CV_GrfmtJpegExifOrientationTest test; + test.safe_run(); +} + #ifdef HAVE_JASPER TEST(Imgcodecs_jasper, regression) { diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index f57edb6d7..d440254e7 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -1922,7 +1922,7 @@ CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel, /** @brief Performs advanced morphological transformations. -The function can perform advanced morphological transformations using an erosion and dilation as +The function morphologyEx can perform advanced morphological transformations using an erosion and dilation as basic operations. Any of the operations can be done in-place. In case of multi-channel images, each channel is @@ -1930,11 +1930,11 @@ processed independently. @param src Source image. The number of channels can be arbitrary. The depth should be one of CV_8U, CV_16U, CV_16S, CV_32F or CV_64F. -@param dst Destination image of the same size and type as src\` . -@param kernel Structuring element. It can be created using getStructuringElement. +@param dst Destination image of the same size and type as source image. +@param op Type of a morphological operation, see cv::MorphTypes +@param kernel Structuring element. It can be created using cv::getStructuringElement. @param anchor Anchor position with the kernel. Negative values mean that the anchor is at the kernel center. -@param op Type of a morphological operation, see cv::MorphTypes @param iterations Number of times erosion and dilation are applied. @param borderType Pixel extrapolation method, see cv::BorderTypes @param borderValue Border value in case of a constant border. The default value has a special @@ -3404,8 +3404,9 @@ CV_EXPORTS_W int connectedComponents(InputArray image, OutputArray labels, @param labels destination labeled image @param stats statistics output for each label, including the background label, see below for available statistics. Statistics are accessed via stats(label, COLUMN) where COLUMN is one of -cv::ConnectedComponentsTypes -@param centroids floating point centroid (x,y) output for each label, including the background label +cv::ConnectedComponentsTypes. The data type is CV_32S. +@param centroids centroid output for each label, including the background label. Centroids are +accessed via centroids(label, 0) for x and centroids(label, 1) for y. The data type CV_64F. @param connectivity 8 or 4 for 8-way or 4-way connectivity respectively @param ltype output image label type. Currently CV_32S and CV_16U are supported. */ diff --git a/modules/imgproc/perf/perf_cvt_color.cpp b/modules/imgproc/perf/perf_cvt_color.cpp index 02622ea80..fc9a2cd8e 100644 --- a/modules/imgproc/perf/perf_cvt_color.cpp +++ b/modules/imgproc/perf/perf_cvt_color.cpp @@ -263,6 +263,11 @@ PERF_TEST_P(Size_CvtMode, cvtColor8u, #if defined(__APPLE__) && defined(HAVE_IPP) SANITY_CHECK(dst, _mode == CX_BGRA2HLS_FULL ? 2 : 1); +#elif defined(_MSC_VER) && _MSC_VER >= 1900 /* MSVC 14 */ + if (_mode == CX_Luv2BGRA) + SANITY_CHECK_NOTHING(); + else + SANITY_CHECK(dst, 1); #else SANITY_CHECK(dst, 1); #endif diff --git a/modules/imgproc/perf/perf_houghLines.cpp b/modules/imgproc/perf/perf_houghLines.cpp index a6e7e7340..6dfaa56aa 100644 --- a/modules/imgproc/perf/perf_houghLines.cpp +++ b/modules/imgproc/perf/perf_houghLines.cpp @@ -37,7 +37,7 @@ PERF_TEST_P(Image_RhoStep_ThetaStep_Threshold, HoughLines, TEST_CYCLE() HoughLines(image, lines, rhoStep, thetaStep, threshold); transpose(lines, lines); -#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801) +#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810) SANITY_CHECK_NOTHING(); #else SANITY_CHECK(lines); diff --git a/modules/imgproc/src/accum.cpp b/modules/imgproc/src/accum.cpp index 8792e85d0..c7cbc40f3 100644 --- a/modules/imgproc/src/accum.cpp +++ b/modules/imgproc/src/accum.cpp @@ -835,7 +835,7 @@ static bool ocl_accumulate( InputArray _src, InputArray _src2, InputOutputArray if (haveMask) k.set(argidx, maskarg); - size_t globalsize[2] = { src.cols * cn / kercn, (src.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)src.cols * cn / kercn, ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/src/blend.cpp b/modules/imgproc/src/blend.cpp index 7a2e57d52..2393f26db 100644 --- a/modules/imgproc/src/blend.cpp +++ b/modules/imgproc/src/blend.cpp @@ -111,7 +111,7 @@ static bool ocl_blendLinear( InputArray _src1, InputArray _src2, InputArray _wei ocl::KernelArg::ReadOnlyNoSize(weights1), ocl::KernelArg::ReadOnlyNoSize(weights2), ocl::KernelArg::WriteOnly(dst)); - size_t globalsize[2] = { dst.cols, dst.rows }; + size_t globalsize[2] = { (size_t)dst.cols, (size_t)dst.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index d51711e0a..815b03b70 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -44,26 +44,32 @@ #include "opencl_kernels_imgproc.hpp" -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) #define USE_IPP_CANNY 1 #else -#undef USE_IPP_CANNY +#define USE_IPP_CANNY 0 #endif namespace cv { - -#ifdef USE_IPP_CANNY +#ifdef HAVE_IPP static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) { +#if USE_IPP_CANNY int size = 0, size1 = 0; IppiSize roi = { _src.cols, _src.rows }; +#if IPP_VERSION_X100 < 900 if (ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size) < 0) return false; if (ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size1) < 0) return false; +#else + if(ippiFilterSobelGetBufferSize(roi, ippMskSize3x3, ippNormL2, ipp8u, ipp16s, 1, &size) < 0) + return false; +#endif + size = std::max(size, size1); if (ippiCannyGetSize(roi, &size1) < 0) @@ -90,6 +96,10 @@ static bool ippCanny(const Mat& _src, Mat& _dst, float low, float high) _dst.ptr(), (int)_dst.step, roi, low, high, buffer) < 0 ) return false; return true; +#else + CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(low); CV_UNUSED(high); + return false; +#endif } #endif @@ -154,8 +164,8 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float ocl::KernelArg::WriteOnlyNoSize(map), (float) low, (float) high); - size_t globalsize[2] = { size.width, size.height }, - localsize[2] = { lSizeX, lSizeY }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }, + localsize[2] = { (size_t)lSizeX, (size_t)lSizeY }; if (!with_sobel.run(2, globalsize, localsize, false)) return false; @@ -183,8 +193,8 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float ocl::KernelArg::WriteOnly(map), low, high); - size_t globalsize[2] = { size.width, size.height }, - localsize[2] = { lSizeX, lSizeY }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }, + localsize[2] = { (size_t)lSizeX, (size_t)lSizeY }; if (!without_sobel.run(2, globalsize, localsize, false)) return false; @@ -200,7 +210,7 @@ static bool ocl_Canny(InputArray _src, OutputArray _dst, float low_thresh, float if (sizey == 0) sizey = 1; - size_t globalsize[2] = { size.width, (size.height + PIX_PER_WI - 1) / PIX_PER_WI }, localsize[2] = { lSizeX, sizey }; + size_t globalsize[2] = { (size_t)size.width, ((size_t)size.height + PIX_PER_WI - 1) / PIX_PER_WI }, localsize[2] = { (size_t)lSizeX, (size_t)sizey }; ocl::Kernel edgesHysteresis("stage2_hysteresis", ocl::imgproc::canny_oclsrc, format("-D STAGE2 -D PIX_PER_WI=%d -D LOCAL_X=%d -D LOCAL_Y=%d", @@ -610,20 +620,7 @@ void cv::Canny( InputArray _src, OutputArray _dst, return; #endif -#ifdef USE_IPP_CANNY - CV_IPP_CHECK() - { - if( aperture_size == 3 && !L2gradient && 1 == cn ) - { - if (ippCanny(src, dst, (float)low_thresh, (float)high_thresh)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - } - } -#endif + CV_IPP_RUN(USE_IPP_CANNY && (aperture_size == 3 && !L2gradient && 1 == cn), ippCanny(src, dst, (float)low_thresh, (float)high_thresh)) #ifdef HAVE_TBB diff --git a/modules/imgproc/src/clahe.cpp b/modules/imgproc/src/clahe.cpp index 75edd18e4..fcd6c21a3 100644 --- a/modules/imgproc/src/clahe.cpp +++ b/modules/imgproc/src/clahe.cpp @@ -107,7 +107,7 @@ namespace clahe cv::UMat lut = _lut.getUMat(); size_t localThreads[3] = { 32, 8, 1 }; - size_t globalThreads[3] = { src.cols, src.rows, 1 }; + size_t globalThreads[3] = { (size_t)src.cols, (size_t)src.rows, 1 }; int idx = 0; idx = k.set(idx, cv::ocl::KernelArg::ReadOnlyNoSize(src)); diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 3c3e51255..95197ec03 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -96,11 +96,10 @@ #define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n)) -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) #define MAX_IPP8u 255 #define MAX_IPP16u 65535 #define MAX_IPP32f 1.0 -static IppStatus sts = ippInit(); #endif namespace cv @@ -200,7 +199,7 @@ void CvtColorLoop(const Mat& src, Mat& dst, const Cvt& cvt) parallel_for_(Range(0, src.rows), CvtColorLoop_Invoker(src, dst, cvt), src.total()/(double)(1<<16) ); } -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) typedef IppStatus (CV_STDCALL* ippiReorderFunc)(const void *, int, void *, int, IppiSize, const int *); typedef IppStatus (CV_STDCALL* ippiGeneralFunc)(const void *, int, void *, int, IppiSize); @@ -305,7 +304,7 @@ static ippiReorderFunc ippiSwapChannelsC3RTab[] = 0, (ippiReorderFunc)ippiSwapChannels_32f_C3R, 0, 0 }; -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 static ippiReorderFunc ippiSwapChannelsC4RTab[] = { (ippiReorderFunc)ippiSwapChannels_8u_C4R, 0, (ippiReorderFunc)ippiSwapChannels_16u_C4R, 0, @@ -379,7 +378,7 @@ static ippiGeneralFunc ippiHLS2RGBTab[] = 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0 }; -#if !defined(HAVE_IPP_ICV_ONLY) && 0 +#if !defined(HAVE_IPP_ICV_ONLY) && IPP_DISABLE_BLOCK static ippiGeneralFunc ippiRGBToLUVTab[] = { (ippiGeneralFunc)ippiRGBToLUV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToLUV_16u_C3R, 0, @@ -6693,7 +6692,7 @@ static bool ocl_cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) int pxPerWIy = dev.isIntel() && (dev.type() & ocl::Device::TYPE_GPU) ? 4 : 1; int pxPerWIx = 1; - size_t globalsize[] = { src.cols, (src.rows + pxPerWIy - 1) / pxPerWIy }; + size_t globalsize[] = { (size_t)src.cols, ((size_t)src.rows + pxPerWIy - 1) / pxPerWIy }; cv::String opts = format("-D depth=%d -D scn=%d -D PIX_PER_WI_Y=%d ", depth, scn, pxPerWIy); @@ -7336,7 +7335,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) switch( code ) { -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR: case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA: CV_Assert( scn == 3 || scn == 4 ); @@ -7369,7 +7368,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC3RTab[depth], 2, 1, 0)) ) return true; } -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 else if( code == CV_RGBA2BGRA ) { if( CvtColorIPPLoopCopy(src, dst, IPPReorderFunctor(ippiSwapChannelsC4RTab[depth], 2, 1, 0)) ) @@ -7379,7 +7378,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) return false; #endif -#if 0 // breaks OCL accuracy tests +#if IPP_DISABLE_BLOCK // breaks OCL accuracy tests case CV_BGR2BGR565: case CV_BGR2BGR555: case CV_RGB2BGR565: case CV_RGB2BGR555: case CV_BGRA2BGR565: case CV_BGRA2BGR555: case CV_RGBA2BGR565: case CV_RGBA2BGR555: CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U ); @@ -7416,6 +7415,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) return false; #endif +#if IPP_VERSION_X100 < 900 case CV_BGR5652BGR: case CV_BGR5552BGR: case CV_BGR5652RGB: case CV_BGR5552RGB: case CV_BGR5652BGRA: case CV_BGR5552BGRA: case CV_BGR5652RGBA: case CV_BGR5552RGBA: if(dcn <= 0) dcn = (code==CV_BGR5652BGRA || code==CV_BGR5552BGRA || code==CV_BGR5652RGBA || code==CV_BGR5552RGBA) ? 4 : 3; @@ -7449,8 +7449,9 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } CV_SUPPRESS_DEPRECATED_END return false; +#endif -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY: CV_Assert( scn == 3 || scn == 4 ); _dst.create(sz, CV_MAKETYPE(depth, 1)); @@ -7497,7 +7498,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) return false; #endif -#if 0 +#if IPP_DISABLE_BLOCK case CV_BGR2YCrCb: case CV_RGB2YCrCb: case CV_BGR2YUV: case CV_RGB2YUV: { @@ -7537,7 +7538,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } #endif -#if 0 +#if IPP_DISABLE_BLOCK case CV_YCrCb2BGR: case CV_YCrCb2RGB: case CV_YUV2BGR: case CV_YUV2RGB: { @@ -7578,7 +7579,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } #endif -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_BGR2XYZ: case CV_RGB2XYZ: CV_Assert( scn == 3 || scn == 4 ); _dst.create(sz, CV_MAKETYPE(depth, 3)); @@ -7607,7 +7608,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) return false; #endif -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_XYZ2BGR: case CV_XYZ2RGB: if( dcn <= 0 ) dcn = 3; CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) ); @@ -7638,7 +7639,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) return false; #endif -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_BGR2HSV: case CV_RGB2HSV: case CV_BGR2HSV_FULL: case CV_RGB2HSV_FULL: case CV_BGR2HLS: case CV_RGB2HLS: case CV_BGR2HLS_FULL: case CV_RGB2HLS_FULL: { @@ -7648,7 +7649,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) if( depth == CV_8U || depth == CV_16U ) { -#if 0 // breaks OCL accuracy tests +#if IPP_DISABLE_BLOCK // breaks OCL accuracy tests if( code == CV_BGR2HSV_FULL && scn == 3 ) { if( CvtColorIPPLoopCopy(src, dst, IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) ) @@ -7695,7 +7696,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } #endif -#if IPP_VERSION_MAJOR >= 7 +#if IPP_VERSION_X100 >= 700 case CV_HSV2BGR: case CV_HSV2RGB: case CV_HSV2BGR_FULL: case CV_HSV2RGB_FULL: case CV_HLS2BGR: case CV_HLS2RGB: case CV_HLS2BGR_FULL: case CV_HLS2RGB_FULL: { @@ -7751,7 +7752,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } #endif -#if 0 +#if IPP_DISABLE_BLOCK case CV_BGR2Lab: case CV_RGB2Lab: case CV_LBGR2Lab: case CV_LRGB2Lab: case CV_BGR2Luv: case CV_RGB2Luv: case CV_LBGR2Luv: case CV_LRGB2Luv: { @@ -7813,7 +7814,7 @@ static bool ipp_cvtColor( Mat &src, OutputArray _dst, int code, int dcn ) } #endif -#if 0 +#if IPP_DISABLE_BLOCK case CV_Lab2BGR: case CV_Lab2RGB: case CV_Lab2LBGR: case CV_Lab2LRGB: case CV_Luv2BGR: case CV_Luv2RGB: case CV_Luv2LBGR: case CV_Luv2LRGB: { diff --git a/modules/imgproc/src/colormap.cpp b/modules/imgproc/src/colormap.cpp index 8e5236ce4..6d03d7b5f 100644 --- a/modules/imgproc/src/colormap.cpp +++ b/modules/imgproc/src/colormap.cpp @@ -188,7 +188,7 @@ namespace colormap void init(int n) { float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - float g[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; + float g[] = { 0, 0.01587301587301587f, 0.03174603174603174f, 0.04761904761904762f, 0.06349206349206349f, 0.07936507936507936f, 0.09523809523809523f, 0.1111111111111111f, 0.126984126984127f, 0.1428571428571428f, 0.1587301587301587f, 0.1746031746031746f, 0.1904761904761905f, 0.2063492063492063f, 0.2222222222222222f, 0.2380952380952381f, 0.253968253968254f, 0.2698412698412698f, 0.2857142857142857f, 0.3015873015873016f, 0.3174603174603174f, 0.3333333333333333f, 0.3492063492063492f, 0.3650793650793651f, 0.3809523809523809f, 0.3968253968253968f, 0.4126984126984127f, 0.4285714285714285f, 0.4444444444444444f, 0.4603174603174603f, 0.4761904761904762f, 0.492063492063492f, 0.5079365079365079f, 0.5238095238095238f, 0.5396825396825397f, 0.5555555555555556f, 0.5714285714285714f, 0.5873015873015873f, 0.6031746031746031f, 0.6190476190476191f, 0.6349206349206349f, 0.6507936507936508f, 0.6666666666666666f, 0.6825396825396826f, 0.6984126984126984f, 0.7142857142857143f, 0.7301587301587301f, 0.746031746031746f, 0.7619047619047619f, 0.7777777777777778f, 0.7936507936507936f, 0.8095238095238095f, 0.8253968253968254f, 0.8412698412698413f, 0.8571428571428571f, 0.873015873015873f, 0.8888888888888888f, 0.9047619047619048f, 0.9206349206349206f, 0.9365079365079365f, 0.9523809523809523f, 0.9682539682539683f, 0.9841269841269841f, 1}; float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, @@ -211,9 +211,9 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0.01388888888888889, 0.02777777777777778, 0.04166666666666666, 0.05555555555555555, 0.06944444444444445, 0.08333333333333333, 0.09722222222222221, 0.1111111111111111, 0.125, 0.1388888888888889, 0.1527777777777778, 0.1666666666666667, 0.1805555555555556, 0.1944444444444444, 0.2083333333333333, 0.2222222222222222, 0.2361111111111111, 0.25, 0.2638888888888889, 0.2777777777777778, 0.2916666666666666, 0.3055555555555555, 0.3194444444444444, 0.3333333333333333, 0.3472222222222222, 0.3611111111111111, 0.375, 0.3888888888888888, 0.4027777777777777, 0.4166666666666666, 0.4305555555555555, 0.4444444444444444, 0.4583333333333333, 0.4722222222222222, 0.4861111111111112, 0.5, 0.5138888888888888, 0.5277777777777778, 0.5416666666666667, 0.5555555555555556, 0.5694444444444444, 0.5833333333333333, 0.5972222222222222, 0.611111111111111, 0.6249999999999999, 0.6388888888888888, 0.6527777777777778, 0.6726190476190474, 0.6944444444444442, 0.7162698412698412, 0.7380952380952381, 0.7599206349206349, 0.7817460317460316, 0.8035714285714286, 0.8253968253968254, 0.8472222222222221, 0.8690476190476188, 0.8908730158730158, 0.9126984126984128, 0.9345238095238095, 0.9563492063492063, 0.978174603174603, 1}; - float g[] = { 0, 0.01388888888888889, 0.02777777777777778, 0.04166666666666666, 0.05555555555555555, 0.06944444444444445, 0.08333333333333333, 0.09722222222222221, 0.1111111111111111, 0.125, 0.1388888888888889, 0.1527777777777778, 0.1666666666666667, 0.1805555555555556, 0.1944444444444444, 0.2083333333333333, 0.2222222222222222, 0.2361111111111111, 0.25, 0.2638888888888889, 0.2777777777777778, 0.2916666666666666, 0.3055555555555555, 0.3194444444444444, 0.3353174603174602, 0.3544973544973544, 0.3736772486772486, 0.3928571428571428, 0.412037037037037, 0.4312169312169312, 0.4503968253968254, 0.4695767195767195, 0.4887566137566137, 0.5079365079365078, 0.5271164021164021, 0.5462962962962963, 0.5654761904761904, 0.5846560846560845, 0.6038359788359787, 0.623015873015873, 0.6421957671957671, 0.6613756613756612, 0.6805555555555555, 0.6997354497354497, 0.7189153439153438, 0.7380952380952379, 0.7572751322751322, 0.7764550264550264, 0.7916666666666666, 0.8055555555555555, 0.8194444444444444, 0.8333333333333334, 0.8472222222222222, 0.861111111111111, 0.875, 0.8888888888888888, 0.9027777777777777, 0.9166666666666665, 0.9305555555555555, 0.9444444444444444, 0.9583333333333333, 0.9722222222222221, 0.986111111111111, 1}; - float b[] = { 0, 0.01917989417989418, 0.03835978835978836, 0.05753968253968253, 0.07671957671957672, 0.09589947089947089, 0.1150793650793651, 0.1342592592592592, 0.1534391534391534, 0.1726190476190476, 0.1917989417989418, 0.210978835978836, 0.2301587301587301, 0.2493386243386243, 0.2685185185185185, 0.2876984126984127, 0.3068783068783069, 0.326058201058201, 0.3452380952380952, 0.3644179894179894, 0.3835978835978835, 0.4027777777777777, 0.4219576719576719, 0.4411375661375661, 0.4583333333333333, 0.4722222222222222, 0.4861111111111111, 0.5, 0.5138888888888888, 0.5277777777777777, 0.5416666666666666, 0.5555555555555556, 0.5694444444444444, 0.5833333333333333, 0.5972222222222222, 0.6111111111111112, 0.625, 0.6388888888888888, 0.6527777777777778, 0.6666666666666667, 0.6805555555555556, 0.6944444444444444, 0.7083333333333333, 0.7222222222222222, 0.736111111111111, 0.7499999999999999, 0.7638888888888888, 0.7777777777777778, 0.7916666666666666, 0.8055555555555555, 0.8194444444444444, 0.8333333333333334, 0.8472222222222222, 0.861111111111111, 0.875, 0.8888888888888888, 0.9027777777777777, 0.9166666666666665, 0.9305555555555555, 0.9444444444444444, 0.9583333333333333, 0.9722222222222221, 0.986111111111111, 1}; + float r[] = { 0, 0.01388888888888889f, 0.02777777777777778f, 0.04166666666666666f, 0.05555555555555555f, 0.06944444444444445f, 0.08333333333333333f, 0.09722222222222221f, 0.1111111111111111f, 0.125f, 0.1388888888888889f, 0.1527777777777778f, 0.1666666666666667f, 0.1805555555555556f, 0.1944444444444444f, 0.2083333333333333f, 0.2222222222222222f, 0.2361111111111111f, 0.25f, 0.2638888888888889f, 0.2777777777777778f, 0.2916666666666666f, 0.3055555555555555f, 0.3194444444444444f, 0.3333333333333333f, 0.3472222222222222f, 0.3611111111111111f, 0.375f, 0.3888888888888888f, 0.4027777777777777f, 0.4166666666666666f, 0.4305555555555555f, 0.4444444444444444f, 0.4583333333333333f, 0.4722222222222222f, 0.4861111111111112f, 0.5f, 0.5138888888888888f, 0.5277777777777778f, 0.5416666666666667f, 0.5555555555555556f, 0.5694444444444444f, 0.5833333333333333f, 0.5972222222222222f, 0.611111111111111f, 0.6249999999999999f, 0.6388888888888888f, 0.6527777777777778f, 0.6726190476190474f, 0.6944444444444442f, 0.7162698412698412f, 0.7380952380952381f, 0.7599206349206349f, 0.7817460317460316f, 0.8035714285714286f, 0.8253968253968254f, 0.8472222222222221f, 0.8690476190476188f, 0.8908730158730158f, 0.9126984126984128f, 0.9345238095238095f, 0.9563492063492063f, 0.978174603174603f, 1}; + float g[] = { 0, 0.01388888888888889f, 0.02777777777777778f, 0.04166666666666666f, 0.05555555555555555f, 0.06944444444444445f, 0.08333333333333333f, 0.09722222222222221f, 0.1111111111111111f, 0.125f, 0.1388888888888889f, 0.1527777777777778f, 0.1666666666666667f, 0.1805555555555556f, 0.1944444444444444f, 0.2083333333333333f, 0.2222222222222222f, 0.2361111111111111f, 0.25f, 0.2638888888888889f, 0.2777777777777778f, 0.2916666666666666f, 0.3055555555555555f, 0.3194444444444444f, 0.3353174603174602f, 0.3544973544973544f, 0.3736772486772486f, 0.3928571428571428f, 0.412037037037037f, 0.4312169312169312f, 0.4503968253968254f, 0.4695767195767195f, 0.4887566137566137f, 0.5079365079365078f, 0.5271164021164021f, 0.5462962962962963f, 0.5654761904761904f, 0.5846560846560845f, 0.6038359788359787f, 0.623015873015873f, 0.6421957671957671f, 0.6613756613756612f, 0.6805555555555555f, 0.6997354497354497f, 0.7189153439153438f, 0.7380952380952379f, 0.7572751322751322f, 0.7764550264550264f, 0.7916666666666666f, 0.8055555555555555f, 0.8194444444444444f, 0.8333333333333334f, 0.8472222222222222f, 0.861111111111111f, 0.875f, 0.8888888888888888f, 0.9027777777777777f, 0.9166666666666665f, 0.9305555555555555f, 0.9444444444444444f, 0.9583333333333333f, 0.9722222222222221f, 0.986111111111111f, 1}; + float b[] = { 0, 0.01917989417989418f, 0.03835978835978836f, 0.05753968253968253f, 0.07671957671957672f, 0.09589947089947089f, 0.1150793650793651f, 0.1342592592592592f, 0.1534391534391534f, 0.1726190476190476f, 0.1917989417989418f, 0.210978835978836f, 0.2301587301587301f, 0.2493386243386243f, 0.2685185185185185f, 0.2876984126984127f, 0.3068783068783069f, 0.326058201058201f, 0.3452380952380952f, 0.3644179894179894f, 0.3835978835978835f, 0.4027777777777777f, 0.4219576719576719f, 0.4411375661375661f, 0.4583333333333333f, 0.4722222222222222f, 0.4861111111111111f, 0.5f, 0.5138888888888888f, 0.5277777777777777f, 0.5416666666666666f, 0.5555555555555556f, 0.5694444444444444f, 0.5833333333333333f, 0.5972222222222222f, 0.6111111111111112f, 0.625f, 0.6388888888888888f, 0.6527777777777778f, 0.6666666666666667f, 0.6805555555555556f, 0.6944444444444444f, 0.7083333333333333f, 0.7222222222222222f, 0.736111111111111f, 0.7499999999999999f, 0.7638888888888888f, 0.7777777777777778f, 0.7916666666666666f, 0.8055555555555555f, 0.8194444444444444f, 0.8333333333333334f, 0.8472222222222222f, 0.861111111111111f, 0.875f, 0.8888888888888888f, 0.9027777777777777f, 0.9166666666666665f, 0.9305555555555555f, 0.9444444444444444f, 0.9583333333333333f, 0.9722222222222221f, 0.986111111111111f, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -241,9 +241,9 @@ namespace colormap // breakpoints Mat X = linspace(0,1,256); // define the basemap - float r[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00588235294117645,0.02156862745098032,0.03725490196078418,0.05294117647058827,0.06862745098039214,0.084313725490196,0.1000000000000001,0.115686274509804,0.1313725490196078,0.1470588235294117,0.1627450980392156,0.1784313725490196,0.1941176470588235,0.2098039215686274,0.2254901960784315,0.2411764705882353,0.2568627450980392,0.2725490196078431,0.2882352941176469,0.303921568627451,0.3196078431372549,0.3352941176470587,0.3509803921568628,0.3666666666666667,0.3823529411764706,0.3980392156862744,0.4137254901960783,0.4294117647058824,0.4450980392156862,0.4607843137254901,0.4764705882352942,0.4921568627450981,0.5078431372549019,0.5235294117647058,0.5392156862745097,0.5549019607843135,0.5705882352941174,0.5862745098039217,0.6019607843137256,0.6176470588235294,0.6333333333333333,0.6490196078431372,0.664705882352941,0.6803921568627449,0.6960784313725492,0.7117647058823531,0.7274509803921569,0.7431372549019608,0.7588235294117647,0.7745098039215685,0.7901960784313724,0.8058823529411763,0.8215686274509801,0.8372549019607844,0.8529411764705883,0.8686274509803922,0.884313725490196,0.8999999999999999,0.9156862745098038,0.9313725490196076,0.947058823529412,0.9627450980392158,0.9784313725490197,0.9941176470588236,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9862745098039216,0.9705882352941178,0.9549019607843139,0.93921568627451,0.9235294117647062,0.9078431372549018,0.892156862745098,0.8764705882352941,0.8607843137254902,0.8450980392156864,0.8294117647058825,0.8137254901960786,0.7980392156862743,0.7823529411764705,0.7666666666666666,0.7509803921568627,0.7352941176470589,0.719607843137255,0.7039215686274511,0.6882352941176473,0.6725490196078434,0.6568627450980391,0.6411764705882352,0.6254901960784314,0.6098039215686275,0.5941176470588236,0.5784313725490198,0.5627450980392159,0.5470588235294116,0.5313725490196077,0.5156862745098039,0.5}; - float g[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001960784313725483,0.01764705882352935,0.03333333333333333,0.0490196078431373,0.06470588235294117,0.08039215686274503,0.09607843137254901,0.111764705882353,0.1274509803921569,0.1431372549019607,0.1588235294117647,0.1745098039215687,0.1901960784313725,0.2058823529411764,0.2215686274509804,0.2372549019607844,0.2529411764705882,0.2686274509803921,0.2843137254901961,0.3,0.3156862745098039,0.3313725490196078,0.3470588235294118,0.3627450980392157,0.3784313725490196,0.3941176470588235,0.4098039215686274,0.4254901960784314,0.4411764705882353,0.4568627450980391,0.4725490196078431,0.4882352941176471,0.503921568627451,0.5196078431372548,0.5352941176470587,0.5509803921568628,0.5666666666666667,0.5823529411764705,0.5980392156862746,0.6137254901960785,0.6294117647058823,0.6450980392156862,0.6607843137254901,0.6764705882352942,0.692156862745098,0.7078431372549019,0.723529411764706,0.7392156862745098,0.7549019607843137,0.7705882352941176,0.7862745098039214,0.8019607843137255,0.8176470588235294,0.8333333333333333,0.8490196078431373,0.8647058823529412,0.8803921568627451,0.8960784313725489,0.9117647058823528,0.9274509803921569,0.9431372549019608,0.9588235294117646,0.9745098039215687,0.9901960784313726,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9901960784313726,0.9745098039215687,0.9588235294117649,0.943137254901961,0.9274509803921571,0.9117647058823528,0.8960784313725489,0.8803921568627451,0.8647058823529412,0.8490196078431373,0.8333333333333335,0.8176470588235296,0.8019607843137253,0.7862745098039214,0.7705882352941176,0.7549019607843137,0.7392156862745098,0.723529411764706,0.7078431372549021,0.6921568627450982,0.6764705882352944,0.6607843137254901,0.6450980392156862,0.6294117647058823,0.6137254901960785,0.5980392156862746,0.5823529411764707,0.5666666666666669,0.5509803921568626,0.5352941176470587,0.5196078431372548,0.503921568627451,0.4882352941176471,0.4725490196078432,0.4568627450980394,0.4411764705882355,0.4254901960784316,0.4098039215686273,0.3941176470588235,0.3784313725490196,0.3627450980392157,0.3470588235294119,0.331372549019608,0.3156862745098041,0.2999999999999998,0.284313725490196,0.2686274509803921,0.2529411764705882,0.2372549019607844,0.2215686274509805,0.2058823529411766,0.1901960784313728,0.1745098039215689,0.1588235294117646,0.1431372549019607,0.1274509803921569,0.111764705882353,0.09607843137254912,0.08039215686274526,0.06470588235294139,0.04901960784313708,0.03333333333333321,0.01764705882352935,0.001960784313725483,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - float b[] = {0.5,0.5156862745098039,0.5313725490196078,0.5470588235294118,0.5627450980392157,0.5784313725490196,0.5941176470588235,0.6098039215686275,0.6254901960784314,0.6411764705882352,0.6568627450980392,0.6725490196078432,0.6882352941176471,0.7039215686274509,0.7196078431372549,0.7352941176470589,0.7509803921568627,0.7666666666666666,0.7823529411764706,0.7980392156862746,0.8137254901960784,0.8294117647058823,0.8450980392156863,0.8607843137254902,0.8764705882352941,0.892156862745098,0.907843137254902,0.9235294117647059,0.9392156862745098,0.9549019607843137,0.9705882352941176,0.9862745098039216,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9941176470588236,0.9784313725490197,0.9627450980392158,0.9470588235294117,0.9313725490196079,0.915686274509804,0.8999999999999999,0.884313725490196,0.8686274509803922,0.8529411764705883,0.8372549019607844,0.8215686274509804,0.8058823529411765,0.7901960784313726,0.7745098039215685,0.7588235294117647,0.7431372549019608,0.7274509803921569,0.7117647058823531,0.696078431372549,0.6803921568627451,0.6647058823529413,0.6490196078431372,0.6333333333333333,0.6176470588235294,0.6019607843137256,0.5862745098039217,0.5705882352941176,0.5549019607843138,0.5392156862745099,0.5235294117647058,0.5078431372549019,0.4921568627450981,0.4764705882352942,0.4607843137254903,0.4450980392156865,0.4294117647058826,0.4137254901960783,0.3980392156862744,0.3823529411764706,0.3666666666666667,0.3509803921568628,0.335294117647059,0.3196078431372551,0.3039215686274508,0.2882352941176469,0.2725490196078431,0.2568627450980392,0.2411764705882353,0.2254901960784315,0.2098039215686276,0.1941176470588237,0.1784313725490199,0.1627450980392156,0.1470588235294117,0.1313725490196078,0.115686274509804,0.1000000000000001,0.08431372549019622,0.06862745098039236,0.05294117647058805,0.03725490196078418,0.02156862745098032,0.00588235294117645,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + float r[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00588235294117645f,0.02156862745098032f,0.03725490196078418f,0.05294117647058827f,0.06862745098039214f,0.084313725490196f,0.1000000000000001f,0.115686274509804f,0.1313725490196078f,0.1470588235294117f,0.1627450980392156f,0.1784313725490196f,0.1941176470588235f,0.2098039215686274f,0.2254901960784315f,0.2411764705882353f,0.2568627450980392f,0.2725490196078431f,0.2882352941176469f,0.303921568627451f,0.3196078431372549f,0.3352941176470587f,0.3509803921568628f,0.3666666666666667f,0.3823529411764706f,0.3980392156862744f,0.4137254901960783f,0.4294117647058824f,0.4450980392156862f,0.4607843137254901f,0.4764705882352942f,0.4921568627450981f,0.5078431372549019f,0.5235294117647058f,0.5392156862745097f,0.5549019607843135f,0.5705882352941174f,0.5862745098039217f,0.6019607843137256f,0.6176470588235294f,0.6333333333333333f,0.6490196078431372f,0.664705882352941f,0.6803921568627449f,0.6960784313725492f,0.7117647058823531f,0.7274509803921569f,0.7431372549019608f,0.7588235294117647f,0.7745098039215685f,0.7901960784313724f,0.8058823529411763f,0.8215686274509801f,0.8372549019607844f,0.8529411764705883f,0.8686274509803922f,0.884313725490196f,0.8999999999999999f,0.9156862745098038f,0.9313725490196076f,0.947058823529412f,0.9627450980392158f,0.9784313725490197f,0.9941176470588236f,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9862745098039216f,0.9705882352941178f,0.9549019607843139f,0.93921568627451f,0.9235294117647062f,0.9078431372549018f,0.892156862745098f,0.8764705882352941f,0.8607843137254902f,0.8450980392156864f,0.8294117647058825f,0.8137254901960786f,0.7980392156862743f,0.7823529411764705f,0.7666666666666666f,0.7509803921568627f,0.7352941176470589f,0.719607843137255f,0.7039215686274511f,0.6882352941176473f,0.6725490196078434f,0.6568627450980391f,0.6411764705882352f,0.6254901960784314f,0.6098039215686275f,0.5941176470588236f,0.5784313725490198f,0.5627450980392159f,0.5470588235294116f,0.5313725490196077f,0.5156862745098039f,0.5f}; + float g[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001960784313725483f,0.01764705882352935f,0.03333333333333333f,0.0490196078431373f,0.06470588235294117f,0.08039215686274503f,0.09607843137254901f,0.111764705882353f,0.1274509803921569f,0.1431372549019607f,0.1588235294117647f,0.1745098039215687f,0.1901960784313725f,0.2058823529411764f,0.2215686274509804f,0.2372549019607844f,0.2529411764705882f,0.2686274509803921f,0.2843137254901961f,0.3f,0.3156862745098039f,0.3313725490196078f,0.3470588235294118f,0.3627450980392157f,0.3784313725490196f,0.3941176470588235f,0.4098039215686274f,0.4254901960784314f,0.4411764705882353f,0.4568627450980391f,0.4725490196078431f,0.4882352941176471f,0.503921568627451f,0.5196078431372548f,0.5352941176470587f,0.5509803921568628f,0.5666666666666667f,0.5823529411764705f,0.5980392156862746f,0.6137254901960785f,0.6294117647058823f,0.6450980392156862f,0.6607843137254901f,0.6764705882352942f,0.692156862745098f,0.7078431372549019f,0.723529411764706f,0.7392156862745098f,0.7549019607843137f,0.7705882352941176f,0.7862745098039214f,0.8019607843137255f,0.8176470588235294f,0.8333333333333333f,0.8490196078431373f,0.8647058823529412f,0.8803921568627451f,0.8960784313725489f,0.9117647058823528f,0.9274509803921569f,0.9431372549019608f,0.9588235294117646f,0.9745098039215687f,0.9901960784313726f,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9901960784313726f,0.9745098039215687f,0.9588235294117649f,0.943137254901961f,0.9274509803921571f,0.9117647058823528f,0.8960784313725489f,0.8803921568627451f,0.8647058823529412f,0.8490196078431373f,0.8333333333333335f,0.8176470588235296f,0.8019607843137253f,0.7862745098039214f,0.7705882352941176f,0.7549019607843137f,0.7392156862745098f,0.723529411764706f,0.7078431372549021f,0.6921568627450982f,0.6764705882352944f,0.6607843137254901f,0.6450980392156862f,0.6294117647058823f,0.6137254901960785f,0.5980392156862746f,0.5823529411764707f,0.5666666666666669f,0.5509803921568626f,0.5352941176470587f,0.5196078431372548f,0.503921568627451f,0.4882352941176471f,0.4725490196078432f,0.4568627450980394f,0.4411764705882355f,0.4254901960784316f,0.4098039215686273f,0.3941176470588235f,0.3784313725490196f,0.3627450980392157f,0.3470588235294119f,0.331372549019608f,0.3156862745098041f,0.2999999999999998f,0.284313725490196f,0.2686274509803921f,0.2529411764705882f,0.2372549019607844f,0.2215686274509805f,0.2058823529411766f,0.1901960784313728f,0.1745098039215689f,0.1588235294117646f,0.1431372549019607f,0.1274509803921569f,0.111764705882353f,0.09607843137254912f,0.08039215686274526f,0.06470588235294139f,0.04901960784313708f,0.03333333333333321f,0.01764705882352935f,0.001960784313725483f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + float b[] = {0.5f,0.5156862745098039f,0.5313725490196078f,0.5470588235294118f,0.5627450980392157f,0.5784313725490196f,0.5941176470588235f,0.6098039215686275f,0.6254901960784314f,0.6411764705882352f,0.6568627450980392f,0.6725490196078432f,0.6882352941176471f,0.7039215686274509f,0.7196078431372549f,0.7352941176470589f,0.7509803921568627f,0.7666666666666666f,0.7823529411764706f,0.7980392156862746f,0.8137254901960784f,0.8294117647058823f,0.8450980392156863f,0.8607843137254902f,0.8764705882352941f,0.892156862745098f,0.907843137254902f,0.9235294117647059f,0.9392156862745098f,0.9549019607843137f,0.9705882352941176f,0.9862745098039216f,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.9941176470588236f,0.9784313725490197f,0.9627450980392158f,0.9470588235294117f,0.9313725490196079f,0.915686274509804f,0.8999999999999999f,0.884313725490196f,0.8686274509803922f,0.8529411764705883f,0.8372549019607844f,0.8215686274509804f,0.8058823529411765f,0.7901960784313726f,0.7745098039215685f,0.7588235294117647f,0.7431372549019608f,0.7274509803921569f,0.7117647058823531f,0.696078431372549f,0.6803921568627451f,0.6647058823529413f,0.6490196078431372f,0.6333333333333333f,0.6176470588235294f,0.6019607843137256f,0.5862745098039217f,0.5705882352941176f,0.5549019607843138f,0.5392156862745099f,0.5235294117647058f,0.5078431372549019f,0.4921568627450981f,0.4764705882352942f,0.4607843137254903f,0.4450980392156865f,0.4294117647058826f,0.4137254901960783f,0.3980392156862744f,0.3823529411764706f,0.3666666666666667f,0.3509803921568628f,0.335294117647059f,0.3196078431372551f,0.3039215686274508f,0.2882352941176469f,0.2725490196078431f,0.2568627450980392f,0.2411764705882353f,0.2254901960784315f,0.2098039215686276f,0.1941176470588237f,0.1784313725490199f,0.1627450980392156f,0.1470588235294117f,0.1313725490196078f,0.115686274509804f,0.1000000000000001f,0.08431372549019622f,0.06862745098039236f,0.05294117647058805f,0.03725490196078418f,0.02156862745098032f,0.00588235294117645f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // now build lookup table this->_lut = ColorMap::linear_colormap(X, Mat(256,1, CV_32FC1, r).clone(), // red @@ -265,9 +265,9 @@ namespace colormap } void init(int n) { - float r[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; - float g[] = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; - float b[] = {1.0, 0.95, 0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6, 0.55, 0.5}; + float r[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; + float g[] = {0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f,}; + float b[] = {1.0, 0.95f, 0.9f, 0.85f, 0.8f, 0.75f, 0.7f, 0.65f, 0.6f, 0.55f, 0.5f}; Mat X = linspace(0,1,11); this->_lut = ColorMap::linear_colormap(X, Mat(11,1, CV_32FC1, r).clone(), // red @@ -289,9 +289,9 @@ namespace colormap } void init(int n) { - float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9365079365079367, 0.8571428571428572, 0.7777777777777777, 0.6984126984126986, 0.6190476190476191, 0.53968253968254, 0.4603174603174605, 0.3809523809523814, 0.3015873015873018, 0.2222222222222223, 0.1428571428571432, 0.06349206349206415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03174603174603208, 0.08465608465608465, 0.1375661375661377, 0.1904761904761907, 0.2433862433862437, 0.2962962962962963, 0.3492063492063493, 0.4021164021164023, 0.4550264550264553, 0.5079365079365079, 0.5608465608465609, 0.6137566137566139, 0.666666666666667}; - float g[] = { 0, 0.03968253968253968, 0.07936507936507936, 0.119047619047619, 0.1587301587301587, 0.1984126984126984, 0.2380952380952381, 0.2777777777777778, 0.3174603174603174, 0.3571428571428571, 0.3968253968253968, 0.4365079365079365, 0.4761904761904762, 0.5158730158730158, 0.5555555555555556, 0.5952380952380952, 0.6349206349206349, 0.6746031746031745, 0.7142857142857142, 0.753968253968254, 0.7936507936507936, 0.8333333333333333, 0.873015873015873, 0.9126984126984127, 0.9523809523809523, 0.992063492063492, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9841269841269842, 0.9047619047619047, 0.8253968253968256, 0.7460317460317465, 0.666666666666667, 0.587301587301587, 0.5079365079365079, 0.4285714285714288, 0.3492063492063493, 0.2698412698412698, 0.1904761904761907, 0.1111111111111116, 0.03174603174603208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.01587301587301582, 0.09523809523809534, 0.1746031746031744, 0.2539682539682535, 0.333333333333333, 0.412698412698413, 0.4920634920634921, 0.5714285714285712, 0.6507936507936507, 0.7301587301587302, 0.8095238095238093, 0.8888888888888884, 0.9682539682539679, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9365079365079367f, 0.8571428571428572f, 0.7777777777777777f, 0.6984126984126986f, 0.6190476190476191f, 0.53968253968254f, 0.4603174603174605f, 0.3809523809523814f, 0.3015873015873018f, 0.2222222222222223f, 0.1428571428571432f, 0.06349206349206415f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03174603174603208f, 0.08465608465608465f, 0.1375661375661377f, 0.1904761904761907f, 0.2433862433862437f, 0.2962962962962963f, 0.3492063492063493f, 0.4021164021164023f, 0.4550264550264553f, 0.5079365079365079f, 0.5608465608465609f, 0.6137566137566139f, 0.666666666666667f}; + float g[] = { 0, 0.03968253968253968f, 0.07936507936507936f, 0.119047619047619f, 0.1587301587301587f, 0.1984126984126984f, 0.2380952380952381f, 0.2777777777777778f, 0.3174603174603174f, 0.3571428571428571f, 0.3968253968253968f, 0.4365079365079365f, 0.4761904761904762f, 0.5158730158730158f, 0.5555555555555556f, 0.5952380952380952f, 0.6349206349206349f, 0.6746031746031745f, 0.7142857142857142f, 0.753968253968254f, 0.7936507936507936f, 0.8333333333333333f, 0.873015873015873f, 0.9126984126984127f, 0.9523809523809523f, 0.992063492063492f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9841269841269842f, 0.9047619047619047f, 0.8253968253968256f, 0.7460317460317465f, 0.666666666666667f, 0.587301587301587f, 0.5079365079365079f, 0.4285714285714288f, 0.3492063492063493f, 0.2698412698412698f, 0.1904761904761907f, 0.1111111111111116f, 0.03174603174603208f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.01587301587301582f, 0.09523809523809534f, 0.1746031746031744f, 0.2539682539682535f, 0.333333333333333f, 0.412698412698413f, 0.4920634920634921f, 0.5714285714285712f, 0.6507936507936507f, 0.7301587301587302f, 0.8095238095238093f, 0.8888888888888884f, 0.9682539682539679f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -313,9 +313,9 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.04761904761904762, 0.09523809523809523, 0.1428571428571428, 0.1904761904761905, 0.2380952380952381, 0.2857142857142857, 0.3333333333333333, 0.3809523809523809, 0.4285714285714285, 0.4761904761904762, 0.5238095238095238, 0.5714285714285714, 0.6190476190476191, 0.6666666666666666, 0.7142857142857143, 0.7619047619047619, 0.8095238095238095, 0.8571428571428571, 0.9047619047619048, 0.9523809523809523, 1}; - float g[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.02380952380952381, 0.04761904761904762, 0.07142857142857142, 0.09523809523809523, 0.119047619047619, 0.1428571428571428, 0.1666666666666667, 0.1904761904761905, 0.2142857142857143, 0.2380952380952381, 0.2619047619047619, 0.2857142857142857, 0.3095238095238095, 0.3333333333333333, 0.3571428571428572, 0.3809523809523809, 0.4047619047619048, 0.4285714285714285, 0.4523809523809524, 0.4761904761904762, 0.5, 0.5238095238095238, 0.5476190476190477, 0.5714285714285714, 0.5952380952380952, 0.6190476190476191, 0.6428571428571429, 0.6666666666666666, 0.6904761904761905, 0.7142857142857143, 0.7380952380952381, 0.7619047619047619, 0.7857142857142857, 0.8095238095238095, 0.8333333333333334, 0.8571428571428571, 0.8809523809523809, 0.9047619047619048, 0.9285714285714286, 0.9523809523809523, 0.9761904761904762, 1}; - float b[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; + float r[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.04761904761904762f, 0.09523809523809523f, 0.1428571428571428f, 0.1904761904761905f, 0.2380952380952381f, 0.2857142857142857f, 0.3333333333333333f, 0.3809523809523809f, 0.4285714285714285f, 0.4761904761904762f, 0.5238095238095238f, 0.5714285714285714f, 0.6190476190476191f, 0.6666666666666666f, 0.7142857142857143f, 0.7619047619047619f, 0.8095238095238095f, 0.8571428571428571f, 0.9047619047619048f, 0.9523809523809523f, 1}; + float g[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.02380952380952381f, 0.04761904761904762f, 0.07142857142857142f, 0.09523809523809523f, 0.119047619047619f, 0.1428571428571428f, 0.1666666666666667f, 0.1904761904761905f, 0.2142857142857143f, 0.2380952380952381f, 0.2619047619047619f, 0.2857142857142857f, 0.3095238095238095f, 0.3333333333333333f, 0.3571428571428572f, 0.3809523809523809f, 0.4047619047619048f, 0.4285714285714285f, 0.4523809523809524f, 0.4761904761904762f, 0.5f, 0.5238095238095238f, 0.5476190476190477f, 0.5714285714285714f, 0.5952380952380952f, 0.6190476190476191f, 0.6428571428571429f, 0.6666666666666666f, 0.6904761904761905f, 0.7142857142857143f, 0.7380952380952381f, 0.7619047619047619f, 0.7857142857142857f, 0.8095238095238095f, 0.8333333333333334f, 0.8571428571428571f, 0.8809523809523809f, 0.9047619047619048f, 0.9285714285714286f, 0.9523809523809523f, 0.9761904761904762f, 1}; + float b[] = { 0, 0.01587301587301587f, 0.03174603174603174f, 0.04761904761904762f, 0.06349206349206349f, 0.07936507936507936f, 0.09523809523809523f, 0.1111111111111111f, 0.126984126984127f, 0.1428571428571428f, 0.1587301587301587f, 0.1746031746031746f, 0.1904761904761905f, 0.2063492063492063f, 0.2222222222222222f, 0.2380952380952381f, 0.253968253968254f, 0.2698412698412698f, 0.2857142857142857f, 0.3015873015873016f, 0.3174603174603174f, 0.3333333333333333f, 0.3492063492063492f, 0.3650793650793651f, 0.3809523809523809f, 0.3968253968253968f, 0.4126984126984127f, 0.4285714285714285f, 0.4444444444444444f, 0.4603174603174603f, 0.4761904761904762f, 0.492063492063492f, 0.5079365079365079f, 0.5238095238095238f, 0.5396825396825397f, 0.5555555555555556f, 0.5714285714285714f, 0.5873015873015873f, 0.6031746031746031f, 0.6190476190476191f, 0.6349206349206349f, 0.6507936507936508f, 0.6666666666666666f, 0.6825396825396826f, 0.6984126984126984f, 0.7142857142857143f, 0.7301587301587301f, 0.746031746031746f, 0.7619047619047619f, 0.7777777777777778f, 0.7936507936507936f, 0.8095238095238095f, 0.8253968253968254f, 0.8412698412698413f, 0.8571428571428571f, 0.873015873015873f, 0.8888888888888888f, 0.9047619047619048f, 0.9206349206349206f, 0.9365079365079365f, 0.9523809523809523f, 0.9682539682539683f, 0.9841269841269841f, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -337,9 +337,9 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; - float g[] = { 0.5, 0.5079365079365079, 0.5158730158730158, 0.5238095238095238, 0.5317460317460317, 0.5396825396825397, 0.5476190476190477, 0.5555555555555556, 0.5634920634920635, 0.5714285714285714, 0.5793650793650793, 0.5873015873015873, 0.5952380952380952, 0.6031746031746031, 0.6111111111111112, 0.6190476190476191, 0.626984126984127, 0.6349206349206349, 0.6428571428571428, 0.6507936507936508, 0.6587301587301587, 0.6666666666666666, 0.6746031746031746, 0.6825396825396826, 0.6904761904761905, 0.6984126984126984, 0.7063492063492063, 0.7142857142857143, 0.7222222222222222, 0.7301587301587301, 0.7380952380952381, 0.746031746031746, 0.753968253968254, 0.7619047619047619, 0.7698412698412698, 0.7777777777777778, 0.7857142857142857, 0.7936507936507937, 0.8015873015873016, 0.8095238095238095, 0.8174603174603174, 0.8253968253968254, 0.8333333333333333, 0.8412698412698413, 0.8492063492063492, 0.8571428571428572, 0.8650793650793651, 0.873015873015873, 0.8809523809523809, 0.8888888888888888, 0.8968253968253967, 0.9047619047619048, 0.9126984126984127, 0.9206349206349207, 0.9285714285714286, 0.9365079365079365, 0.9444444444444444, 0.9523809523809523, 0.9603174603174602, 0.9682539682539683, 0.9761904761904762, 0.9841269841269842, 0.9920634920634921, 1}; - float b[] = { 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4}; + float r[] = { 0, 0.01587301587301587f, 0.03174603174603174f, 0.04761904761904762f, 0.06349206349206349f, 0.07936507936507936f, 0.09523809523809523f, 0.1111111111111111f, 0.126984126984127f, 0.1428571428571428f, 0.1587301587301587f, 0.1746031746031746f, 0.1904761904761905f, 0.2063492063492063f, 0.2222222222222222f, 0.2380952380952381f, 0.253968253968254f, 0.2698412698412698f, 0.2857142857142857f, 0.3015873015873016f, 0.3174603174603174f, 0.3333333333333333f, 0.3492063492063492f, 0.3650793650793651f, 0.3809523809523809f, 0.3968253968253968f, 0.4126984126984127f, 0.4285714285714285f, 0.4444444444444444f, 0.4603174603174603f, 0.4761904761904762f, 0.492063492063492f, 0.5079365079365079f, 0.5238095238095238f, 0.5396825396825397f, 0.5555555555555556f, 0.5714285714285714f, 0.5873015873015873f, 0.6031746031746031f, 0.6190476190476191f, 0.6349206349206349f, 0.6507936507936508f, 0.6666666666666666f, 0.6825396825396826f, 0.6984126984126984f, 0.7142857142857143f, 0.7301587301587301f, 0.746031746031746f, 0.7619047619047619f, 0.7777777777777778f, 0.7936507936507936f, 0.8095238095238095f, 0.8253968253968254f, 0.8412698412698413f, 0.8571428571428571f, 0.873015873015873f, 0.8888888888888888f, 0.9047619047619048f, 0.9206349206349206f, 0.9365079365079365f, 0.9523809523809523f, 0.9682539682539683f, 0.9841269841269841f, 1}; + float g[] = { 0.5f, 0.5079365079365079f, 0.5158730158730158f, 0.5238095238095238f, 0.5317460317460317f, 0.5396825396825397f, 0.5476190476190477f, 0.5555555555555556f, 0.5634920634920635f, 0.5714285714285714f, 0.5793650793650793f, 0.5873015873015873f, 0.5952380952380952f, 0.6031746031746031f, 0.6111111111111112f, 0.6190476190476191f, 0.626984126984127f, 0.6349206349206349f, 0.6428571428571428f, 0.6507936507936508f, 0.6587301587301587f, 0.6666666666666666f, 0.6746031746031746f, 0.6825396825396826f, 0.6904761904761905f, 0.6984126984126984f, 0.7063492063492063f, 0.7142857142857143f, 0.7222222222222222f, 0.7301587301587301f, 0.7380952380952381f, 0.746031746031746f, 0.753968253968254f, 0.7619047619047619f, 0.7698412698412698f, 0.7777777777777778f, 0.7857142857142857f, 0.7936507936507937f, 0.8015873015873016f, 0.8095238095238095f, 0.8174603174603174f, 0.8253968253968254f, 0.8333333333333333f, 0.8412698412698413f, 0.8492063492063492f, 0.8571428571428572f, 0.8650793650793651f, 0.873015873015873f, 0.8809523809523809f, 0.8888888888888888f, 0.8968253968253967f, 0.9047619047619048f, 0.9126984126984127f, 0.9206349206349207f, 0.9285714285714286f, 0.9365079365079365f, 0.9444444444444444f, 0.9523809523809523f, 0.9603174603174602f, 0.9682539682539683f, 0.9761904761904762f, 0.9841269841269842f, 0.9920634920634921f, 1}; + float b[] = { 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -362,8 +362,8 @@ namespace colormap void init(int n) { float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - float g[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; - float b[] = { 1, 0.9841269841269842, 0.9682539682539683, 0.9523809523809523, 0.9365079365079365, 0.9206349206349207, 0.9047619047619048, 0.8888888888888888, 0.873015873015873, 0.8571428571428572, 0.8412698412698413, 0.8253968253968254, 0.8095238095238095, 0.7936507936507937, 0.7777777777777778, 0.7619047619047619, 0.746031746031746, 0.7301587301587302, 0.7142857142857143, 0.6984126984126984, 0.6825396825396826, 0.6666666666666667, 0.6507936507936508, 0.6349206349206349, 0.6190476190476191, 0.6031746031746033, 0.5873015873015873, 0.5714285714285714, 0.5555555555555556, 0.5396825396825398, 0.5238095238095238, 0.5079365079365079, 0.4920634920634921, 0.4761904761904762, 0.4603174603174603, 0.4444444444444444, 0.4285714285714286, 0.4126984126984127, 0.3968253968253969, 0.3809523809523809, 0.3650793650793651, 0.3492063492063492, 0.3333333333333334, 0.3174603174603174, 0.3015873015873016, 0.2857142857142857, 0.2698412698412699, 0.253968253968254, 0.2380952380952381, 0.2222222222222222, 0.2063492063492064, 0.1904761904761905, 0.1746031746031746, 0.1587301587301587, 0.1428571428571429, 0.126984126984127, 0.1111111111111112, 0.09523809523809523, 0.07936507936507942, 0.06349206349206349, 0.04761904761904767, 0.03174603174603174, 0.01587301587301593, 0}; + float g[] = { 0, 0.01587301587301587f, 0.03174603174603174f, 0.04761904761904762f, 0.06349206349206349f, 0.07936507936507936f, 0.09523809523809523f, 0.1111111111111111f, 0.126984126984127f, 0.1428571428571428f, 0.1587301587301587f, 0.1746031746031746f, 0.1904761904761905f, 0.2063492063492063f, 0.2222222222222222f, 0.2380952380952381f, 0.253968253968254f, 0.2698412698412698f, 0.2857142857142857f, 0.3015873015873016f, 0.3174603174603174f, 0.3333333333333333f, 0.3492063492063492f, 0.3650793650793651f, 0.3809523809523809f, 0.3968253968253968f, 0.4126984126984127f, 0.4285714285714285f, 0.4444444444444444f, 0.4603174603174603f, 0.4761904761904762f, 0.492063492063492f, 0.5079365079365079f, 0.5238095238095238f, 0.5396825396825397f, 0.5555555555555556f, 0.5714285714285714f, 0.5873015873015873f, 0.6031746031746031f, 0.6190476190476191f, 0.6349206349206349f, 0.6507936507936508f, 0.6666666666666666f, 0.6825396825396826f, 0.6984126984126984f, 0.7142857142857143f, 0.7301587301587301f, 0.746031746031746f, 0.7619047619047619f, 0.7777777777777778f, 0.7936507936507936f, 0.8095238095238095f, 0.8253968253968254f, 0.8412698412698413f, 0.8571428571428571f, 0.873015873015873f, 0.8888888888888888f, 0.9047619047619048f, 0.9206349206349206f, 0.9365079365079365f, 0.9523809523809523f, 0.9682539682539683f, 0.9841269841269841f, 1}; + float b[] = { 1, 0.9841269841269842f, 0.9682539682539683f, 0.9523809523809523f, 0.9365079365079365f, 0.9206349206349207f, 0.9047619047619048f, 0.8888888888888888f, 0.873015873015873f, 0.8571428571428572f, 0.8412698412698413f, 0.8253968253968254f, 0.8095238095238095f, 0.7936507936507937f, 0.7777777777777778f, 0.7619047619047619f, 0.746031746031746f, 0.7301587301587302f, 0.7142857142857143f, 0.6984126984126984f, 0.6825396825396826f, 0.6666666666666667f, 0.6507936507936508f, 0.6349206349206349f, 0.6190476190476191f, 0.6031746031746033f, 0.5873015873015873f, 0.5714285714285714f, 0.5555555555555556f, 0.5396825396825398f, 0.5238095238095238f, 0.5079365079365079f, 0.4920634920634921f, 0.4761904761904762f, 0.4603174603174603f, 0.4444444444444444f, 0.4285714285714286f, 0.4126984126984127f, 0.3968253968253969f, 0.3809523809523809f, 0.3650793650793651f, 0.3492063492063492f, 0.3333333333333334f, 0.3174603174603174f, 0.3015873015873016f, 0.2857142857142857f, 0.2698412698412699f, 0.253968253968254f, 0.2380952380952381f, 0.2222222222222222f, 0.2063492063492064f, 0.1904761904761905f, 0.1746031746031746f, 0.1587301587301587f, 0.1428571428571429f, 0.126984126984127f, 0.1111111111111112f, 0.09523809523809523f, 0.07936507936507942f, 0.06349206349206349f, 0.04761904761904767f, 0.03174603174603174f, 0.01587301587301593f, 0}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -385,8 +385,8 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0.01587301587301587, 0.03174603174603174, 0.04761904761904762, 0.06349206349206349, 0.07936507936507936, 0.09523809523809523, 0.1111111111111111, 0.126984126984127, 0.1428571428571428, 0.1587301587301587, 0.1746031746031746, 0.1904761904761905, 0.2063492063492063, 0.2222222222222222, 0.2380952380952381, 0.253968253968254, 0.2698412698412698, 0.2857142857142857, 0.3015873015873016, 0.3174603174603174, 0.3333333333333333, 0.3492063492063492, 0.3650793650793651, 0.3809523809523809, 0.3968253968253968, 0.4126984126984127, 0.4285714285714285, 0.4444444444444444, 0.4603174603174603, 0.4761904761904762, 0.492063492063492, 0.5079365079365079, 0.5238095238095238, 0.5396825396825397, 0.5555555555555556, 0.5714285714285714, 0.5873015873015873, 0.6031746031746031, 0.6190476190476191, 0.6349206349206349, 0.6507936507936508, 0.6666666666666666, 0.6825396825396826, 0.6984126984126984, 0.7142857142857143, 0.7301587301587301, 0.746031746031746, 0.7619047619047619, 0.7777777777777778, 0.7936507936507936, 0.8095238095238095, 0.8253968253968254, 0.8412698412698413, 0.8571428571428571, 0.873015873015873, 0.8888888888888888, 0.9047619047619048, 0.9206349206349206, 0.9365079365079365, 0.9523809523809523, 0.9682539682539683, 0.9841269841269841, 1}; - float g[] = { 1, 0.9841269841269842, 0.9682539682539683, 0.9523809523809523, 0.9365079365079365, 0.9206349206349207, 0.9047619047619048, 0.8888888888888888, 0.873015873015873, 0.8571428571428572, 0.8412698412698413, 0.8253968253968254, 0.8095238095238095, 0.7936507936507937, 0.7777777777777778, 0.7619047619047619, 0.746031746031746, 0.7301587301587302, 0.7142857142857143, 0.6984126984126984, 0.6825396825396826, 0.6666666666666667, 0.6507936507936508, 0.6349206349206349, 0.6190476190476191, 0.6031746031746033, 0.5873015873015873, 0.5714285714285714, 0.5555555555555556, 0.5396825396825398, 0.5238095238095238, 0.5079365079365079, 0.4920634920634921, 0.4761904761904762, 0.4603174603174603, 0.4444444444444444, 0.4285714285714286, 0.4126984126984127, 0.3968253968253969, 0.3809523809523809, 0.3650793650793651, 0.3492063492063492, 0.3333333333333334, 0.3174603174603174, 0.3015873015873016, 0.2857142857142857, 0.2698412698412699, 0.253968253968254, 0.2380952380952381, 0.2222222222222222, 0.2063492063492064, 0.1904761904761905, 0.1746031746031746, 0.1587301587301587, 0.1428571428571429, 0.126984126984127, 0.1111111111111112, 0.09523809523809523, 0.07936507936507942, 0.06349206349206349, 0.04761904761904767, 0.03174603174603174, 0.01587301587301593, 0}; + float r[] = { 0, 0.01587301587301587f, 0.03174603174603174f, 0.04761904761904762f, 0.06349206349206349f, 0.07936507936507936f, 0.09523809523809523f, 0.1111111111111111f, 0.126984126984127f, 0.1428571428571428f, 0.1587301587301587f, 0.1746031746031746f, 0.1904761904761905f, 0.2063492063492063f, 0.2222222222222222f, 0.2380952380952381f, 0.253968253968254f, 0.2698412698412698f, 0.2857142857142857f, 0.3015873015873016f, 0.3174603174603174f, 0.3333333333333333f, 0.3492063492063492f, 0.3650793650793651f, 0.3809523809523809f, 0.3968253968253968f, 0.4126984126984127f, 0.4285714285714285f, 0.4444444444444444f, 0.4603174603174603f, 0.4761904761904762f, 0.492063492063492f, 0.5079365079365079f, 0.5238095238095238f, 0.5396825396825397f, 0.5555555555555556f, 0.5714285714285714f, 0.5873015873015873f, 0.6031746031746031f, 0.6190476190476191f, 0.6349206349206349f, 0.6507936507936508f, 0.6666666666666666f, 0.6825396825396826f, 0.6984126984126984f, 0.7142857142857143f, 0.7301587301587301f, 0.746031746031746f, 0.7619047619047619f, 0.7777777777777778f, 0.7936507936507936f, 0.8095238095238095f, 0.8253968253968254f, 0.8412698412698413f, 0.8571428571428571f, 0.873015873015873f, 0.8888888888888888f, 0.9047619047619048f, 0.9206349206349206f, 0.9365079365079365f, 0.9523809523809523f, 0.9682539682539683f, 0.9841269841269841f, 1}; + float g[] = { 1, 0.9841269841269842f, 0.9682539682539683f, 0.9523809523809523f, 0.9365079365079365f, 0.9206349206349207f, 0.9047619047619048f, 0.8888888888888888f, 0.873015873015873f, 0.8571428571428572f, 0.8412698412698413f, 0.8253968253968254f, 0.8095238095238095f, 0.7936507936507937f, 0.7777777777777778f, 0.7619047619047619f, 0.746031746031746f, 0.7301587301587302f, 0.7142857142857143f, 0.6984126984126984f, 0.6825396825396826f, 0.6666666666666667f, 0.6507936507936508f, 0.6349206349206349f, 0.6190476190476191f, 0.6031746031746033f, 0.5873015873015873f, 0.5714285714285714f, 0.5555555555555556f, 0.5396825396825398f, 0.5238095238095238f, 0.5079365079365079f, 0.4920634920634921f, 0.4761904761904762f, 0.4603174603174603f, 0.4444444444444444f, 0.4285714285714286f, 0.4126984126984127f, 0.3968253968253969f, 0.3809523809523809f, 0.3650793650793651f, 0.3492063492063492f, 0.3333333333333334f, 0.3174603174603174f, 0.3015873015873016f, 0.2857142857142857f, 0.2698412698412699f, 0.253968253968254f, 0.2380952380952381f, 0.2222222222222222f, 0.2063492063492064f, 0.1904761904761905f, 0.1746031746031746f, 0.1587301587301587f, 0.1428571428571429f, 0.126984126984127f, 0.1111111111111112f, 0.09523809523809523f, 0.07936507936507942f, 0.06349206349206349f, 0.04761904761904767f, 0.03174603174603174f, 0.01587301587301593f, 0}; float b[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, @@ -409,9 +409,9 @@ namespace colormap } void init(int n) { - float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526, 0.8571428571428568, 0.7619047619047614, 0.6666666666666665, 0.5714285714285716, 0.4761904761904763, 0.3809523809523805, 0.2857142857142856, 0.1904761904761907, 0.0952380952380949, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.09523809523809557, 0.1904761904761905, 0.2857142857142854, 0.3809523809523809, 0.4761904761904765, 0.5714285714285714, 0.6666666666666663, 0.7619047619047619, 0.8571428571428574, 0.9523809523809523, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - float g[] = { 0, 0.09523809523809523, 0.1904761904761905, 0.2857142857142857, 0.3809523809523809, 0.4761904761904762, 0.5714285714285714, 0.6666666666666666, 0.7619047619047619, 0.8571428571428571, 0.9523809523809523, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526, 0.8571428571428577, 0.7619047619047619, 0.6666666666666665, 0.5714285714285716, 0.4761904761904767, 0.3809523809523814, 0.2857142857142856, 0.1904761904761907, 0.09523809523809579, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.09523809523809523, 0.1904761904761905, 0.2857142857142857, 0.3809523809523809, 0.4761904761904762, 0.5714285714285714, 0.6666666666666666, 0.7619047619047619, 0.8571428571428571, 0.9523809523809523, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526, 0.8571428571428577, 0.7619047619047614, 0.6666666666666665, 0.5714285714285716, 0.4761904761904767, 0.3809523809523805, 0.2857142857142856, 0.1904761904761907, 0.09523809523809579, 0}; + float r[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526f, 0.8571428571428568f, 0.7619047619047614f, 0.6666666666666665f, 0.5714285714285716f, 0.4761904761904763f, 0.3809523809523805f, 0.2857142857142856f, 0.1904761904761907f, 0.0952380952380949f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.09523809523809557f, 0.1904761904761905f, 0.2857142857142854f, 0.3809523809523809f, 0.4761904761904765f, 0.5714285714285714f, 0.6666666666666663f, 0.7619047619047619f, 0.8571428571428574f, 0.9523809523809523f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float g[] = { 0, 0.09523809523809523f, 0.1904761904761905f, 0.2857142857142857f, 0.3809523809523809f, 0.4761904761904762f, 0.5714285714285714f, 0.6666666666666666f, 0.7619047619047619f, 0.8571428571428571f, 0.9523809523809523f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526f, 0.8571428571428577f, 0.7619047619047619f, 0.6666666666666665f, 0.5714285714285716f, 0.4761904761904767f, 0.3809523809523814f, 0.2857142857142856f, 0.1904761904761907f, 0.09523809523809579f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.09523809523809523f, 0.1904761904761905f, 0.2857142857142857f, 0.3809523809523809f, 0.4761904761904762f, 0.5714285714285714f, 0.6666666666666666f, 0.7619047619047619f, 0.8571428571428571f, 0.9523809523809523f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9523809523809526f, 0.8571428571428577f, 0.7619047619047614f, 0.6666666666666665f, 0.5714285714285716f, 0.4761904761904767f, 0.3809523809523805f, 0.2857142857142856f, 0.1904761904761907f, 0.09523809523809579f, 0}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -433,9 +433,9 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0.1571348402636772, 0.2222222222222222, 0.2721655269759087, 0.3142696805273544, 0.3513641844631533, 0.3849001794597505, 0.415739709641549, 0.4444444444444444, 0.4714045207910317, 0.4969039949999532, 0.5211573066470477, 0.5443310539518174, 0.5665577237325317, 0.5879447357921312, 0.6085806194501846, 0.6285393610547089, 0.6478835438717, 0.6666666666666666, 0.6849348892187751, 0.7027283689263065, 0.7200822998230956, 0.7370277311900888, 0.753592220347252, 0.7663560447348133, 0.7732293307186413, 0.7800420555749596, 0.7867957924694432, 0.7934920476158722, 0.8001322641986387, 0.8067178260046388, 0.8132500607904444, 0.8197302434079591, 0.8261595987094034, 0.8325393042503717, 0.8388704928078611, 0.8451542547285166, 0.8513916401208816, 0.8575836609041332, 0.8637312927246217, 0.8698354767504924, 0.8758971213537393, 0.8819171036881968, 0.8878962711712378, 0.8938354428762595, 0.8997354108424372, 0.9055969413076769, 0.9114207758701963, 0.9172076325837248, 0.9229582069908971, 0.9286731730990523, 0.9343531843023135, 0.9399988742535192, 0.9456108576893002, 0.9511897312113418, 0.9567360740266436, 0.9622504486493763, 0.9677334015667416, 0.9731854638710686, 0.9786071518602129, 0.9839989676081821, 0.9893613995077727, 0.9946949227868761, 1}; - float g[] = { 0, 0.1028688999747279, 0.1454785934906616, 0.1781741612749496, 0.2057377999494559, 0.2300218531141181, 0.2519763153394848, 0.2721655269759087, 0.2909571869813232, 0.3086066999241838, 0.3253000243161777, 0.3411775438127727, 0.3563483225498992, 0.3708990935094579, 0.3849001794597505, 0.3984095364447979, 0.4114755998989117, 0.4241393401869012, 0.4364357804719847, 0.4483951394230328, 0.4600437062282361, 0.4714045207910317, 0.4824979096371639, 0.4933419132673033, 0.5091750772173156, 0.5328701692569688, 0.5555555555555556, 0.5773502691896257, 0.5983516452371671, 0.6186404847588913, 0.6382847385042254, 0.6573421981221795, 0.6758625033664688, 0.6938886664887108, 0.7114582486036499, 0.7286042804780002, 0.7453559924999299, 0.7617394000445604, 0.7777777777777778, 0.7934920476158723, 0.8089010988089465, 0.8240220541217402, 0.8388704928078611, 0.8534606386520677, 0.8678055195451838, 0.8819171036881968, 0.8958064164776166, 0.9094836413191612, 0.9172076325837248, 0.9229582069908971, 0.9286731730990523, 0.9343531843023135, 0.9399988742535192, 0.9456108576893002, 0.9511897312113418, 0.9567360740266436, 0.9622504486493763, 0.9677334015667416, 0.9731854638710686, 0.9786071518602129, 0.9839989676081821, 0.9893613995077727, 0.9946949227868761, 1}; - float b[] = { 0, 0.1028688999747279, 0.1454785934906616, 0.1781741612749496, 0.2057377999494559, 0.2300218531141181, 0.2519763153394848, 0.2721655269759087, 0.2909571869813232, 0.3086066999241838, 0.3253000243161777, 0.3411775438127727, 0.3563483225498992, 0.3708990935094579, 0.3849001794597505, 0.3984095364447979, 0.4114755998989117, 0.4241393401869012, 0.4364357804719847, 0.4483951394230328, 0.4600437062282361, 0.4714045207910317, 0.4824979096371639, 0.4933419132673033, 0.5039526306789697, 0.5143444998736397, 0.5245305283129621, 0.5345224838248488, 0.5443310539518174, 0.5539659798925444, 0.563436169819011, 0.5727497953228163, 0.5819143739626463, 0.5909368402852788, 0.5998236072282915, 0.6085806194501846, 0.6172133998483676, 0.6257270902992705, 0.6341264874742278, 0.642416074439621, 0.6506000486323554, 0.6586823467062358, 0.6666666666666666, 0.6745564876468501, 0.6823550876255453, 0.6900655593423541, 0.6976908246297114, 0.7052336473499384, 0.7237468644557459, 0.7453559924999298, 0.7663560447348133, 0.7867957924694432, 0.8067178260046388, 0.8261595987094034, 0.8451542547285166, 0.8637312927246217, 0.8819171036881968, 0.8997354108424372, 0.9172076325837248, 0.9343531843023135, 0.9511897312113418, 0.9677334015667416, 0.9839989676081821, 1}; + float r[] = { 0, 0.1571348402636772f, 0.2222222222222222f, 0.2721655269759087f, 0.3142696805273544f, 0.3513641844631533f, 0.3849001794597505f, 0.415739709641549f, 0.4444444444444444f, 0.4714045207910317f, 0.4969039949999532f, 0.5211573066470477f, 0.5443310539518174f, 0.5665577237325317f, 0.5879447357921312f, 0.6085806194501846f, 0.6285393610547089f, 0.6478835438717f, 0.6666666666666666f, 0.6849348892187751f, 0.7027283689263065f, 0.7200822998230956f, 0.7370277311900888f, 0.753592220347252f, 0.7663560447348133f, 0.7732293307186413f, 0.7800420555749596f, 0.7867957924694432f, 0.7934920476158722f, 0.8001322641986387f, 0.8067178260046388f, 0.8132500607904444f, 0.8197302434079591f, 0.8261595987094034f, 0.8325393042503717f, 0.8388704928078611f, 0.8451542547285166f, 0.8513916401208816f, 0.8575836609041332f, 0.8637312927246217f, 0.8698354767504924f, 0.8758971213537393f, 0.8819171036881968f, 0.8878962711712378f, 0.8938354428762595f, 0.8997354108424372f, 0.9055969413076769f, 0.9114207758701963f, 0.9172076325837248f, 0.9229582069908971f, 0.9286731730990523f, 0.9343531843023135f, 0.9399988742535192f, 0.9456108576893002f, 0.9511897312113418f, 0.9567360740266436f, 0.9622504486493763f, 0.9677334015667416f, 0.9731854638710686f, 0.9786071518602129f, 0.9839989676081821f, 0.9893613995077727f, 0.9946949227868761f, 1}; + float g[] = { 0, 0.1028688999747279f, 0.1454785934906616f, 0.1781741612749496f, 0.2057377999494559f, 0.2300218531141181f, 0.2519763153394848f, 0.2721655269759087f, 0.2909571869813232f, 0.3086066999241838f, 0.3253000243161777f, 0.3411775438127727f, 0.3563483225498992f, 0.3708990935094579f, 0.3849001794597505f, 0.3984095364447979f, 0.4114755998989117f, 0.4241393401869012f, 0.4364357804719847f, 0.4483951394230328f, 0.4600437062282361f, 0.4714045207910317f, 0.4824979096371639f, 0.4933419132673033f, 0.5091750772173156f, 0.5328701692569688f, 0.5555555555555556f, 0.5773502691896257f, 0.5983516452371671f, 0.6186404847588913f, 0.6382847385042254f, 0.6573421981221795f, 0.6758625033664688f, 0.6938886664887108f, 0.7114582486036499f, 0.7286042804780002f, 0.7453559924999299f, 0.7617394000445604f, 0.7777777777777778f, 0.7934920476158723f, 0.8089010988089465f, 0.8240220541217402f, 0.8388704928078611f, 0.8534606386520677f, 0.8678055195451838f, 0.8819171036881968f, 0.8958064164776166f, 0.9094836413191612f, 0.9172076325837248f, 0.9229582069908971f, 0.9286731730990523f, 0.9343531843023135f, 0.9399988742535192f, 0.9456108576893002f, 0.9511897312113418f, 0.9567360740266436f, 0.9622504486493763f, 0.9677334015667416f, 0.9731854638710686f, 0.9786071518602129f, 0.9839989676081821f, 0.9893613995077727f, 0.9946949227868761f, 1}; + float b[] = { 0, 0.1028688999747279f, 0.1454785934906616f, 0.1781741612749496f, 0.2057377999494559f, 0.2300218531141181f, 0.2519763153394848f, 0.2721655269759087f, 0.2909571869813232f, 0.3086066999241838f, 0.3253000243161777f, 0.3411775438127727f, 0.3563483225498992f, 0.3708990935094579f, 0.3849001794597505f, 0.3984095364447979f, 0.4114755998989117f, 0.4241393401869012f, 0.4364357804719847f, 0.4483951394230328f, 0.4600437062282361f, 0.4714045207910317f, 0.4824979096371639f, 0.4933419132673033f, 0.5039526306789697f, 0.5143444998736397f, 0.5245305283129621f, 0.5345224838248488f, 0.5443310539518174f, 0.5539659798925444f, 0.563436169819011f, 0.5727497953228163f, 0.5819143739626463f, 0.5909368402852788f, 0.5998236072282915f, 0.6085806194501846f, 0.6172133998483676f, 0.6257270902992705f, 0.6341264874742278f, 0.642416074439621f, 0.6506000486323554f, 0.6586823467062358f, 0.6666666666666666f, 0.6745564876468501f, 0.6823550876255453f, 0.6900655593423541f, 0.6976908246297114f, 0.7052336473499384f, 0.7237468644557459f, 0.7453559924999298f, 0.7663560447348133f, 0.7867957924694432f, 0.8067178260046388f, 0.8261595987094034f, 0.8451542547285166f, 0.8637312927246217f, 0.8819171036881968f, 0.8997354108424372f, 0.9172076325837248f, 0.9343531843023135f, 0.9511897312113418f, 0.9677334015667416f, 0.9839989676081821f, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -457,9 +457,9 @@ namespace colormap } void init(int n) { - float r[] = { 0, 0.03968253968253968, 0.07936507936507936, 0.119047619047619, 0.1587301587301587, 0.1984126984126984, 0.2380952380952381, 0.2777777777777778, 0.3174603174603174, 0.3571428571428571, 0.3968253968253968, 0.4365079365079365, 0.4761904761904762, 0.5158730158730158, 0.5555555555555556, 0.5952380952380952, 0.6349206349206349, 0.6746031746031745, 0.7142857142857142, 0.753968253968254, 0.7936507936507936, 0.8333333333333333, 0.873015873015873, 0.9126984126984127, 0.9523809523809523, 0.992063492063492, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - float g[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03174603174603163, 0.0714285714285714, 0.1111111111111112, 0.1507936507936507, 0.1904761904761905, 0.23015873015873, 0.2698412698412698, 0.3095238095238093, 0.3492063492063491, 0.3888888888888888, 0.4285714285714284, 0.4682539682539679, 0.5079365079365079, 0.5476190476190477, 0.5873015873015872, 0.6269841269841268, 0.6666666666666665, 0.7063492063492065, 0.746031746031746, 0.7857142857142856, 0.8253968253968254, 0.8650793650793651, 0.9047619047619047, 0.9444444444444442, 0.984126984126984, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.04761904761904745, 0.1269841269841265, 0.2063492063492056, 0.2857142857142856, 0.3650793650793656, 0.4444444444444446, 0.5238095238095237, 0.6031746031746028, 0.6825396825396828, 0.7619047619047619, 0.8412698412698409, 0.92063492063492, 1}; + float r[] = { 0, 0.03968253968253968f, 0.07936507936507936f, 0.119047619047619f, 0.1587301587301587f, 0.1984126984126984f, 0.2380952380952381f, 0.2777777777777778f, 0.3174603174603174f, 0.3571428571428571f, 0.3968253968253968f, 0.4365079365079365f, 0.4761904761904762f, 0.5158730158730158f, 0.5555555555555556f, 0.5952380952380952f, 0.6349206349206349f, 0.6746031746031745f, 0.7142857142857142f, 0.753968253968254f, 0.7936507936507936f, 0.8333333333333333f, 0.873015873015873f, 0.9126984126984127f, 0.9523809523809523f, 0.992063492063492f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float g[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.03174603174603163f, 0.0714285714285714f, 0.1111111111111112f, 0.1507936507936507f, 0.1904761904761905f, 0.23015873015873f, 0.2698412698412698f, 0.3095238095238093f, 0.3492063492063491f, 0.3888888888888888f, 0.4285714285714284f, 0.4682539682539679f, 0.5079365079365079f, 0.5476190476190477f, 0.5873015873015872f, 0.6269841269841268f, 0.6666666666666665f, 0.7063492063492065f, 0.746031746031746f, 0.7857142857142856f, 0.8253968253968254f, 0.8650793650793651f, 0.9047619047619047f, 0.9444444444444442f, 0.984126984126984f, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + float b[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.04761904761904745f, 0.1269841269841265f, 0.2063492063492056f, 0.2857142857142856f, 0.3650793650793656f, 0.4444444444444446f, 0.5238095238095237f, 0.6031746031746028f, 0.6825396825396828f, 0.7619047619047619f, 0.8412698412698409f, 0.92063492063492f, 1}; Mat X = linspace(0,1,64); this->_lut = ColorMap::linear_colormap(X, Mat(64,1, CV_32FC1, r).clone(), // red @@ -481,9 +481,9 @@ namespace colormap } void init(int n) { - float r[] = { 0.2078, 0.0118, 0.0784, 0.0235, 0.2196, 0.5725, 0.8510, 0.9882, 0.9765 }; - float g[] = { 0.1647, 0.3882, 0.5216, 0.6549, 0.7255, 0.7490, 0.7294, 0.8078, 0.9843 }; - float b[] = { 0.5294, 0.8824, 0.8314, 0.7765, 0.6196, 0.4510, 0.3373, 0.1804, 0.0549 }; + float r[] = { 0.2078f, 0.0118f, 0.0784f, 0.0235f, 0.2196f, 0.5725f, 0.8510f, 0.9882f, 0.9765f }; + float g[] = { 0.1647f, 0.3882f, 0.5216f, 0.6549f, 0.7255f, 0.7490f, 0.7294f, 0.8078f, 0.9843f }; + float b[] = { 0.5294f, 0.8824f, 0.8314f, 0.7765f, 0.6196f, 0.4510f, 0.3373f, 0.1804f, 0.0549f }; Mat X = linspace(0, 1, 9); this->_lut = ColorMap::linear_colormap(X, Mat(9, 1, CV_32FC1, r).clone(), // red diff --git a/modules/imgproc/src/contours.cpp b/modules/imgproc/src/contours.cpp index bb21e4106..4cb3f55c4 100644 --- a/modules/imgproc/src/contours.cpp +++ b/modules/imgproc/src/contours.cpp @@ -222,7 +222,6 @@ cvStartFindContours( void* _img, CvMemStorage* storage, scanner->lnbd.x = 0; scanner->lnbd.y = 1; scanner->nbd = 2; - scanner->mode = (int) mode; scanner->frame_info.contour = &(scanner->frame); scanner->frame_info.is_hole = 1; scanner->frame_info.next = 0; diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index d9b3d943e..946625eb0 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -394,7 +394,7 @@ static bool extractCovData(InputArray _src, UMat & Dx, UMat & Dy, int depth, Dx.create(src.size(), CV_32FC1); Dy.create(src.size(), CV_32FC1); - size_t localsize[2] = { sobel_lsz, sobel_lsz }; + size_t localsize[2] = { (size_t)sobel_lsz, (size_t)sobel_lsz }; size_t globalsize[2] = { localsize[0] * (1 + (src.cols - 1) / localsize[0]), localsize[1] * (1 + (src.rows - 1) / localsize[1]) }; @@ -515,7 +515,7 @@ static bool ocl_preCornerDetect( InputArray _src, OutputArray _dst, int ksize, i ocl::KernelArg::ReadOnlyNoSize(D2x), ocl::KernelArg::ReadOnlyNoSize(D2y), ocl::KernelArg::ReadOnlyNoSize(Dxy), ocl::KernelArg::WriteOnly(dst), (float)factor); - size_t globalsize[2] = { dst.cols, dst.rows }; + size_t globalsize[2] = { (size_t)dst.cols, (size_t)dst.rows }; return k.run(2, globalsize, NULL, false); } @@ -528,7 +528,7 @@ namespace cv { static bool ipp_cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, int ksize, int borderType ) { -#if IPP_VERSION_MAJOR >= 8 +#if IPP_VERSION_X100 >= 800 Mat src = _src.getMat(); _dst.create( src.size(), CV_32FC1 ); Mat dst = _dst.getMat(); @@ -603,16 +603,12 @@ void cv::cornerMinEigenVal( InputArray _src, OutputArray _dst, int blockSize, in ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, 0.0, borderType, MINEIGENVAL)) #ifdef HAVE_IPP - int kerSize = ksize; - if (ksize < 0) - { - kerSize = 3; - } + int kerSize = (ksize < 0)?3:ksize; bool isolated = (borderType & BORDER_ISOLATED) != 0; int borderTypeNI = borderType & ~BORDER_ISOLATED; #endif CV_IPP_RUN(((borderTypeNI == BORDER_REPLICATE && (!_src.isSubmatrix() || isolated)) && - (kerSize == 3 || kerSize == 5) && (blockSize == 3 || blockSize == 5)) && IPP_VERSION_MAJOR >= 8, + (kerSize == 3 || kerSize == 5) && (blockSize == 3 || blockSize == 5)) && IPP_VERSION_X100 >= 800, ipp_cornerMinEigenVal( _src, _dst, blockSize, ksize, borderType )); @@ -629,7 +625,7 @@ namespace cv { static bool ipp_cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType ) { -#if IPP_VERSION_X100 >= 801 && 0 +#if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Mat src = _src.getMat(); _dst.create( src.size(), CV_32FC1 ); Mat dst = _dst.getMat(); @@ -696,7 +692,7 @@ void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksi #endif CV_IPP_RUN(((ksize == 3 || ksize == 5) && (_src.type() == CV_8UC1 || _src.type() == CV_32FC1) && (borderTypeNI == BORDER_CONSTANT || borderTypeNI == BORDER_REPLICATE) && CV_MAT_CN(_src.type()) == 1 && - (!_src.isSubmatrix() || isolated)) && IPP_VERSION_X100 >= 801 && 0, ipp_cornerHarris( _src, _dst, blockSize, ksize, k, borderType )); + (!_src.isSubmatrix() || isolated)) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK, ipp_cornerHarris( _src, _dst, blockSize, ksize, k, borderType )); Mat src = _src.getMat(); diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index 482f4d365..d41b8ae53 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -43,10 +43,6 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) -static IppStatus sts = ippInit(); -#endif - /****************************************************************************************\ Sobel & Scharr Derivative Filters \****************************************************************************************/ @@ -183,15 +179,12 @@ cv::Ptr cv::createDerivFilter(int srcType, int dstType, kx, ky, Point(-1,-1), 0, borderType ); } -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - -#define IPP_RETURN_ERROR {setIppErrorStatus(); return false;} - +#ifdef HAVE_IPP namespace cv { -#if IPP_VERSION_X100 >= 801 static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) { +#if IPP_VERSION_X100 >= 810 if ((0 > dx) || (0 > dy) || (1 != dx + dy)) return false; if (fabs(delta) > FLT_EPSILON) @@ -233,19 +226,19 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx if (horz) { if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp8u, ipp16s, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrHorizMaskBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } else { if (0 > ippiFilterScharrVertMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp8u, ipp16s, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrVertMaskBorder_8u16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } ippsFree(pBuffer); @@ -256,19 +249,19 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx if (horz) { if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp16s, ipp16s, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrHorizMaskBorder_16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } else { if (0 > ippiFilterScharrVertMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp16s, ipp16s, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrVertMaskBorder_16s_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } ippsFree(pBuffer); @@ -279,134 +272,34 @@ static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx if (horz) { if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp32f, ipp32f, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrHorizMaskBorder_32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } else { if (0 > ippiFilterScharrVertMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp32f, ipp32f, 1, &bufferSize)) - IPP_RETURN_ERROR + return false; pBuffer = ippsMalloc_8u(bufferSize); if (NULL == pBuffer) - IPP_RETURN_ERROR + return false; sts = ippiFilterScharrVertMaskBorder_32f_C1R(src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); } ippsFree(pBuffer); if (sts < 0) - IPP_RETURN_ERROR; + return false;; if (FLT_EPSILON < fabs(scale - 1.0)) sts = ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, roiSize); } return (0 <= sts); -} -#elif IPP_VERSION_X100 >= 700 -static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) -{ - if (BORDER_REPLICATE != borderType) - return false; - if ((0 > dx) || (0 > dy) || (1 != dx + dy)) - return false; - if (fabs(delta) > FLT_EPSILON) - return false; - - Mat src = _src.getMat(), dst = _dst.getMat(); - - int bufSize = 0; - cv::AutoBuffer buffer; - IppiSize roi = ippiSize(src.cols, src.rows); - - if( ddepth < 0 ) - ddepth = src.depth(); - - dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); - - switch(src.type()) - { - case CV_8UC1: - { - if(scale != 1) - return false; - - switch(dst.type()) - { - case CV_16S: - { - if ((dx == 1) && (dy == 0)) - { - if (0 > ippiFilterScharrVertGetBufferSize_8u16s_C1R(roi,&bufSize)) - return false; - buffer.allocate(bufSize); - return (0 <= ippiFilterScharrVertBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, roi, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)); - } - if ((dx == 0) && (dy == 1)) - { - if (0 > ippiFilterScharrHorizGetBufferSize_8u16s_C1R(roi,&bufSize)) - return false; - buffer.allocate(bufSize); - return (0 <= ippiFilterScharrHorizBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, roi, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)); - } - return false; - } - default: - return false; - } - } - case CV_32FC1: - { - switch(dst.type()) - { - case CV_32FC1: - { - if ((dx == 1) && (dy == 0)) - { - if (0 > ippiFilterScharrVertGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows),&bufSize)) - return false; - buffer.allocate(bufSize); - - if (0 > ippiFilterScharrVertBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), - ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - { - return false; - } - - if (scale != 1) - /* IPP is fast, so MulC produce very little perf degradation.*/ - //ippiMulC_32f_C1IR((Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); - ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); - return true; - } - if ((dx == 0) && (dy == 1)) - { - if (0 > ippiFilterScharrHorizGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows),&bufSize)) - return false; - buffer.allocate(bufSize); - - if (0 > ippiFilterScharrHorizBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), - ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - return false; - - if (scale != 1) - ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); - return true; - } - } - default: - return false; - } - } - default: - return false; - } -} +#else + CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ddepth); CV_UNUSED(dx); CV_UNUSED(dy); CV_UNUSED(scale); CV_UNUSED(delta); CV_UNUSED(borderType); + return false; #endif +} static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) { @@ -423,58 +316,75 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if ( ddepth < 0 ) ddepth = src.depth(); + IppiSize roi = {src.cols, src.rows}; + IppiMaskSize kernel = (IppiMaskSize)(ksize*10+ksize); + if (src.type() == CV_8U && dst.type() == CV_16S && scale == 1) { +#if IPP_VERSION_X100 >= 900 + if(ippiFilterSobelGetBufferSize(roi, kernel, ippNormL2, ipp8u, ipp16s, 1, &bufSize) < 0) + return false; + buffer.allocate(bufSize); +#endif + if ((dx == 1) && (dy == 0)) { - if (0 > ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR +#if IPP_VERSION_X100 < 900 + if (0 > ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelNegVertBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; return true; } if ((dx == 0) && (dy == 1)) { - if (0 > ippiFilterSobelHorizGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR +#if IPP_VERSION_X100 < 900 + if (0 > ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelHorizBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; return true; } #if !defined(HAVE_IPP_ICV_ONLY) if ((dx == 2) && (dy == 0)) { - if (0 > ippiFilterSobelVertSecondGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR +#if IPP_VERSION_X100 < 900 + if (0 > ippiFilterSobelVertSecondGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelVertSecondBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; return true; } if ((dx == 0) && (dy == 2)) { - if (0 > ippiFilterSobelHorizSecondGetBufferSize_8u16s_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR +#if IPP_VERSION_X100 < 900 + if (0 > ippiFilterSobelHorizSecondGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelHorizSecondBorder_8u16s_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; return true; } #endif @@ -482,17 +392,25 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if (src.type() == CV_32F && dst.type() == CV_32F) { -#if 0 +#if IPP_VERSION_X100 >= 900 + if(ippiFilterSobelGetBufferSize(roi, kernel, ippNormL2, ipp32f, ipp32f, 1, &bufSize) < 0) + return false; + buffer.allocate(bufSize); +#endif + +#if IPP_DISABLE_BLOCK if ((dx == 1) && (dy == 0)) { - if (0 > ippiFilterSobelNegVertGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), &bufSize)) - IPP_RETURN_ERROR +#if IPP_VERSION_X100 < 900 + if (0 > ippiFilterSobelNegVertGetBufferSize_32f_C1R(roi, kernel, &bufSize)) + return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelNegVertBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; if(scale != 1) ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); return true; @@ -500,13 +418,16 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if ((dx == 0) && (dy == 1)) { - if (0 > ippiFilterSobelHorizGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR +#if IPP_VERSION_X100 < 900 + if (0 > ippiFilterSobelHorizGetBufferSize_32f_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); +#endif + if (0 > ippiFilterSobelHorizBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; if(scale != 1) ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); return true; @@ -515,14 +436,16 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, #if !defined(HAVE_IPP_ICV_ONLY) if((dx == 2) && (dy == 0)) { - if (0 > ippiFilterSobelVertSecondGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR +#if IPP_VERSION_X100 < 900 + if (0 > ippiFilterSobelVertSecondGetBufferSize_32f_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelVertSecondBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; if(scale != 1) ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); return true; @@ -530,14 +453,16 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, if((dx == 0) && (dy == 2)) { - if (0 > ippiFilterSobelHorizSecondGetBufferSize_32f_C1R(ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize),&bufSize)) - IPP_RETURN_ERROR +#if IPP_VERSION_X100 < 900 + if (0 > ippiFilterSobelHorizSecondGetBufferSize_32f_C1R(roi, kernel,&bufSize)) + return false; buffer.allocate(bufSize); +#endif if (0 > ippiFilterSobelHorizSecondBorder_32f_C1R(src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, ippiSize(src.cols, src.rows), (IppiMaskSize)(ksize*10+ksize), + dst.ptr(), (int)dst.step, roi, kernel, ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - IPP_RETURN_ERROR + return false; if(scale != 1) ippiMulC_32f_C1R(dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); @@ -547,41 +472,22 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, } return false; } -#ifdef HAVE_IPP + static bool ipp_sobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) { if (ksize < 0) { if (IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)) - { - CV_IMPL_ADD(CV_IMPL_IPP); return true; - } } else if (0 < ksize) { if (IPPDerivSobel(_src, _dst, ddepth, dx, dy, ksize, scale, delta, borderType)) - { - CV_IMPL_ADD(CV_IMPL_IPP); return true; - } } return false; } -static bool ipp_scharr(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) -{ -#if IPP_VERSION_MAJOR >= 7 - if (IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return true; - } -#endif - return false; } -#endif -} - #endif void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, @@ -604,10 +510,8 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, } #endif - CV_IPP_RUN(true, ipp_sobel(_src, _dst, ddepth, dx, dy, ksize, scale, delta, borderType)); - int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); Mat kx, ky; @@ -643,9 +547,7 @@ void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, } #endif - - CV_IPP_RUN(true, ipp_scharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)); - + CV_IPP_RUN(true, IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)); int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); @@ -800,7 +702,7 @@ static bool ocl_Laplacian5(InputArray _src, OutputArray _dst, else k.args(d2xarg, d2yarg, dstarg, iscale, idelta); - size_t globalsize[] = { dst.cols * cn / kercn, dst.rows }; + size_t globalsize[] = { (size_t)dst.cols * cn / kercn, (size_t)dst.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/src/distransform.cpp b/modules/imgproc/src/distransform.cpp index a6491086e..cde6ec4eb 100644 --- a/modules/imgproc/src/distransform.cpp +++ b/modules/imgproc/src/distransform.cpp @@ -785,7 +785,7 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe { if( maskSize == CV_DIST_MASK_3 ) { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) CV_IPP_CHECK() { IppiSize roi = { src.cols, src.rows }; @@ -802,7 +802,7 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe } else { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) CV_IPP_CHECK() { IppiSize roi = { src.cols, src.rows }; diff --git a/modules/imgproc/src/drawing.cpp b/modules/imgproc/src/drawing.cpp index c2db76482..f9d8bb0d3 100644 --- a/modules/imgproc/src/drawing.cpp +++ b/modules/imgproc/src/drawing.cpp @@ -610,12 +610,12 @@ LineAA( Mat& img, Point pt1, Point pt2, const void* color ) ICV_PUT_POINT(); ICV_PUT_POINT(); - tptr += step; + tptr += 4; a = (ep_corr * FilterTable[dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); - tptr += step; + tptr += 4; a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff; ICV_PUT_POINT(); ICV_PUT_POINT(); @@ -2090,6 +2090,10 @@ void putText( InputOutputArray _img, const String& text, Point org, int thickness, int line_type, bool bottomLeftOrigin ) { + if ( text.empty() ) + { + return; + } Mat img = _img.getMat(); const int* ascii = getFontData(fontFace); @@ -2111,7 +2115,7 @@ void putText( InputOutputArray _img, const String& text, Point org, pts.reserve(1 << 10); const char **faces = cv::g_HersheyGlyphs; - for( int i = 0; text[i] != '\0'; i++ ) + for( int i = 0; i < (int)text.size(); i++ ) { int c = (uchar)text[i]; Point p; @@ -2158,7 +2162,7 @@ Size getTextSize( const String& text, int fontFace, double fontScale, int thickn int cap_line = (ascii[0] >> 4) & 15; size.height = cvRound((cap_line + base_line)*fontScale + (thickness+1)/2); - for( int i = 0; text[i] != '\0'; i++ ) + for( int i = 0; i < (int)text.size(); i++ ) { int c = (uchar)text[i]; Point p; @@ -2232,6 +2236,7 @@ void cv::polylines(InputOutputArray _img, InputArrayOfArrays pts, Mat p = pts.getMat(manyContours ? i : -1); if( p.total() == 0 ) { + ptsptr[i] = NULL; npts[i] = 0; continue; } diff --git a/modules/imgproc/src/featureselect.cpp b/modules/imgproc/src/featureselect.cpp index e51859e01..3d5af6330 100644 --- a/modules/imgproc/src/featureselect.cpp +++ b/modules/imgproc/src/featureselect.cpp @@ -156,7 +156,7 @@ static bool ocl_goodFeaturesToTrack( InputArray _image, OutputArray _corners, thresholdarg, (int)possibleCornersCount); } - size_t globalsize[2] = { eig.cols - 2, eig.rows - 2 }; + size_t globalsize[2] = { (size_t)eig.cols - 2, (size_t)eig.rows - 2 }; if (!k.run(2, globalsize, NULL, false)) return false; diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 10c8240a9..f78296ced 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -47,7 +47,7 @@ Base Image Filter \****************************************************************************************/ -#if IPP_VERSION_X100 >= 701 +#if IPP_VERSION_X100 >= 710 #define USE_IPP_SEP_FILTERS 1 #else #undef USE_IPP_SEP_FILTERS @@ -1415,14 +1415,14 @@ struct RowVec_32f { kernel = _kernel; haveSSE = checkHardwareSupport(CV_CPU_SSE); -#if defined USE_IPP_SEP_FILTERS && 0 +#if defined USE_IPP_SEP_FILTERS && IPP_DISABLE_BLOCK bufsz = -1; #endif } int operator()(const uchar* _src, uchar* _dst, int width, int cn) const { -#if defined USE_IPP_SEP_FILTERS && 0 +#if defined USE_IPP_SEP_FILTERS && IPP_DISABLE_BLOCK CV_IPP_CHECK() { int ret = ippiOperator(_src, _dst, width, cn); @@ -1463,7 +1463,7 @@ struct RowVec_32f Mat kernel; bool haveSSE; -#if defined USE_IPP_SEP_FILTERS && 0 +#if defined USE_IPP_SEP_FILTERS && IPP_DISABLE_BLOCK private: mutable int bufsz; int ippiOperator(const uchar* _src, uchar* _dst, int width, int cn) const @@ -4031,7 +4031,7 @@ static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, cv::Mat kernelMat = _kernel.getMat(); cv::Size sz = _src.size(), wholeSize; - size_t globalsize[2] = { sz.width, sz.height }; + size_t globalsize[2] = { (size_t)sz.width, (size_t)sz.height }; size_t localsize_general[2] = {0, 1}; size_t* localsize = NULL; @@ -4579,7 +4579,11 @@ static bool ipp_filter2D( InputArray _src, OutputArray _dst, int ddepth, int stype = src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype), ktype = kernel.type(), kdepth = CV_MAT_DEPTH(ktype); bool isolated = (borderType & BORDER_ISOLATED) != 0; +#if IPP_VERSION_X100 >= 900 + Point ippAnchor((kernel.cols-1)/2, (kernel.rows-1)/2); +#else Point ippAnchor(kernel.cols >> 1, kernel.rows >> 1); +#endif int borderTypeNI = borderType & ~BORDER_ISOLATED; IppiBorderType ippBorderType = ippiGetBorderType(borderTypeNI); @@ -4610,24 +4614,64 @@ static bool ipp_filter2D( InputArray _src, OutputArray _dst, int ddepth, if ((status = ippiFilterBorderGetSize(kernelSize, dstRoiSize, dataType, kernelType, cn, &specSize, &bufsize)) >= 0) { - IppiFilterBorderSpec * spec = (IppiFilterBorderSpec *)ippMalloc(specSize); - Ipp8u * buffer = ippsMalloc_8u(bufsize); + IppAutoBuffer spec(specSize); + IppAutoBuffer buffer(bufsize); Ipp32f borderValue[4] = { 0, 0, 0, 0 }; - Mat reversedKernel; - flip(kernel, reversedKernel, -1); - - if ((kdepth == CV_32F && (status = ippiFilterBorderInit_32f((const Ipp32f *)reversedKernel.data, kernelSize, - dataType, cn, ippRndFinancial, spec)) >= 0 ) || - (kdepth == CV_16S && (status = ippiFilterBorderInit_16s((const Ipp16s *)reversedKernel.data, - kernelSize, 0, dataType, cn, ippRndFinancial, spec)) >= 0)) + if(kdepth == CV_32F) { - status = ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, dstRoiSize, - ippBorderType, borderValue, spec, buffer); - } + Ipp32f *pKerBuffer = (Ipp32f*)kernel.data; + IppAutoBuffer kerTmp; + int kerStep = sizeof(Ipp32f)*kernelSize.width; +#if IPP_VERSION_X100 >= 900 + if(kernel.step != kerStep) + { + kerTmp.Alloc(kerStep*kernelSize.height); + if(ippiCopy_32f_C1R((Ipp32f*)kernel.data, (int)kernel.step, kerTmp, kerStep, kernelSize) < 0) + return false; + pKerBuffer = kerTmp; + } +#else + kerTmp.Alloc(kerStep*kernelSize.height); + Mat kerFlip(Size(kernelSize.width, kernelSize.height), CV_32FC1, kerTmp, kerStep); + flip(kernel, kerFlip, -1); + pKerBuffer = kerTmp; +#endif - ippsFree(buffer); - ippsFree(spec); + if((status = ippiFilterBorderInit_32f(pKerBuffer, kernelSize, + dataType, cn, ippRndFinancial, spec)) >= 0 ) + { + status = ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, dstRoiSize, + ippBorderType, borderValue, spec, buffer); + } + } + else if(kdepth == CV_16S) + { + Ipp16s *pKerBuffer = (Ipp16s*)kernel.data; + IppAutoBuffer kerTmp; + int kerStep = sizeof(Ipp16s)*kernelSize.width; +#if IPP_VERSION_X100 >= 900 + if(kernel.step != kerStep) + { + kerTmp.Alloc(kerStep*kernelSize.height); + if(ippiCopy_16s_C1R((Ipp16s*)kernel.data, (int)kernel.step, kerTmp, kerStep, kernelSize) < 0) + return false; + pKerBuffer = kerTmp; + } +#else + kerTmp.Alloc(kerStep*kernelSize.height); + Mat kerFlip(Size(kernelSize.width, kernelSize.height), CV_16SC1, kerTmp, kerStep); + flip(kernel, kerFlip, -1); + pKerBuffer = kerTmp; +#endif + + if((status = ippiFilterBorderInit_16s(pKerBuffer, kernelSize, + 0, dataType, cn, ippRndFinancial, spec)) >= 0) + { + status = ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, dstRoiSize, + ippBorderType, borderValue, spec, buffer); + } + } } if (status >= 0) diff --git a/modules/imgproc/src/grabcut.cpp b/modules/imgproc/src/grabcut.cpp index c0967a1dc..36356beb4 100644 --- a/modules/imgproc/src/grabcut.cpp +++ b/modules/imgproc/src/grabcut.cpp @@ -537,7 +537,7 @@ void cv::grabCut( InputArray _img, InputOutputArray _mask, Rect rect, if( img.empty() ) CV_Error( CV_StsBadArg, "image is empty" ); if( img.type() != CV_8UC3 ) - CV_Error( CV_StsBadArg, "image mush have CV_8UC3 type" ); + CV_Error( CV_StsBadArg, "image must have CV_8UC3 type" ); GMM bgdGMM( bgdModel ), fgdGMM( fgdModel ); Mat compIdxs( img.size(), CV_32SC1 ); diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index d9c5edfd4..7e181684c 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1176,12 +1176,11 @@ calcHist_8u( std::vector& _ptrs, const std::vector& _deltas, } #ifdef HAVE_IPP - class IPPCalcHistInvoker : public ParallelLoopBody { public: - IPPCalcHistInvoker(const Mat & _src, Mat & _hist, AutoBuffer & _levels, Ipp32s _histSize, Ipp32s _low, Ipp32s _high, bool * _ok) : + IPPCalcHistInvoker(const Mat & _src, Mat & _hist, AutoBuffer & _levels, Ipp32s _histSize, Ipp32f _low, Ipp32f _high, bool * _ok) : ParallelLoopBody(), src(&_src), hist(&_hist), levels(&_levels), histSize(_histSize), low(_low), high(_high), ok(_ok) { *ok = true; @@ -1190,17 +1189,58 @@ public: virtual void operator() (const Range & range) const { Mat phist(hist->size(), hist->type(), Scalar::all(0)); +#if IPP_VERSION_X100 >= 900 + IppiSize roi = {src->cols, range.end - range.start}; + int bufferSize = 0; + int specSize = 0; + IppiHistogramSpec *pSpec = NULL; + Ipp8u *pBuffer = NULL; - IppStatus status = ippiHistogramEven_8u_C1R( - src->ptr(range.start), (int)src->step, ippiSize(src->cols, range.end - range.start), - phist.ptr(), (Ipp32s *)*levels, histSize, low, high); - - if (status < 0) + if(ippiHistogramGetBufferSize(ipp8u, roi, &histSize, 1, 1, &specSize, &bufferSize) < 0) + { + *ok = false; + return; + } + + pBuffer = (Ipp8u*)ippMalloc(bufferSize); + if(!pBuffer && bufferSize) + { + *ok = false; + return; + } + + pSpec = (IppiHistogramSpec*)ippMalloc(specSize); + if(!pSpec && specSize) + { + if(pBuffer) ippFree(pBuffer); + *ok = false; + return; + } + + if(ippiHistogramUniformInit(ipp8u, (Ipp32f*)&low, (Ipp32f*)&high, (Ipp32s*)&histSize, 1, pSpec) < 0) + { + if(pSpec) ippFree(pSpec); + if(pBuffer) ippFree(pBuffer); + *ok = false; + return; + } + + IppStatus status = ippiHistogram_8u_C1R(src->ptr(range.start), (int)src->step, ippiSize(src->cols, range.end - range.start), + phist.ptr(), pSpec, pBuffer); + + if(pSpec) ippFree(pSpec); + if(pBuffer) ippFree(pBuffer); +#else + CV_SUPPRESS_DEPRECATED_START + IppStatus status = ippiHistogramEven_8u_C1R(src->ptr(range.start), (int)src->step, ippiSize(src->cols, range.end - range.start), + phist.ptr(), (Ipp32s*)(Ipp32f*)*levels, histSize, (Ipp32s)low, (Ipp32s)high); + CV_SUPPRESS_DEPRECATED_END +#endif + if(status < 0) { *ok = false; return; } - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); for (int i = 0; i < histSize; ++i) CV_XADD((int *)(hist->data + i * hist->step), *(int *)(phist.data + i * phist.step)); @@ -1209,8 +1249,9 @@ public: private: const Mat * src; Mat * hist; - AutoBuffer * levels; - Ipp32s histSize, low, high; + AutoBuffer * levels; + Ipp32s histSize; + Ipp32f low, high; bool * ok; const IPPCalcHistInvoker & operator = (const IPPCalcHistInvoker & ); @@ -1241,7 +1282,7 @@ static bool ipp_calchist(const Mat* images, int nimages, const int* channels, !accumulate && uniform) { ihist.setTo(Scalar::all(0)); - AutoBuffer levels(histSize[0] + 1); + AutoBuffer levels(histSize[0] + 1); bool ok = true; const Mat & src = images[0]; @@ -1249,14 +1290,13 @@ static bool ipp_calchist(const Mat* images, int nimages, const int* channels, #ifdef HAVE_CONCURRENCY nstripes = 1; #endif - IPPCalcHistInvoker invoker(src, ihist, levels, histSize[0] + 1, (Ipp32s)ranges[0][0], (Ipp32s)ranges[0][1], &ok); + IPPCalcHistInvoker invoker(src, ihist, levels, histSize[0] + 1, ranges[0][0], ranges[0][1], &ok); Range range(0, src.rows); parallel_for_(range, invoker, nstripes); if (ok) { ihist.convertTo(hist, CV_32F); - CV_IMPL_ADD(CV_IMPL_IPP); return true; } } @@ -2180,7 +2220,7 @@ static bool ocl_calcBackProject( InputArrayOfArrays _images, std::vector ch mapk.args(ocl::KernelArg::ReadOnlyNoSize(im), ocl::KernelArg::PtrReadOnly(lut), ocl::KernelArg::WriteOnly(dst)); - size_t globalsize[2] = { size.width, size.height }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }; return mapk.run(2, globalsize, NULL, false); } else if (histdims == 2) @@ -2227,7 +2267,7 @@ static bool ocl_calcBackProject( InputArrayOfArrays _images, std::vector ch mapk.args(ocl::KernelArg::ReadOnlyNoSize(im0), ocl::KernelArg::ReadOnlyNoSize(im1), ocl::KernelArg::ReadOnlyNoSize(hist), ocl::KernelArg::PtrReadOnly(lut), scale, ocl::KernelArg::WriteOnly(dst)); - size_t globalsize[2] = { size.width, size.height }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }; return mapk.run(2, globalsize, NULL, false); } return false; diff --git a/modules/imgproc/src/hough.cpp b/modules/imgproc/src/hough.cpp index c5bb2e20e..ae3eef946 100644 --- a/modules/imgproc/src/hough.cpp +++ b/modules/imgproc/src/hough.cpp @@ -96,7 +96,7 @@ HoughLinesStandard( const Mat& img, float rho, float theta, int numangle = cvRound((max_theta - min_theta) / theta); int numrho = cvRound(((width + height) * 2 + 1) / rho); -#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801) +#if defined HAVE_IPP && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810 && IPP_DISABLED_BLOCK CV_IPP_CHECK() { IppiSize srcSize = { width, height }; @@ -429,7 +429,7 @@ HoughLinesProbabilistic( Mat& image, int numangle = cvRound(CV_PI / theta); int numrho = cvRound(((width + height) * 2 + 1) / rho); -#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801) +#if defined HAVE_IPP && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810 && IPP_DISABLED_BLOCK CV_IPP_CHECK() { IppiSize srcSize = { width, height }; @@ -680,8 +680,8 @@ static bool ocl_makePointsList(InputArray _src, OutputArray _pointsList, InputOu pointListKernel.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnlyNoSize(pointsList), ocl::KernelArg::PtrWriteOnly(counters)); - size_t localThreads[2] = { workgroup_size, 1 }; - size_t globalThreads[2] = { workgroup_size, src.rows }; + size_t localThreads[2] = { (size_t)workgroup_size, 1 }; + size_t globalThreads[2] = { (size_t)workgroup_size, (size_t)src.rows }; return pointListKernel.run(2, globalThreads, localThreads, false); } @@ -775,7 +775,7 @@ static bool ocl_HoughLines(InputArray _src, OutputArray _lines, double rho, doub getLinesKernel.args(ocl::KernelArg::ReadOnly(accum), ocl::KernelArg::WriteOnlyNoSize(lines), ocl::KernelArg::PtrWriteOnly(counters), linesMax, threshold, (float) rho, (float) theta); - size_t globalThreads[2] = { (numrho + pixPerWI - 1)/pixPerWI, numangle }; + size_t globalThreads[2] = { ((size_t)numrho + pixPerWI - 1)/pixPerWI, (size_t)numangle }; if (!getLinesKernel.run(2, globalThreads, NULL, false)) return false; @@ -829,7 +829,7 @@ static bool ocl_HoughLinesP(InputArray _src, OutputArray _lines, double rho, dou ocl::KernelArg::WriteOnlyNoSize(lines), ocl::KernelArg::PtrWriteOnly(counters), linesMax, threshold, (int) minLineLength, (int) maxGap, (float) rho, (float) theta); - size_t globalThreads[2] = { numrho, numangle }; + size_t globalThreads[2] = { (size_t)numrho, (size_t)numangle }; if (!getLinesKernel.run(2, globalThreads, NULL, false)) return false; diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 433e38f70..585d3a6e9 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -50,19 +50,15 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) -static IppStatus sts = ippInit(); -#endif - namespace cv { -#if IPP_VERSION_X100 >= 701 +#if IPP_VERSION_X100 >= 710 typedef IppStatus (CV_STDCALL* ippiResizeFunc)(const void*, int, const void*, int, IppiPoint, IppiSize, IppiBorderType, void*, void*, Ipp8u*); typedef IppStatus (CV_STDCALL* ippiResizeGetBufferSize)(void*, IppiSize, Ipp32u, int*); typedef IppStatus (CV_STDCALL* ippiResizeGetSrcOffset)(void*, IppiPoint, IppiPoint*); #endif -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) && 0 +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) && IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize); typedef IppStatus (CV_STDCALL* ippiWarpPerspectiveFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [3][3], int); typedef IppStatus (CV_STDCALL* ippiWarpAffineBackFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [2][3], int); @@ -2745,7 +2741,7 @@ static int computeResizeAreaTab( int ssize, int dsize, int cn, double scale, Dec getBufferSizeFunc = (ippiResizeGetBufferSize)ippiResizeGetBufferSize_##TYPE; \ getSrcOffsetFunc = (ippiResizeGetSrcOffset)ippiResizeGetSrcOffset_##TYPE; -#if IPP_VERSION_X100 >= 701 +#if IPP_VERSION_X100 >= 710 class IPPresizeInvoker : public ParallelLoopBody { @@ -2765,7 +2761,7 @@ public: switch (type) { -#if 0 // disabled since it breaks tests for CascadeClassifier +#if IPP_DISABLE_BLOCK // disabled since it breaks tests for CascadeClassifier case CV_8UC1: SET_IPP_RESIZE_PTR(8u,C1); break; case CV_8UC3: SET_IPP_RESIZE_PTR(8u,C3); break; case CV_8UC4: SET_IPP_RESIZE_PTR(8u,C4); break; @@ -2904,7 +2900,7 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, Size ssize = src.size(); ocl::Kernel k; - size_t globalsize[] = { dst.cols, dst.rows }; + size_t globalsize[] = { (size_t)dst.cols, (size_t)dst.rows }; ocl::Image2D srcImage; @@ -3092,7 +3088,7 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, #endif -#if IPP_VERSION_X100 >= 701 +#if IPP_VERSION_X100 >= 710 static bool ipp_resize_mt( Mat src, Mat dst, double inv_scale_x, double inv_scale_y, int interpolation) { @@ -3278,7 +3274,7 @@ void cv::resize( InputArray _src, OutputArray _dst, Size dsize, double ex = fabs((double)dsize.width / _src.cols() - inv_scale_x) / inv_scale_x; double ey = fabs((double)dsize.height / _src.rows() - inv_scale_y) / inv_scale_y; #endif - CV_IPP_RUN(IPP_VERSION_X100 >= 701 && ((ex < IPP_RESIZE_EPS && ey < IPP_RESIZE_EPS && depth != CV_64F) || (ex == 0 && ey == 0 && depth == CV_64F)) && + CV_IPP_RUN(IPP_VERSION_X100 >= 710 && ((ex < IPP_RESIZE_EPS && ey < IPP_RESIZE_EPS && depth != CV_64F) || (ex == 0 && ey == 0 && depth == CV_64F)) && (interpolation == INTER_LINEAR || interpolation == INTER_CUBIC) && !(interpolation == INTER_LINEAR && is_area_fast && iscale_x == 2 && iscale_y == 2 && depth == CV_8U) && mode >= 0 && (cn == 1 || cn == 3 || cn == 4) && (depth == CV_16U || depth == CV_16S || depth == CV_32F || @@ -4570,13 +4566,13 @@ static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, Input else k.args(srcarg, dstarg, map1arg, ocl::KernelArg::ReadOnlyNoSize(map2), scalararg); - size_t globalThreads[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalThreads[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalThreads, NULL, false); } #endif -#if IPP_VERSION_X100 >= 0 && !defined HAVE_IPP_ICV_ONLY && 0 +#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK typedef IppStatus (CV_STDCALL * ippiRemap)(const void * pSrc, IppiSize srcSize, int srcStep, IppiRect srcRoi, const Ipp32f* pxMap, int xMapStep, const Ipp32f* pyMap, int yMapStep, @@ -4684,7 +4680,7 @@ void cv::remap( InputArray _src, OutputArray _dst, int type = src.type(), depth = CV_MAT_DEPTH(type); -#if IPP_VERSION_X100 >= 0 && !defined HAVE_IPP_ICV_ONLY && 0 +#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if ((interpolation == INTER_LINEAR || interpolation == INTER_CUBIC || interpolation == INTER_NEAREST) && @@ -5410,7 +5406,7 @@ private: }; -#if defined (HAVE_IPP) && IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR >= 801 && 0 +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK class IPPWarpAffineInvoker : public ParallelLoopBody { @@ -5559,7 +5555,7 @@ static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0, k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst), ocl::KernelArg::PtrReadOnly(M0), ocl::KernelArg(0, 0, 0, 0, borderBuf, CV_ELEM_SIZE(sctype))); - size_t globalThreads[2] = { dst.cols, (dst.rows + rowsPerWI - 1) / rowsPerWI }; + size_t globalThreads[2] = { (size_t)dst.cols, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; return k.run(2, globalThreads, NULL, false); } @@ -5615,7 +5611,7 @@ void cv::warpAffine( InputArray _src, OutputArray _dst, const int AB_BITS = MAX(10, (int)INTER_BITS); const int AB_SCALE = 1 << AB_BITS; -#if defined (HAVE_IPP) && IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR >= 801 && 0 +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK CV_IPP_CHECK() { int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); @@ -6039,7 +6035,7 @@ private: }; -#if defined (HAVE_IPP) && IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR >= 801 && 0 +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK class IPPWarpPerspectiveInvoker : public ParallelLoopBody { @@ -6124,7 +6120,7 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0, #endif -#if defined (HAVE_IPP) && IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR >= 801 && 0 +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK CV_IPP_CHECK() { int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); diff --git a/modules/imgproc/src/main.cpp b/modules/imgproc/src/main.cpp new file mode 100644 index 000000000..127f86b26 --- /dev/null +++ b/modules/imgproc/src/main.cpp @@ -0,0 +1,52 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +// +// Library initialization file +// + +#include "precomp.hpp" + +IPP_INITIALIZER_AUTO + +/* End of file. */ diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index 3b86be234..15c4a6103 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -499,7 +499,7 @@ static bool ocl_moments( InputArray _src, Moments& m, bool binary) int ntiles = xtiles*ytiles; UMat umbuf(1, ntiles*K, CV_32S); - size_t globalsize[] = {xtiles, sz.height}, localsize[] = {1, TILE_SIZE}; + size_t globalsize[] = {(size_t)xtiles, (size_t)sz.height}, localsize[] = {1, TILE_SIZE}; bool ok = k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::PtrWriteOnly(umbuf), xtiles).run(2, globalsize, localsize, true); @@ -577,7 +577,7 @@ cv::Moments cv::moments( InputArray _src, bool binary ) if( cn > 1 ) CV_Error( CV_StsBadArg, "Invalid image type (must be single-channel)" ); -#if IPP_VERSION_X100 >= 801 && 0 +#if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if (!binary) diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 822df8e47..ee3cdc04b 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1140,7 +1140,7 @@ private: static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kernel, const Size& ksize, const Point &anchor, bool rectKernel) { -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 int type = src.type(); const Mat* _src = &src; Mat temp; @@ -1155,7 +1155,36 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern if (!rectKernel) { -#if 1 +#if IPP_VERSION_X100 >= 900 + if (((kernel.cols - 1) / 2 != anchor.x) || ((kernel.rows - 1) / 2 != anchor.y)) + return false; + #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ + case cvtype: \ + {\ + int specSize = 0, bufferSize = 0;\ + if (0 > ippiMorphologyBorderGetSize_##flavor(roiSize, kernelSize, &specSize, &bufferSize))\ + return false;\ + IppiMorphState *pSpec = (IppiMorphState*)ippMalloc(specSize);\ + Ipp8u *pBuffer = (Ipp8u*)ippMalloc(bufferSize);\ + if (0 > ippiMorphologyBorderInit_##flavor(roiSize, kernel.ptr(), kernelSize, pSpec, pBuffer))\ + {\ + ippFree(pBuffer);\ + ippFree(pSpec);\ + return false;\ + }\ + bool ok = false;\ + if (op == MORPH_ERODE)\ + ok = (0 <= ippiErodeBorder_##flavor(_src->ptr(), (int)_src->step[0], dst.ptr(), (int)dst.step[0],\ + roiSize, ippBorderRepl, 0, pSpec, pBuffer));\ + else\ + ok = (0 <= ippiDilateBorder_##flavor(_src->ptr(), (int)_src->step[0], dst.ptr(), (int)dst.step[0],\ + roiSize, ippBorderRepl, 0, pSpec, pBuffer));\ + ippFree(pBuffer);\ + ippFree(pSpec);\ + return ok;\ + }\ + break; +#else if (((kernel.cols - 1) / 2 != anchor.x) || ((kernel.rows - 1) / 2 != anchor.y)) return false; #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ @@ -1184,35 +1213,8 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern return ok;\ }\ break; -#else - IppiPoint point = {anchor.x, anchor.y}; - // this is case, which can be used with the anchor not in center of the kernel, but - // ippiMorphologyBorderGetSize_, ippiErodeBorderReplicate_ and ippiDilateBorderReplicate_ are deprecated. - #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ - case cvtype: \ - {\ - int specSize = 0;\ - int bufferSize = 0;\ - if (0 > ippiMorphologyGetSize_##flavor( roiSize.width, kernel.ptr() kernelSize, &specSize))\ - return false;\ - bool ok = false;\ - IppiMorphState* pState = (IppiMorphState*)ippMalloc(specSize);\ - if (ippiMorphologyInit_##flavor(roiSize.width, kernel.ptr(), kernelSize, point, pState) >= 0)\ - {\ - if (op == MORPH_ERODE)\ - ok = ippiErodeBorderReplicate_##flavor(_src->ptr(), (int)_src->step[0],\ - dst.ptr(), (int)dst.step[0],\ - roiSize, ippBorderRepl, pState ) >= 0;\ - else\ - ok = ippiDilateBorderReplicate_##flavor(_src->ptr(), (int)_src->step[0],\ - dst.ptr(), (int)dst.step[0],\ - roiSize, ippBorderRepl, pState ) >= 0;\ - }\ - ippFree(pState);\ - return ok;\ - }\ - break; #endif + CV_SUPPRESS_DEPRECATED_START switch (type) { IPP_MORPH_CASE(CV_8UC1, 8u_C1R, 8u); @@ -1224,14 +1226,43 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern default: ; } - + CV_SUPPRESS_DEPRECATED_END #undef IPP_MORPH_CASE } else { +#if IPP_VERSION_X100 != 900 // Problems with accuracy in 9.0.0 +#if IPP_VERSION_X100 >= 900 + if (((kernelSize.width - 1) / 2 != anchor.x) || ((kernelSize.height - 1) / 2 != anchor.y)) // Arbitrary anchor is no longer supporeted since IPP 9.0.0 + return false; + + #define IPP_MORPH_CASE(cvtype, flavor, data_type, cn) \ + case cvtype: \ + {\ + if (op == MORPH_ERODE)\ + {\ + int bufSize = 0;\ + if (0 > ippiFilterMinBorderGetBufferSize(roiSize, kernelSize, ipp##data_type, cn, &bufSize))\ + return false;\ + AutoBuffer buf(bufSize + 64);\ + uchar* buffer = alignPtr((uchar*)buf, 32);\ + return (0 <= ippiFilterMinBorder_##flavor(_src->ptr(), (int)_src->step[0], dst.ptr(), (int)dst.step[0], roiSize, kernelSize, ippBorderRepl, 0, buffer));\ + }\ + else\ + {\ + int bufSize = 0;\ + if (0 > ippiFilterMaxBorderGetBufferSize(roiSize, kernelSize, ipp##data_type, cn, &bufSize))\ + return false;\ + AutoBuffer buf(bufSize + 64);\ + uchar* buffer = alignPtr((uchar*)buf, 32);\ + return (0 <= ippiFilterMaxBorder_##flavor(_src->ptr(), (int)_src->step[0], dst.ptr(), (int)dst.step[0], roiSize, kernelSize, ippBorderRepl, 0, buffer));\ + }\ + }\ + break; +#else IppiPoint point = {anchor.x, anchor.y}; - #define IPP_MORPH_CASE(cvtype, flavor, data_type) \ + #define IPP_MORPH_CASE(cvtype, flavor, data_type, cn) \ case cvtype: \ {\ int bufSize = 0;\ @@ -1244,19 +1275,23 @@ static bool ipp_MorphReplicate(int op, const Mat &src, Mat &dst, const Mat &kern return (0 <= ippiFilterMaxBorderReplicate_##flavor(_src->ptr(), (int)_src->step[0], dst.ptr(), (int)dst.step[0], roiSize, kernelSize, point, buffer));\ }\ break; +#endif + CV_SUPPRESS_DEPRECATED_START switch (type) { - IPP_MORPH_CASE(CV_8UC1, 8u_C1R, 8u); - IPP_MORPH_CASE(CV_8UC3, 8u_C3R, 8u); - IPP_MORPH_CASE(CV_8UC4, 8u_C4R, 8u); - IPP_MORPH_CASE(CV_32FC1, 32f_C1R, 32f); - IPP_MORPH_CASE(CV_32FC3, 32f_C3R, 32f); - IPP_MORPH_CASE(CV_32FC4, 32f_C4R, 32f); + IPP_MORPH_CASE(CV_8UC1, 8u_C1R, 8u, 1); + IPP_MORPH_CASE(CV_8UC3, 8u_C3R, 8u, 3); + IPP_MORPH_CASE(CV_8UC4, 8u_C4R, 8u, 4); + IPP_MORPH_CASE(CV_32FC1, 32f_C1R, 32f, 1); + IPP_MORPH_CASE(CV_32FC3, 32f_C3R, 32f, 3); + IPP_MORPH_CASE(CV_32FC4, 32f_C4R, 32f, 4); default: ; } + CV_SUPPRESS_DEPRECATED_END #undef IPP_MORPH_CASE +#endif } #else CV_UNUSED(op); CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(kernel); CV_UNUSED(ksize); CV_UNUSED(anchor); CV_UNUSED(rectKernel); @@ -1376,7 +1411,7 @@ static bool ocl_morphSmall( InputArray _src, OutputArray _dst, InputArray _kerne const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" }; - size_t globalsize[2] = { size.width, size.height }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }; UMat src = _src.getUMat(); if (!isolated) @@ -1557,7 +1592,7 @@ static bool ocl_morphOp(InputArray _src, OutputArray _dst, InputArray _kernel, #else size_t localThreads[2] = { 16, 16 }; #endif - size_t globalThreads[2] = { ssize.width, ssize.height }; + size_t globalThreads[2] = { (size_t)ssize.width, (size_t)ssize.height }; #ifdef __APPLE__ if( actual_op != MORPH_ERODE && actual_op != MORPH_DILATE ) @@ -1715,7 +1750,7 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, iterations = 1; } - CV_IPP_RUN(IPP_VERSION_X100 >= 801, ipp_MorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue)) + CV_IPP_RUN(IPP_VERSION_X100 >= 810, ipp_MorphOp(op, _src, _dst, kernel, anchor, iterations, borderType, borderValue)) Mat src = _src.getMat(); _dst.create( src.size(), src.type() ); diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index 1d8c94333..0d311e22f 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -1107,8 +1107,8 @@ static bool ocl_pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, in k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::WriteOnly(dst)); - size_t localThreads[2] = { local_size/kercn, 1 }; - size_t globalThreads[2] = { (src.cols + (kercn-1))/kercn, (dst.rows + 1) / 2 }; + size_t localThreads[2] = { (size_t)local_size/kercn, 1 }; + size_t globalThreads[2] = { ((size_t)src.cols + (kercn-1))/kercn, ((size_t)dst.rows + 1) / 2 }; return k.run(2, globalThreads, localThreads, false); } @@ -1144,8 +1144,8 @@ static bool ocl_pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int doubleSupport ? " -D DOUBLE_SUPPORT" : "", ocl::typeToStr(depth), channels, local_size ); - size_t globalThreads[2] = { dst.cols, dst.rows }; - size_t localThreads[2] = { local_size, local_size }; + size_t globalThreads[2] = { (size_t)dst.cols, (size_t)dst.rows }; + size_t localThreads[2] = { (size_t)local_size, (size_t)local_size }; ocl::Kernel k; if (ocl::Device::getDefault().isIntel() && channels == 1) { @@ -1171,7 +1171,7 @@ namespace cv { static bool ipp_pyrdown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { -#if IPP_VERSION_X100 >= 801 && 0 +#if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Size dsz = _dsz.area() == 0 ? Size((_src.cols() + 1)/2, (_src.rows() + 1)/2) : _dsz; bool isolated = (borderType & BORDER_ISOLATED) != 0; int borderTypeNI = borderType & ~BORDER_ISOLATED; @@ -1276,7 +1276,7 @@ namespace cv { static bool ipp_pyrup( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType ) { -#if IPP_VERSION_X100 >= 801 && 0 +#if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Size sz = _src.dims() <= 2 ? _src.size() : Size(); Size dsz = _dsz.area() == 0 ? Size(_src.cols()*2, _src.rows()*2) : _dsz; @@ -1375,12 +1375,12 @@ void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderT } -#if 0 //#ifdef HAVE_IPP +#ifdef HAVE_IPP namespace cv { static bool ipp_buildpyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel, int borderType ) { -#if IPP_VERSION_X100 >= 801 && 0 +#if IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK Mat src = _src.getMat(); _dst.create( maxlevel + 1, 1, 0 ); _dst.getMatRef(0) = src; @@ -1508,13 +1508,8 @@ void cv::buildPyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel, int i=1; -#if (IPP_VERSION_X100 >= 801 && 0) - bool isolated = (borderType & BORDER_ISOLATED) != 0; - int borderTypeNI = borderType & ~BORDER_ISOLATED; - CV_IPP_RUN(((IPP_VERSION_X100 >= 801 && 0) && (borderTypeNI == BORDER_DEFAULT && (!_src.isSubmatrix() || isolated))), + CV_IPP_RUN(((IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK) && ((borderType & ~BORDER_ISOLATED) == BORDER_DEFAULT && (!_src.isSubmatrix() || ((borderType & BORDER_ISOLATED) != 0)))), ipp_buildpyramid( _src, _dst, maxlevel, borderType)); -#endif - for( ; i <= maxlevel; i++ ) pyrDown( _dst.getMatRef(i-1), _dst.getMatRef(i), Size(), borderType ); diff --git a/modules/imgproc/src/rotcalipers.cpp b/modules/imgproc/src/rotcalipers.cpp index bfcc6ea26..c80636bdc 100644 --- a/modules/imgproc/src/rotcalipers.cpp +++ b/modules/imgproc/src/rotcalipers.cpp @@ -184,24 +184,28 @@ static void rotatingCalipers( const Point2f* points, int n, int mode, float* out /* compute cosine of angle between calipers side and polygon edge */ /* dp - dot product */ - float dp0 = base_a * vect[seq[0]].x + base_b * vect[seq[0]].y; - float dp1 = -base_b * vect[seq[1]].x + base_a * vect[seq[1]].y; - float dp2 = -base_a * vect[seq[2]].x - base_b * vect[seq[2]].y; - float dp3 = base_b * vect[seq[3]].x - base_a * vect[seq[3]].y; + float dp[4] = { + +base_a * vect[seq[0]].x + base_b * vect[seq[0]].y, + -base_b * vect[seq[1]].x + base_a * vect[seq[1]].y, + -base_a * vect[seq[2]].x - base_b * vect[seq[2]].y, + +base_b * vect[seq[3]].x - base_a * vect[seq[3]].y, + }; - float cosalpha = dp0 * inv_vect_length[seq[0]]; - float maxcos = cosalpha; + float maxcos = dp[0] * inv_vect_length[seq[0]]; /* number of calipers edges, that has minimal angle with edge */ int main_element = 0; /* choose minimal angle */ - cosalpha = dp1 * inv_vect_length[seq[1]]; - maxcos = (cosalpha > maxcos) ? (main_element = 1, cosalpha) : maxcos; - cosalpha = dp2 * inv_vect_length[seq[2]]; - maxcos = (cosalpha > maxcos) ? (main_element = 2, cosalpha) : maxcos; - cosalpha = dp3 * inv_vect_length[seq[3]]; - maxcos = (cosalpha > maxcos) ? (main_element = 3, cosalpha) : maxcos; + for ( i = 1; i < 4; ++i ) + { + float cosalpha = dp[i] * inv_vect_length[seq[i]]; + if (cosalpha > maxcos) + { + main_element = i; + maxcos = cosalpha; + } + } /*rotate calipers*/ { diff --git a/modules/imgproc/src/samplers.cpp b/modules/imgproc/src/samplers.cpp index c592138ea..c89bd32e0 100644 --- a/modules/imgproc/src/samplers.cpp +++ b/modules/imgproc/src/samplers.cpp @@ -374,7 +374,7 @@ void cv::getRectSubPix( InputArray _image, Size patchSize, Point2f center, _patch.create(patchSize, CV_MAKETYPE(ddepth, cn)); Mat patch = _patch.getMat(); -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) CV_IPP_CHECK() { typedef IppStatus (CV_STDCALL *ippiGetRectSubPixFunc)( const void* src, int src_step, diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 012b90418..855c43283 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1057,7 +1057,7 @@ static bool ocl_boxFilter( InputArray _src, OutputArray _dst, int ddepth, wtype = CV_MAKE_TYPE(wdepth, cn), dtype = CV_MAKE_TYPE(ddepth, cn); const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", 0, "BORDER_REFLECT_101" }; - size_t globalsize[2] = { size.width, size.height }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }; size_t localsize_general[2] = { 0, 1 }, * localsize = NULL; UMat src = _src.getUMat(); @@ -1668,6 +1668,7 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) { +#if IPP_VERSION_X100 >= 810 int type = _src.type(); Size size = _src.size(); @@ -1694,32 +1695,33 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, if (ippiFilterGaussianGetBufferSize(roiSize, (Ipp32u)ksize.width, dataType, cn, &specSize, &bufferSize) >= 0) { - IppFilterGaussianSpec * pSpec = (IppFilterGaussianSpec *)ippMalloc(specSize); - Ipp8u * pBuffer = (Ipp8u*)ippMalloc(bufferSize); + IppAutoBuffer spec(specSize); + IppAutoBuffer buffer(bufferSize); - if (ippiFilterGaussianInit(roiSize, (Ipp32u)ksize.width, (Ipp32f)sigma1, ippBorder, dataType, 1, pSpec, pBuffer) >= 0) + if (ippiFilterGaussianInit(roiSize, (Ipp32u)ksize.width, (Ipp32f)sigma1, ippBorder, dataType, cn, spec, buffer) >= 0) { #define IPP_FILTER_GAUSS_C1(ippfavor) \ { \ - typedef Ipp##ippfavor ippType; \ - ippType borderValues = 0; \ - status = ippiFilterGaussianBorder_##ippfavor##_C1R(src.ptr(), (int)src.step, \ - dst.ptr(), (int)dst.step, roiSize, borderValues, pSpec, pBuffer); \ + Ipp##ippfavor borderValues = 0; \ + status = ippiFilterGaussianBorder_##ippfavor##_C1R(src.ptr(), (int)src.step, \ + dst.ptr(), (int)dst.step, roiSize, borderValues, spec, buffer); \ } #define IPP_FILTER_GAUSS_CN(ippfavor, ippcn) \ { \ - typedef Ipp##ippfavor ippType; \ - ippType borderValues[] = { 0, 0, 0 }; \ - status = ippiFilterGaussianBorder_##ippfavor##_C##ippcn##R(src.ptr(), (int)src.step, \ - dst.ptr(), (int)dst.step, roiSize, borderValues, pSpec, pBuffer); \ + Ipp##ippfavor borderValues[] = { 0, 0, 0 }; \ + status = ippiFilterGaussianBorder_##ippfavor##_C##ippcn##R(src.ptr(), (int)src.step, \ + dst.ptr(), (int)dst.step, roiSize, borderValues, spec, buffer); \ } IppStatus status = ippStsErr; #if !HAVE_ICV +#if IPP_VERSION_X100 > 901 // Buffer overflow in IPP if (type == CV_8UC1) IPP_FILTER_GAUSS_C1(8u) - else if (type == CV_8UC3) + else +#endif + if (type == CV_8UC3) IPP_FILTER_GAUSS_CN(8u, 3) else if (type == CV_16UC1) IPP_FILTER_GAUSS_C1(16u) @@ -1736,16 +1738,8 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, if (type == CV_32FC1) IPP_FILTER_GAUSS_C1(32f) - if (pSpec) - ippFree(pSpec); - if (pBuffer) - ippFree(pBuffer); - if(status >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); return true; - } #undef IPP_FILTER_GAUSS_C1 #undef IPP_FILTER_GAUSS_CN @@ -1753,6 +1747,9 @@ static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, } } } +#else + CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ksize); CV_UNUSED(sigma1); CV_UNUSED(sigma2); CV_UNUSED(borderType); +#endif return false; } } @@ -1788,10 +1785,8 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, return; #endif - CV_IPP_RUN(true, ipp_GaussianBlur( _src, _dst, ksize, sigma1, sigma2, borderType)); - Mat kx, ky; createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2); sepFilter2D(_src, _dst, CV_MAT_DEPTH(type), kx, ky, Point(-1,-1), 0, borderType ); @@ -2708,7 +2703,7 @@ namespace cv { static bool ipp_medianFilter( InputArray _src0, OutputArray _dst, int ksize ) { -#if IPP_VERSION_X100 >= 801 +#if IPP_VERSION_X100 >= 810 Mat src0 = _src0.getMat(); _dst.create( src0.size(), src0.type() ); Mat dst = _dst.getMat(); @@ -2754,6 +2749,8 @@ static bool ipp_medianFilter( InputArray _src0, OutputArray _dst, int ksize ) IPP_FILTER_MEDIAN_BORDER(Ipp32f, ipp32f, 32f_C1R); } #undef IPP_FILTER_MEDIAN_BORDER +#else + CV_UNUSED(_src0); CV_UNUSED(_dst); CV_UNUSED(ksize); #endif return false; } @@ -2777,7 +2774,7 @@ void cv::medianBlur( InputArray _src0, OutputArray _dst, int ksize ) _dst.create( src0.size(), src0.type() ); Mat dst = _dst.getMat(); - CV_IPP_RUN(IPP_VERSION_X100 >= 801 && ksize <= 5, ipp_medianFilter(_src0,_dst, ksize)); + CV_IPP_RUN(IPP_VERSION_X100 >= 810 && ksize <= 5, ipp_medianFilter(_src0,_dst, ksize)); #ifdef HAVE_TEGRA_OPTIMIZATION if (tegra::useTegra() && tegra::medianBlur(src0, dst, ksize)) @@ -2995,7 +2992,7 @@ private: float *space_weight, *color_weight; }; -#if defined (HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && 0 +#if defined (HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_DISABLE_BLOCK class IPPBilateralFilter_8u_Invoker : public ParallelLoopBody { @@ -3131,7 +3128,7 @@ static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d, ocl::KernelArg::PtrReadOnly(uspace_weight), ocl::KernelArg::PtrReadOnly(uspace_ofs)); - size_t globalsize[2] = { dst.cols / sizeDiv, dst.rows }; + size_t globalsize[2] = { (size_t)dst.cols / sizeDiv, (size_t)dst.rows }; return k.run(2, globalsize, NULL, false); } @@ -3165,7 +3162,7 @@ bilateralFilter_8u( const Mat& src, Mat& dst, int d, Mat temp; copyMakeBorder( src, temp, radius, radius, radius, radius, borderType ); -#if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7) && 0 +#if defined HAVE_IPP && (IPP_VERSION_X100 >= 700) && IPP_DISABLE_BLOCK CV_IPP_CHECK() { if( cn == 1 ) diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index a6e86f6c0..7771d2cab 100755 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -44,10 +44,6 @@ #include "precomp.hpp" #include "opencl_kernels_imgproc.hpp" -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) -static IppStatus sts = ippInit(); -#endif - namespace cv { @@ -429,7 +425,7 @@ namespace cv { static bool ipp_integral(InputArray _src, OutputArray _sum, OutputArray _sqsum, OutputArray _tilted, int sdepth, int sqdepth) { -#if !defined(HAVE_IPP_ICV_ONLY) // Disabled on ICV due invalid results +#if !defined(HAVE_IPP_ICV_ONLY) && (IPP_VERSION_X100 != 900) // Disabled on ICV due invalid results int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); if( sdepth <= 0 ) sdepth = depth == CV_8U ? CV_32S : CV_64F; diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index e5f4986cf..59b07032b 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -72,7 +72,7 @@ static bool extractFirstChannel_32F(InputArray _image, OutputArray _result, int UMat result = _result.getUMat(); - size_t globalsize[2] = {result.cols, (result.rows+pxPerWIy-1)/pxPerWIy}; + size_t globalsize[2] = {(size_t)result.cols, ((size_t)result.rows+pxPerWIy-1)/pxPerWIy}; return k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::WriteOnly(result)).run( 2, globalsize, NULL, false); } @@ -286,7 +286,7 @@ static bool matchTemplateNaive_CCORR(InputArray _image, InputArray _templ, Outpu k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)); - size_t globalsize[2] = { (result.cols+pxPerWIx-1)/pxPerWIx, result.rows}; + size_t globalsize[2] = { ((size_t)result.cols+pxPerWIx-1)/pxPerWIx, (size_t)result.rows}; return k.run(2, globalsize, NULL, false); } @@ -338,7 +338,7 @@ static bool matchTemplate_CCORR_NORMED(InputArray _image, InputArray _templ, Out k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum)); - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } @@ -363,7 +363,7 @@ static bool matchTemplateNaive_SQDIFF(InputArray _image, InputArray _templ, Outp k.args(ocl::KernelArg::ReadOnlyNoSize(image), ocl::KernelArg::ReadOnly(templ), ocl::KernelArg::WriteOnly(result)); - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } @@ -396,7 +396,7 @@ static bool matchTemplate_SQDIFF(InputArray _image, InputArray _templ, OutputArr k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum)); - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } @@ -427,7 +427,7 @@ static bool matchTemplate_SQDIFF_NORMED(InputArray _image, InputArray _templ, Ou k.args(ocl::KernelArg::ReadOnlyNoSize(image_sqsums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, ocl::KernelArg::PtrReadOnly(templ_sqsum)); - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } @@ -465,7 +465,7 @@ static bool matchTemplate_CCOEFF(InputArray _image, InputArray _templ, OutputArr k.args(ocl::KernelArg::ReadOnlyNoSize(image_sums), ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, templ_sum); } - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } @@ -533,7 +533,7 @@ static bool matchTemplate_CCOEFF_NORMED(InputArray _image, InputArray _templ, Ou ocl::KernelArg::ReadWrite(result), templ.rows, templ.cols, scale, templ_sum, templ_sqsum_sum); } - size_t globalsize[2] = { result.cols, result.rows }; + size_t globalsize[2] = { (size_t)result.cols, (size_t)result.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 66665f978..0b61347fd 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -907,7 +907,7 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) #ifdef HAVE_IPP static bool ipp_getThreshVal_Otsu_8u( const unsigned char* _src, int step, Size size, unsigned char &thresh) { -#if IPP_VERSION_X100 >= 801 && !HAVE_ICV +#if IPP_VERSION_X100 >= 810 && !HAVE_ICV int ippStatus = -1; IppiSize srcSize = { size.width, size.height }; CV_SUPPRESS_DEPRECATED_START @@ -937,7 +937,7 @@ getThreshVal_Otsu_8u( const Mat& _src ) #ifdef HAVE_IPP unsigned char thresh; - CV_IPP_RUN(IPP_VERSION_X100 >= 801 && !HAVE_ICV, ipp_getThreshVal_Otsu_8u(_src.ptr(), step, size, thresh), thresh); + CV_IPP_RUN(IPP_VERSION_X100 >= 810 && !HAVE_ICV, ipp_getThreshVal_Otsu_8u(_src.ptr(), step, size, thresh), thresh); #endif const int N = 256; @@ -1180,7 +1180,7 @@ static bool ocl_threshold( InputArray _src, OutputArray _dst, double & thresh, d ocl::KernelArg::Constant(Mat(1, 1, depth, Scalar::all(maxval))), ocl::KernelArg::Constant(Mat(1, 1, depth, Scalar::all(min_val)))); - size_t globalsize[2] = { dst.cols * cn / kercn, dst.rows }; + size_t globalsize[2] = { (size_t)dst.cols * cn / kercn, (size_t)dst.rows }; globalsize[1] = (globalsize[1] + stride_size - 1) / stride_size; return k.run(2, globalsize, NULL, false); } diff --git a/modules/imgproc/test/ocl/test_color.cpp b/modules/imgproc/test/ocl/test_color.cpp index 6e117cdd5..160c03534 100644 --- a/modules/imgproc/test/ocl/test_color.cpp +++ b/modules/imgproc/test/ocl/test_color.cpp @@ -155,7 +155,7 @@ OCL_TEST_P(CvtColor, YCrCb2BGRA) { performTest(3, 4, CVTCODE(YCrCb2BGR)); } // RGB <-> XYZ -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define IPP_EPS depth <= CV_32S ? 1 : 5e-5 #else #define IPP_EPS 1e-3 @@ -175,7 +175,7 @@ OCL_TEST_P(CvtColor, XYZ2BGRA) { performTest(3, 4, CVTCODE(XYZ2BGR), IPP_EPS); } // RGB <-> HSV -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define IPP_EPS depth <= CV_32S ? 1 : 4e-5 #else #define IPP_EPS 1e-3 @@ -207,7 +207,7 @@ OCL_TEST_P(CvtColor8u32f, HSV2BGRA_FULL) { performTest(3, 4, CVTCODE(HSV2BGR_FUL // RGB <-> HLS -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define IPP_EPS depth == CV_8U ? 2 : 1e-3 #else #define IPP_EPS depth == CV_8U ? 1 : 1e-3 @@ -269,7 +269,7 @@ OCL_TEST_P(CvtColor8u, GRAY2BGR555) { performTest(1, 2, CVTCODE(GRAY2BGR555)); } // RGBA <-> mRGBA -#if IPP_VERSION_X100 > 0 +#ifdef HAVE_IPP #define IPP_EPS depth <= CV_32S ? 1 : 1e-3 #else #define IPP_EPS 1e-3 diff --git a/modules/imgproc/test/test_cvtyuv.cpp b/modules/imgproc/test/test_cvtyuv.cpp index 0cce64cdb..5db497269 100644 --- a/modules/imgproc/test/test_cvtyuv.cpp +++ b/modules/imgproc/test/test_cvtyuv.cpp @@ -548,7 +548,7 @@ void referenceRGB2YUV(const Mat& rgb, Mat& yuv, RGBreader* rgbReader, YUVwriter* struct ConversionYUV { - ConversionYUV( const int code ) + explicit ConversionYUV( const int code ) { yuvReader_ = YUVreader :: getReader(code); yuvWriter_ = YUVwriter :: getWriter(code); @@ -557,6 +557,24 @@ struct ConversionYUV grayWriter_ = GRAYwriter:: getWriter(code); } + ~ConversionYUV() + { + if (yuvReader_) + delete yuvReader_; + + if (yuvWriter_) + delete yuvWriter_; + + if (rgbReader_) + delete rgbReader_; + + if (rgbWriter_) + delete rgbWriter_; + + if (grayWriter_) + delete grayWriter_; + } + int getDcn() { return (rgbWriter_ != 0) ? rgbWriter_->channels() : ((grayWriter_ != 0) ? grayWriter_->channels() : yuvWriter_->channels()); diff --git a/modules/imgproc/test/test_floodfill.cpp b/modules/imgproc/test/test_floodfill.cpp index d919b1602..bb34449fd 100644 --- a/modules/imgproc/test/test_floodfill.cpp +++ b/modules/imgproc/test/test_floodfill.cpp @@ -508,6 +508,8 @@ _exit_: comp[7] = new_val.val[2]; #endif comp[8] = 0; + + cvReleaseMemStorage(&st); } diff --git a/modules/imgproc/test/test_houghLines.cpp b/modules/imgproc/test/test_houghLines.cpp index fd9783b31..cf6dc87d9 100644 --- a/modules/imgproc/test/test_houghLines.cpp +++ b/modules/imgproc/test/test_houghLines.cpp @@ -189,7 +189,7 @@ void BaseHoughLineTest::run_test(int type) else if (type == PROBABILISTIC) count = countMatIntersection(exp_lines, lines, 1e-4f, 0.f); -#if (0 && defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801) +#if defined HAVE_IPP && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 810 && IPP_DISABLED_BLOCK EXPECT_GE( count, (int) (exp_lines.total() * 0.8) ); #else EXPECT_EQ( count, (int) exp_lines.total()); diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index 4ffd50b41..0568cbce0 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -1372,17 +1372,65 @@ void CV_GetQuadSubPixTest::prepare_to_validation( int /*test_case_idx*/ ) dst.convertTo(dst0, dst0.depth()); } +////////////////////////////// resizeArea ///////////////////////////////// + +template +static void check_resize_area(const Mat& expected, const Mat& actual, double tolerance = 1.0) +{ + ASSERT_EQ(actual.type(), expected.type()); + ASSERT_EQ(actual.size(), expected.size()); + + Mat diff; + absdiff(actual, expected, diff); + + Mat one_channel_diff = diff; //.reshape(1); + + Size dsize = actual.size(); + bool next = true; + for (int dy = 0; dy < dsize.height && next; ++dy) + { + const T* eD = expected.ptr(dy); + const T* aD = actual.ptr(dy); + + for (int dx = 0; dx < dsize.width && next; ++dx) + if (fabs(static_cast(aD[dx] - eD[dx])) > tolerance) + { + cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast(norm(actual, expected, NORM_INF))); + cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy); + + const int radius = 3; + int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height); + int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width); + + std::cout << "Abs diff:" << std::endl << diff << std::endl; + std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; + std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; + + next = false; + } + } + + ASSERT_EQ(0, norm(one_channel_diff, cv::NORM_INF)); +} + +/////////////////////////////////////////////////////////////////////////// + TEST(Imgproc_cvWarpAffine, regression) { IplImage* src = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1); IplImage* dst = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1); + cvZero(src); + float m[6]; CvMat M = cvMat( 2, 3, CV_32F, m ); int w = src->width; int h = src->height; cv2DRotationMatrix(cvPoint2D32f(w*0.5f, h*0.5f), 45.0, 1.0, &M); cvWarpAffine(src, dst, &M); + + cvReleaseImage(&src); + cvReleaseImage(&dst); } TEST(Imgproc_fitLine_vector_3d, regression) @@ -1496,41 +1544,45 @@ TEST(Imgproc_resize_area, regression) cv::resize(src, actual, cv::Size(), 0.3, 0.3, INTER_AREA); - ASSERT_EQ(actual.type(), expected.type()); - ASSERT_EQ(actual.size(), expected.size()); + check_resize_area(expected, actual, 1.0); +} - Mat diff; - absdiff(actual, expected, diff); +TEST(Imgproc_resize_area, regression_half_round) +{ + static uchar input_data[32 * 32]; + for(int i = 0; i < 32 * 32; ++i) + input_data[i] = (uchar)(i % 2 + 253 + i / (16 * 32)); - Mat one_channel_diff = diff; //.reshape(1); + static uchar expected_data[16 * 16]; + for(int i = 0; i < 16 * 16; ++i) + expected_data[i] = (uchar)(254 + i / (16 * 8)); - float elem_diff = 1.0f; - Size dsize = actual.size(); - bool next = true; - for (int dy = 0; dy < dsize.height && next; ++dy) - { - ushort* eD = expected.ptr(dy); - ushort* aD = actual.ptr(dy); + cv::Mat src(32, 32, CV_8UC1, input_data); + cv::Mat expected(16, 16, CV_8UC1, expected_data); + cv::Mat actual(expected.size(), expected.type()); - for (int dx = 0; dx < dsize.width && next; ++dx) - if (fabs(static_cast(aD[dx] - eD[dx])) > elem_diff) - { - cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast(norm(actual, expected, NORM_INF))); - cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy); + cv::resize(src, actual, cv::Size(), 0.5, 0.5, INTER_AREA); - const int radius = 3; - int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height); - int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width); + check_resize_area(expected, actual, 0.5); +} - std::cout << "Abs diff:" << std::endl << diff << std::endl; - std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; - std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl; +TEST(Imgproc_resize_area, regression_quarter_round) +{ + static uchar input_data[32 * 32]; + for(int i = 0; i < 32 * 32; ++i) + input_data[i] = (uchar)(i % 2 + 253 + i / (16 * 32)); - next = false; - } - } + static uchar expected_data[8 * 8]; + for(int i = 0; i < 8 * 8; ++i) + expected_data[i] = 254; - ASSERT_EQ(cvtest::norm(one_channel_diff, cv::NORM_INF), 0); + cv::Mat src(32, 32, CV_8UC1, input_data); + cv::Mat expected(8, 8, CV_8UC1, expected_data); + cv::Mat actual(expected.size(), expected.type()); + + cv::resize(src, actual, cv::Size(), 0.25, 0.25, INTER_AREA); + + check_resize_area(expected, actual, 0.5); } diff --git a/modules/imgproc/test/test_imgwarp_strict.cpp b/modules/imgproc/test/test_imgwarp_strict.cpp index 00d383a02..4756b7f42 100644 --- a/modules/imgproc/test/test_imgwarp_strict.cpp +++ b/modules/imgproc/test/test_imgwarp_strict.cpp @@ -651,8 +651,7 @@ private: }; CV_Remap_Test::CV_Remap_Test() : - CV_ImageWarpBaseTest(), mapx(), mapy(), - borderType(-1), borderValue() + CV_ImageWarpBaseTest(), borderType(-1) { funcs[0] = &CV_Remap_Test::remap_nearest; funcs[1] = &CV_Remap_Test::remap_generic; @@ -673,7 +672,7 @@ void CV_Remap_Test::generate_test_data() // generating the mapx, mapy matrices static const int mapx_types[] = { CV_16SC2, CV_32FC1, CV_32FC2 }; mapx.create(dst.size(), mapx_types[rng.uniform(0, sizeof(mapx_types) / sizeof(int))]); - mapy = Mat(); + mapy.release(); const int n = std::min(std::min(src.cols, src.rows) / 10 + 1, 2); float _n = 0; //static_cast(-n); @@ -700,7 +699,7 @@ void CV_Remap_Test::generate_test_data() { MatIterator_ begin_y = mapy.begin(), end_y = mapy.end(); for ( ; begin_y != end_y; ++begin_y) - begin_y[0] = static_cast(rng.uniform(0, 1024)); + *begin_y = static_cast(rng.uniform(0, 1024)); } break; @@ -708,7 +707,7 @@ void CV_Remap_Test::generate_test_data() { MatIterator_ begin_y = mapy.begin(), end_y = mapy.end(); for ( ; begin_y != end_y; ++begin_y) - begin_y[0] = static_cast(rng.uniform(0, 1024)); + *begin_y = static_cast(rng.uniform(0, 1024)); } break; } @@ -725,8 +724,8 @@ void CV_Remap_Test::generate_test_data() MatIterator_ begin_y = mapy.begin(); for ( ; begin_x != end_x; ++begin_x, ++begin_y) { - begin_x[0] = rng.uniform(_n, fscols); - begin_y[0] = rng.uniform(_n, fsrows); + *begin_x = rng.uniform(_n, fscols); + *begin_y = rng.uniform(_n, fsrows); } } break; @@ -794,23 +793,6 @@ void CV_Remap_Test::prepare_test_data_for_reference_func() { CV_ImageWarpBaseTest::prepare_test_data_for_reference_func(); convert_maps(); -/* - const int ksize = 3; - Mat kernel = getStructuringElement(CV_MOP_ERODE, Size(ksize, ksize)); - Mat mask(src.size(), CV_8UC1, Scalar::all(255)), dst_mask; - cv::erode(src, erode_src, kernel); - cv::erode(mask, dst_mask, kernel, Point(-1, -1), 1, BORDER_CONSTANT, Scalar::all(0)); - bitwise_not(dst_mask, mask); - src.copyTo(erode_src, mask); - dst_mask.release(); - - mask = Scalar::all(0); - kernel = getStructuringElement(CV_MOP_DILATE, kernel.size()); - cv::dilate(src, dilate_src, kernel); - cv::dilate(mask, dst_mask, kernel, Point(-1, -1), 1, BORDER_CONSTANT, Scalar::all(255)); - src.copyTo(dilate_src, dst_mask); - dst_mask.release(); -*/ } void CV_Remap_Test::run_reference_func() diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 3a113d5cc..68d3ff9ca 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -7,6 +7,13 @@ if(IOS OR WINRT OR NOT PYTHON_DEFAULT_AVAILABLE OR NOT ANT_EXECUTABLE OR NOT (JN ocv_module_disable(java) endif() +if(EXISTS ${CMAKE_BINARY_DIR}/src) + execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/src") +endif() +if(EXISTS ${CMAKE_BINARY_DIR}/gen) + execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/gen") +endif() + set(the_description "The java bindings") ocv_add_module(java BINDINGS opencv_core opencv_imgproc) ocv_module_include_directories("${CMAKE_CURRENT_SOURCE_DIR}/generator/src/cpp") @@ -81,7 +88,7 @@ macro(copy_common_tests _src_location _dst_location _deps) foreach(f ${_files}) add_custom_command( OUTPUT "${_dst}/${f}" - COMMAND ${CMAKE_COMMAND} -E copy "${_src}/${f}" "${_dst}/${f}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_src}/${f}" "${_dst}/${f}" MAIN_DEPENDENCY "${_src}/${f}" COMMENT "Copying ${f}") list(APPEND ${_deps} "${_src}/${f}" "${_dst}/${f}") @@ -102,7 +109,7 @@ macro(copy_modules_tests _modules _dst_location _deps) foreach (f ${_files}) add_custom_command( OUTPUT "${_dst}/${_tree}/${f}" - COMMAND ${CMAKE_COMMAND} -E copy "${_src}/${f}" "${_dst}/${_tree}/${f}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_src}/${f}" "${_dst}/${_tree}/${f}" MAIN_DEPENDENCY "${_src}/${f}" COMMENT "Copying ${f}") list(APPEND ${_deps} "${_src}/${f}" "${_dst}/${_tree}/${f}") @@ -179,6 +186,16 @@ if(NOT ANDROID) else() file(GLOB_RECURSE handwrittren_lib_project_files_rel RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/android_lib/" "${CMAKE_CURRENT_SOURCE_DIR}/android_lib/*") list(REMOVE_ITEM handwrittren_lib_project_files_rel "${ANDROID_MANIFEST_FILE}") + + # calc default SDK Target + android_get_compatible_target(android_sdk_target ${ANDROID_NATIVE_API_LEVEL} ${ANDROID_SDK_TARGET} 11) + string(REGEX REPLACE "android-" "" android_sdk_target_num ${android_sdk_target}) + # filter out + if( (ANDROID_SDK_TARGET AND ANDROID_SDK_TARGET LESS 21) OR (android_sdk_target_num LESS 21) ) + message(STATUS "[OpenCV for Android SDK]: A new OpenGL Camera Bridge (CameraGLSurfaceView, CameraGLRendererBase, CameraRenderer, Camera2Renderer) is disabled, because ANDROID_SDK_TARGET (${android_sdk_target_num}) < 21") + ocv_list_filterout(handwritten_java_sources "android\\\\+CameraGL") + ocv_list_filterout(handwritten_java_sources "android\\\\+Camera.?Renderer") + endif() endif() # IMPORTANT: add dependencies to cmake (we should rerun cmake if any of these files is modified) @@ -208,7 +225,7 @@ foreach(java_file ${step3_input_files}) string(REPLACE "+" "/" java_file_name "${java_file_name}") set(output_name "${OpenCV_BINARY_DIR}/src/org/opencv/${java_file_name}") add_custom_command(OUTPUT "${output_name}" - COMMAND ${CMAKE_COMMAND} -E copy "${java_file}" "${output_name}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${java_file}" "${output_name}" MAIN_DEPENDENCY "${java_file}" DEPENDS ${step1_depends} ${generated_java_sources} ${handwritten_java_sources} COMMENT "Generating src/org/opencv/${java_file_name}" @@ -239,7 +256,7 @@ if(ANDROID) foreach(jni_file ${handwritten_cpp_sources} ${handwritten_h_sources} ${generated_cpp_sources}) get_filename_component(jni_file_name "${jni_file}" NAME) add_custom_command(OUTPUT "${OpenCV_BINARY_DIR}/jni/${jni_file_name}" - COMMAND ${CMAKE_COMMAND} -E copy "${jni_file}" "${OpenCV_BINARY_DIR}/jni/${jni_file_name}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${jni_file}" "${OpenCV_BINARY_DIR}/jni/${jni_file_name}" DEPENDS "${jni_file}" ${java_hdr_deps} COMMENT "Generating jni/${jni_file_name}" ) @@ -257,9 +274,9 @@ if(ANDROID AND ANDROID_EXECUTABLE) add_custom_command(OUTPUT ${lib_target_files} "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" COMMAND ${CMAKE_COMMAND} -E remove ${lib_target_files} - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" COMMAND ${ANDROID_EXECUTABLE} --silent create lib-project --path \"${OpenCV_BINARY_DIR}\" --target \"${lib_target_sdk_target}\" --name OpenCV --package org.opencv 2>\"${CMAKE_CURRENT_BINARY_DIR}/create_lib_project.log\" - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" "${OpenCV_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" MAIN_DEPENDENCY "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_MANIFEST_FILE}" DEPENDS ${android_step3_input_files} ${android_copied_files} COMMENT "Generating OpenCV Android library project. SDK target: ${lib_target_sdk_target}" diff --git a/modules/java/android_lib/AndroidManifest.xml b/modules/java/android_lib/AndroidManifest.xml index 1943221e9..228c6cfbb 100644 --- a/modules/java/android_lib/AndroidManifest.xml +++ b/modules/java/android_lib/AndroidManifest.xml @@ -4,5 +4,5 @@ android:versionCode="@OPENCV_VERSION_MAJOR@@OPENCV_VERSION_MINOR@@OPENCV_VERSION_PATCH@0" android:versionName="@OPENCV_VERSION@"> - + diff --git a/modules/java/android_test/CMakeLists.txt b/modules/java/android_test/CMakeLists.txt index e19573228..f6261a7c0 100644 --- a/modules/java/android_test/CMakeLists.txt +++ b/modules/java/android_test/CMakeLists.txt @@ -21,7 +21,7 @@ file(GLOB_RECURSE test_files RELATIVE "${test_dir}" "${test_dir}/res/*" "${test_ foreach(f ${test_files} ${ANDROID_MANIFEST_FILE} ".classpath" ".project") add_custom_command( OUTPUT "${opencv_test_java_bin_dir}/${f}" - COMMAND ${CMAKE_COMMAND} -E copy "${test_dir}/${f}" "${opencv_test_java_bin_dir}/${f}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${test_dir}/${f}" "${opencv_test_java_bin_dir}/${f}" MAIN_DEPENDENCY "${test_dir}/${f}" COMMENT "Copying ${f}") list(APPEND opencv_test_java_file_deps "${test_dir}/${f}" "${opencv_test_java_bin_dir}/${f}") @@ -49,7 +49,7 @@ get_filename_component(java_name "${java_location}" NAME) # build java part add_custom_command( OUTPUT "${opencv_test_java_bin_dir}/bin/OpenCVTest-debug.apk" - COMMAND ${CMAKE_COMMAND} -E copy "${java_location}" "${opencv_test_java_bin_dir}/libs/${ANDROID_NDK_ABI_NAME}/${java_name}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${java_location}" "${opencv_test_java_bin_dir}/libs/${ANDROID_NDK_ABI_NAME}/${java_name}" COMMAND ${ANT_EXECUTABLE} -q -noinput -k debug COMMAND ${CMAKE_COMMAND} -E touch "${opencv_test_java_bin_dir}/bin/OpenCVTest-debug.apk" # needed because ant does not update the timestamp of updated apk WORKING_DIRECTORY "${opencv_test_java_bin_dir}" @@ -62,7 +62,7 @@ add_dependencies(${PROJECT_NAME} opencv_java ${__android_project_chain}) set(__android_project_chain ${PROJECT_NAME} CACHE INTERNAL "auxiliary variable used for Android progects chaining" FORCE) # put the final .apk to the OpenCV's bin folder -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${opencv_test_java_bin_dir}/bin/OpenCVTest-debug.apk" "${OpenCV_BINARY_DIR}/bin/${PROJECT_NAME}.apk") +add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${opencv_test_java_bin_dir}/bin/OpenCVTest-debug.apk" "${OpenCV_BINARY_DIR}/bin/${PROJECT_NAME}.apk") add_dependencies(opencv_tests ${PROJECT_NAME}) diff --git a/modules/java/generator/gen_java.py b/modules/java/generator/gen_java.py index 649059d28..a51bef170 100755 --- a/modules/java/generator/gen_java.py +++ b/modules/java/generator/gen_java.py @@ -13,8 +13,6 @@ else: class_ignore_list = ( #core "FileNode", "FileStorage", "KDTree", "KeyPoint", "DMatch", - #videoio - "VideoWriter", ) const_ignore_list = ( @@ -186,6 +184,7 @@ type_dict = { "env" : { "j_type" : "", "jn_type" : "", "jni_type" : "JNIEnv*"}, "cls" : { "j_type" : "", "jn_type" : "", "jni_type" : "jclass"}, "bool" : { "j_type" : "boolean", "jn_type" : "boolean", "jni_type" : "jboolean", "suffix" : "Z" }, + "char" : { "j_type" : "char", "jn_type" : "char", "jni_type" : "jchar", "suffix" : "C" }, "int" : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" }, "long" : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" }, "float" : { "j_type" : "float", "jn_type" : "float", "jni_type" : "jfloat", "suffix" : "F" }, @@ -1162,7 +1161,7 @@ class JavaWrapperGenerator(object): ("jdoubleArray _da_retval_ = env->NewDoubleArray(%(cnt)i); " + "jdouble _tmp_retval_[%(cnt)i] = {%(args)s}; " + "env->SetDoubleArrayRegion(_da_retval_, 0, %(cnt)i, _tmp_retval_);") % - { "cnt" : len(fields), "args" : ", ".join(["_retval_" + f[1] for f in fields]) } ) + { "cnt" : len(fields), "args" : ", ".join(["(jdouble)_retval_" + f[1] for f in fields]) } ) if fi.classname and fi.ctype and not fi.static: # non-static class method except c-tor # adding 'self' jn_args.append ( ArgInfo([ "__int64", "nativeObj", "", [], "" ]) ) @@ -1209,7 +1208,7 @@ class JavaWrapperGenerator(object): j_prologue.append( "double[] %s_out = new double[%i];" % (a.name, len(fields)) ) c_epilogue.append( \ "jdouble tmp_%(n)s[%(cnt)i] = {%(args)s}; env->SetDoubleArrayRegion(%(n)s_out, 0, %(cnt)i, tmp_%(n)s);" % - { "n" : a.name, "cnt" : len(fields), "args" : ", ".join([a.name + f[1] for f in fields]) } ) + { "n" : a.name, "cnt" : len(fields), "args" : ", ".join(["(jdouble)" + a.name + f[1] for f in fields]) } ) if a.ctype in ('bool', 'int', 'long', 'float', 'double'): j_epilogue.append('if(%(n)s!=null) %(n)s[0] = (%(t)s)%(n)s_out[0];' % {'n':a.name,'t':a.ctype}) else: diff --git a/modules/java/generator/src/cpp/Mat.cpp b/modules/java/generator/src/cpp/Mat.cpp index 185cb2de9..d8483cd02 100644 --- a/modules/java/generator/src/cpp/Mat.cpp +++ b/modules/java/generator/src/cpp/Mat.cpp @@ -1070,7 +1070,7 @@ JNIEXPORT void JNICALL Java_org_opencv_core_Mat_locateROI_10 Size wholeSize; Point ofs; me->locateROI( wholeSize, ofs ); - jdouble tmp_wholeSize[2] = {wholeSize.width, wholeSize.height}; env->SetDoubleArrayRegion(wholeSize_out, 0, 2, tmp_wholeSize); jdouble tmp_ofs[2] = {ofs.x, ofs.y}; env->SetDoubleArrayRegion(ofs_out, 0, 2, tmp_ofs); + jdouble tmp_wholeSize[2] = {(jdouble)wholeSize.width, (jdouble)wholeSize.height}; env->SetDoubleArrayRegion(wholeSize_out, 0, 2, tmp_wholeSize); jdouble tmp_ofs[2] = {(jdouble)ofs.x, (jdouble)ofs.y}; env->SetDoubleArrayRegion(ofs_out, 0, 2, tmp_ofs); } catch(const std::exception &e) { throwJavaException(env, &e, method_name); } catch (...) { @@ -1489,7 +1489,7 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_n_1size Mat* me = (Mat*) self; //TODO: check for NULL Size _retval_ = me->size( ); jdoubleArray _da_retval_ = env->NewDoubleArray(2); - jdouble _tmp_retval_[2] = {_retval_.width, _retval_.height}; + jdouble _tmp_retval_[2] = {(jdouble)_retval_.width, (jdouble)_retval_.height}; env->SetDoubleArrayRegion(_da_retval_, 0, 2, _tmp_retval_); return _da_retval_; } catch(const std::exception &e) { diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Camera2Renderer.java b/modules/java/generator/src/java/android+Camera2Renderer.java similarity index 70% rename from samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Camera2Renderer.java rename to modules/java/generator/src/java/android+Camera2Renderer.java index 217268a78..408214057 100644 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Camera2Renderer.java +++ b/modules/java/generator/src/java/android+Camera2Renderer.java @@ -1,10 +1,9 @@ -package org.opencv.samples.tutorial4; +package org.opencv.android; import java.util.Arrays; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; - -import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.content.Context; import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; @@ -20,38 +19,45 @@ import android.util.Log; import android.util.Size; import android.view.Surface; -@SuppressLint("NewApi") public class Camera2Renderer extends MyGLRendererBase { +@TargetApi(21) +public class Camera2Renderer extends CameraGLRendererBase { protected final String LOGTAG = "Camera2Renderer"; private CameraDevice mCameraDevice; private CameraCaptureSession mCaptureSession; private CaptureRequest.Builder mPreviewRequestBuilder; private String mCameraID; - private Size mPreviewSize = new Size(1280, 720); + private Size mPreviewSize = new Size(-1, -1); private HandlerThread mBackgroundThread; private Handler mBackgroundHandler; private Semaphore mCameraOpenCloseLock = new Semaphore(1); - Camera2Renderer(MyGLSurfaceView view) { + Camera2Renderer(CameraGLSurfaceView view) { super(view); } - public void onResume() { - stopBackgroundThread(); - super.onResume(); + @Override + protected void doStart() { + Log.d(LOGTAG, "doStart"); startBackgroundThread(); + super.doStart(); } - public void onPause() { - super.onPause(); + + @Override + protected void doStop() { + Log.d(LOGTAG, "doStop"); + super.doStop(); stopBackgroundThread(); } - boolean cacPreviewSize(final int width, final int height) { + boolean cacPreviewSize(final int width, final int height) { Log.i(LOGTAG, "cacPreviewSize: "+width+"x"+height); - if(mCameraID == null) + if(mCameraID == null) { + Log.e(LOGTAG, "Camera isn't initialized!"); return false; + } CameraManager manager = (CameraManager) mView.getContext() .getSystemService(Context.CAMERA_SERVICE); try { @@ -72,7 +78,8 @@ import android.view.Surface; } } Log.i(LOGTAG, "best size: "+bestWidth+"x"+bestHeight); - if( mPreviewSize.getWidth() == bestWidth && + if( bestWidth == 0 || bestHeight == 0 || + mPreviewSize.getWidth() == bestWidth && mPreviewSize.getHeight() == bestHeight ) return false; else { @@ -89,26 +96,38 @@ import android.view.Surface; return false; } - protected void openCamera() { + @Override + protected void openCamera(int id) { Log.i(LOGTAG, "openCamera"); - //closeCamera(); - CameraManager manager = (CameraManager) mView.getContext() - .getSystemService(Context.CAMERA_SERVICE); + CameraManager manager = (CameraManager) mView.getContext().getSystemService(Context.CAMERA_SERVICE); try { - for (String cameraID : manager.getCameraIdList()) { - CameraCharacteristics characteristics = manager - .getCameraCharacteristics(cameraID); - if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) - continue; - - mCameraID = cameraID; - break; + String camList[] = manager.getCameraIdList(); + if(camList.length == 0) { + Log.e(LOGTAG, "Error: camera isn't detected."); + return; } - if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { - throw new RuntimeException( - "Time out waiting to lock camera opening."); + if(id == CameraBridgeViewBase.CAMERA_ID_ANY) { + mCameraID = camList[0]; + } else { + for (String cameraID : camList) { + CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraID); + if( id == CameraBridgeViewBase.CAMERA_ID_BACK && + characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK || + id == CameraBridgeViewBase.CAMERA_ID_FRONT && + characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) { + mCameraID = cameraID; + break; + } + } + } + if(mCameraID != null) { + if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { + throw new RuntimeException( + "Time out waiting to lock camera opening."); + } + Log.i(LOGTAG, "Opening camera: " + mCameraID); + manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler); } - manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler); } catch (CameraAccessException e) { Log.e(LOGTAG, "OpenCamera - Camera Access Exception"); } catch (IllegalArgumentException e) { @@ -120,6 +139,7 @@ import android.view.Surface; } } + @Override protected void closeCamera() { Log.i(LOGTAG, "closeCamera"); try { @@ -133,8 +153,7 @@ import android.view.Surface; mCameraDevice = null; } } catch (InterruptedException e) { - throw new RuntimeException( - "Interrupted while trying to lock camera closing.", e); + throw new RuntimeException("Interrupted while trying to lock camera closing.", e); } finally { mCameraOpenCloseLock.release(); } @@ -166,7 +185,10 @@ import android.view.Surface; }; private void createCameraPreviewSession() { - Log.i(LOGTAG, "createCameraPreviewSession"); + int w=mPreviewSize.getWidth(), h=mPreviewSize.getHeight(); + Log.i(LOGTAG, "createCameraPreviewSession("+w+"x"+h+")"); + if(w<0 || h<0) + return; try { mCameraOpenCloseLock.acquire(); if (null == mCameraDevice) { @@ -179,15 +201,14 @@ import android.view.Surface; Log.e(LOGTAG, "createCameraPreviewSession: mCaptureSession is already started"); return; } - if(null == mSTex) { + if(null == mSTexture) { mCameraOpenCloseLock.release(); Log.e(LOGTAG, "createCameraPreviewSession: preview SurfaceTexture is null"); return; } - Log.d(LOGTAG, "starting preview "+mPreviewSize.getWidth()+"x"+mPreviewSize.getHeight()); - mSTex.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); + mSTexture.setDefaultBufferSize(w, h); - Surface surface = new Surface(mSTex); + Surface surface = new Surface(mSTexture); mPreviewRequestBuilder = mCameraDevice .createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); @@ -196,20 +217,13 @@ import android.view.Surface; mCameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() { @Override - public void onConfigured( - CameraCaptureSession cameraCaptureSession) { + public void onConfigured( CameraCaptureSession cameraCaptureSession) { mCaptureSession = cameraCaptureSession; try { - mPreviewRequestBuilder - .set(CaptureRequest.CONTROL_AF_MODE, - CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); - mPreviewRequestBuilder - .set(CaptureRequest.CONTROL_AE_MODE, - CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); + mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); + mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); - mCaptureSession.setRepeatingRequest( - mPreviewRequestBuilder.build(), null, - mBackgroundHandler); + mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, mBackgroundHandler); Log.i(LOGTAG, "CameraPreviewSession has been started"); } catch (CameraAccessException e) { Log.e(LOGTAG, "createCaptureSession failed"); @@ -237,6 +251,7 @@ import android.view.Surface; private void startBackgroundThread() { Log.i(LOGTAG, "startBackgroundThread"); + stopBackgroundThread(); mBackgroundThread = new HandlerThread("CameraBackground"); mBackgroundThread.start(); mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); @@ -259,9 +274,16 @@ import android.view.Surface; @Override protected void setCameraPreviewSize(int width, int height) { Log.i(LOGTAG, "setCameraPreviewSize("+width+"x"+height+")"); + if(mMaxCameraWidth > 0 && mMaxCameraWidth < width) width = mMaxCameraWidth; + if(mMaxCameraHeight > 0 && mMaxCameraHeight < height) height = mMaxCameraHeight; try { mCameraOpenCloseLock.acquire(); - if( !cacPreviewSize(width, height) ) { + + boolean needReconfig = cacPreviewSize(width, height); + mCameraWidth = mPreviewSize.getWidth(); + mCameraHeight = mPreviewSize.getHeight(); + + if( !needReconfig ) { mCameraOpenCloseLock.release(); return; } @@ -274,8 +296,7 @@ import android.view.Surface; createCameraPreviewSession(); } catch (InterruptedException e) { mCameraOpenCloseLock.release(); - throw new RuntimeException( - "Interrupted while setCameraPreviewSize.", e); + throw new RuntimeException("Interrupted while setCameraPreviewSize.", e); } } } diff --git a/modules/java/generator/src/java/android+CameraBridgeViewBase.java b/modules/java/generator/src/java/android+CameraBridgeViewBase.java index da939017c..14e041146 100644 --- a/modules/java/generator/src/java/android+CameraBridgeViewBase.java +++ b/modules/java/generator/src/java/android+CameraBridgeViewBase.java @@ -3,10 +3,8 @@ package org.opencv.android; import java.util.List; import org.opencv.R; -import org.opencv.android.Utils; import org.opencv.core.Mat; import org.opencv.core.Size; -import org.opencv.videoio.Videoio; import android.app.Activity; import android.app.AlertDialog; @@ -451,7 +449,7 @@ public abstract class CameraBridgeViewBase extends SurfaceView implements Surfac */ protected abstract void disconnectCamera(); - // NOTE: On Android 4.1.x the function must be called before SurfaceTextre constructor! + // NOTE: On Android 4.1.x the function must be called before SurfaceTexture constructor! protected void AllocateCache() { mCacheBitmap = Bitmap.createBitmap(mFrameWidth, mFrameHeight, Bitmap.Config.ARGB_8888); diff --git a/modules/java/generator/src/java/android+CameraGLRendererBase.java b/modules/java/generator/src/java/android+CameraGLRendererBase.java new file mode 100644 index 000000000..60c37c304 --- /dev/null +++ b/modules/java/generator/src/java/android+CameraGLRendererBase.java @@ -0,0 +1,440 @@ +package org.opencv.android; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import org.opencv.android.CameraGLSurfaceView.CameraTextureListener; + +import android.annotation.TargetApi; +import android.graphics.SurfaceTexture; +import android.opengl.GLES11Ext; +import android.opengl.GLES20; +import android.opengl.GLSurfaceView; +import android.util.Log; +import android.view.View; + +@TargetApi(15) +public abstract class CameraGLRendererBase implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { + + protected final String LOGTAG = "CameraGLRendererBase"; + + // shaders + private final String vss = "" + + "attribute vec2 vPosition;\n" + + "attribute vec2 vTexCoord;\n" + "varying vec2 texCoord;\n" + + "void main() {\n" + " texCoord = vTexCoord;\n" + + " gl_Position = vec4 ( vPosition.x, vPosition.y, 0.0, 1.0 );\n" + + "}"; + + private final String fssOES = "" + + "#extension GL_OES_EGL_image_external : require\n" + + "precision mediump float;\n" + + "uniform samplerExternalOES sTexture;\n" + + "varying vec2 texCoord;\n" + + "void main() {\n" + + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; + + private final String fss2D = "" + + "precision mediump float;\n" + + "uniform sampler2D sTexture;\n" + + "varying vec2 texCoord;\n" + + "void main() {\n" + + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; + + // coord-s + private final float vertices[] = { + -1, -1, + -1, 1, + 1, -1, + 1, 1 }; + private final float texCoordOES[] = { + 0, 1, + 0, 0, + 1, 1, + 1, 0 }; + private final float texCoord2D[] = { + 0, 0, + 0, 1, + 1, 0, + 1, 1 }; + + private int[] texCamera = {0}, texFBO = {0}, texDraw = {0}; + private int[] FBO = {0}; + private int progOES = -1, prog2D = -1; + private int vPosOES, vTCOES, vPos2D, vTC2D; + + private FloatBuffer vert, texOES, tex2D; + + protected int mCameraWidth = -1, mCameraHeight = -1; + protected int mFBOWidth = -1, mFBOHeight = -1; + protected int mMaxCameraWidth = -1, mMaxCameraHeight = -1; + protected int mCameraIndex = CameraBridgeViewBase.CAMERA_ID_ANY; + + protected SurfaceTexture mSTexture; + + protected boolean mHaveSurface = false; + protected boolean mHaveFBO = false; + protected boolean mUpdateST = false; + protected boolean mEnabled = true; + protected boolean mIsStarted = false; + + protected CameraGLSurfaceView mView; + + protected abstract void openCamera(int id); + protected abstract void closeCamera(); + protected abstract void setCameraPreviewSize(int width, int height); // updates mCameraWidth & mCameraHeight + + public CameraGLRendererBase(CameraGLSurfaceView view) { + mView = view; + int bytes = vertices.length * Float.SIZE / Byte.SIZE; + vert = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + texOES = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + tex2D = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + vert.put(vertices).position(0); + texOES.put(texCoordOES).position(0); + tex2D.put(texCoord2D).position(0); + } + + @Override + public synchronized void onFrameAvailable(SurfaceTexture surfaceTexture) { + //Log.i(LOGTAG, "onFrameAvailable"); + mUpdateST = true; + mView.requestRender(); + } + + @Override + public void onDrawFrame(GL10 gl) { + //Log.i(LOGTAG, "onDrawFrame start"); + + if (!mHaveFBO) + return; + + synchronized(this) { + if (mUpdateST) { + mSTexture.updateTexImage(); + mUpdateST = false; + } + + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + + CameraTextureListener texListener = mView.getCameraTextureListener(); + if(texListener != null) { + //Log.d(LOGTAG, "haveUserCallback"); + // texCamera(OES) -> texFBO + drawTex(texCamera[0], true, FBO[0]); + + // call user code (texFBO -> texDraw) + boolean modified = texListener.onCameraTexture(texFBO[0], texDraw[0], mCameraWidth, mCameraHeight); + + if(modified) { + // texDraw -> screen + drawTex(texDraw[0], false, 0); + } else { + // texFBO -> screen + drawTex(texFBO[0], false, 0); + } + } else { + Log.d(LOGTAG, "texCamera(OES) -> screen"); + // texCamera(OES) -> screen + drawTex(texCamera[0], true, 0); + } + //Log.i(LOGTAG, "onDrawFrame end"); + } + } + + @Override + public void onSurfaceChanged(GL10 gl, int surfaceWidth, int surfaceHeight) { + Log.i(LOGTAG, "onSurfaceChanged("+surfaceWidth+"x"+surfaceHeight+")"); + mHaveSurface = true; + updateState(); + setPreviewSize(surfaceWidth, surfaceHeight); + } + + @Override + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + Log.i(LOGTAG, "onSurfaceCreated"); + initShaders(); + } + + private void initShaders() { + String strGLVersion = GLES20.glGetString(GLES20.GL_VERSION); + if (strGLVersion != null) + Log.i(LOGTAG, "OpenGL ES version: " + strGLVersion); + + GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + + progOES = loadShader(vss, fssOES); + vPosOES = GLES20.glGetAttribLocation(progOES, "vPosition"); + vTCOES = GLES20.glGetAttribLocation(progOES, "vTexCoord"); + GLES20.glEnableVertexAttribArray(vPosOES); + GLES20.glEnableVertexAttribArray(vTCOES); + + prog2D = loadShader(vss, fss2D); + vPos2D = GLES20.glGetAttribLocation(prog2D, "vPosition"); + vTC2D = GLES20.glGetAttribLocation(prog2D, "vTexCoord"); + GLES20.glEnableVertexAttribArray(vPos2D); + GLES20.glEnableVertexAttribArray(vTC2D); + } + + private void initSurfaceTexture() { + Log.d(LOGTAG, "initSurfaceTexture"); + deleteSurfaceTexture(); + initTexOES(texCamera); + mSTexture = new SurfaceTexture(texCamera[0]); + mSTexture.setOnFrameAvailableListener(this); + } + + private void deleteSurfaceTexture() { + Log.d(LOGTAG, "deleteSurfaceTexture"); + if(mSTexture != null) { + mSTexture.release(); + mSTexture = null; + deleteTex(texCamera); + } + } + + private void initTexOES(int[] tex) { + if(tex.length == 1) { + GLES20.glGenTextures(1, tex, 0); + GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + } + } + + private static void deleteTex(int[] tex) { + if(tex.length == 1) { + GLES20.glDeleteTextures(1, tex, 0); + } + } + + private static int loadShader(String vss, String fss) { + Log.d("CameraGLRendererBase", "loadShader"); + int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); + GLES20.glShaderSource(vshader, vss); + GLES20.glCompileShader(vshader); + int[] status = new int[1]; + GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, status, 0); + if (status[0] == 0) { + Log.e("CameraGLRendererBase", "Could not compile vertex shader: "+GLES20.glGetShaderInfoLog(vshader)); + GLES20.glDeleteShader(vshader); + vshader = 0; + return 0; + } + + int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); + GLES20.glShaderSource(fshader, fss); + GLES20.glCompileShader(fshader); + GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, status, 0); + if (status[0] == 0) { + Log.e("CameraGLRendererBase", "Could not compile fragment shader:"+GLES20.glGetShaderInfoLog(fshader)); + GLES20.glDeleteShader(vshader); + GLES20.glDeleteShader(fshader); + fshader = 0; + return 0; + } + + int program = GLES20.glCreateProgram(); + GLES20.glAttachShader(program, vshader); + GLES20.glAttachShader(program, fshader); + GLES20.glLinkProgram(program); + GLES20.glDeleteShader(vshader); + GLES20.glDeleteShader(fshader); + GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, status, 0); + if (status[0] == 0) { + Log.e("CameraGLRendererBase", "Could not link shader program: "+GLES20.glGetProgramInfoLog(program)); + program = 0; + return 0; + } + GLES20.glValidateProgram(program); + GLES20.glGetProgramiv(program, GLES20.GL_VALIDATE_STATUS, status, 0); + if (status[0] == 0) + { + Log.e("CameraGLRendererBase", "Shader program validation error: "+GLES20.glGetProgramInfoLog(program)); + GLES20.glDeleteProgram(program); + program = 0; + return 0; + } + + Log.d("CameraGLRendererBase", "Shader program is built OK"); + + return program; + } + + private void deleteFBO() + { + Log.d(LOGTAG, "deleteFBO("+mFBOWidth+"x"+mFBOHeight+")"); + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); + GLES20.glDeleteFramebuffers(1, FBO, 0); + + deleteTex(texFBO); + deleteTex(texDraw); + mFBOWidth = mFBOHeight = 0; + } + + private void initFBO(int width, int height) + { + Log.d(LOGTAG, "initFBO("+width+"x"+height+")"); + + deleteFBO(); + + GLES20.glGenTextures(1, texDraw, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texDraw[0]); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + + GLES20.glGenTextures(1, texFBO, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texFBO[0]); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + + //int hFBO; + GLES20.glGenFramebuffers(1, FBO, 0); + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, FBO[0]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texFBO[0], 0); + Log.d(LOGTAG, "initFBO error status: " + GLES20.glGetError()); + + int FBOstatus = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); + if (FBOstatus != GLES20.GL_FRAMEBUFFER_COMPLETE) + Log.e(LOGTAG, "initFBO failed, status: " + FBOstatus); + + mFBOWidth = width; + mFBOHeight = height; + } + + // draw texture to FBO or to screen if fbo == 0 + private void drawTex(int tex, boolean isOES, int fbo) + { + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo); + + if(fbo == 0) + GLES20.glViewport(0, 0, mView.getWidth(), mView.getHeight()); + else + GLES20.glViewport(0, 0, mFBOWidth, mFBOHeight); + + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + + if(isOES) { + GLES20.glUseProgram(progOES); + GLES20.glVertexAttribPointer(vPosOES, 2, GLES20.GL_FLOAT, false, 4*2, vert); + GLES20.glVertexAttribPointer(vTCOES, 2, GLES20.GL_FLOAT, false, 4*2, texOES); + } else { + GLES20.glUseProgram(prog2D); + GLES20.glVertexAttribPointer(vPos2D, 2, GLES20.GL_FLOAT, false, 4*2, vert); + GLES20.glVertexAttribPointer(vTC2D, 2, GLES20.GL_FLOAT, false, 4*2, tex2D); + } + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + + if(isOES) { + GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex); + GLES20.glUniform1i(GLES20.glGetUniformLocation(progOES, "sTexture"), 0); + } else { + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex); + GLES20.glUniform1i(GLES20.glGetUniformLocation(prog2D, "sTexture"), 0); + } + + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + GLES20.glFlush(); + } + + public synchronized void enableView() { + Log.d(LOGTAG, "enableView"); + mEnabled = true; + updateState(); + } + + public synchronized void disableView() { + Log.d(LOGTAG, "disableView"); + mEnabled = false; + updateState(); + } + + protected void updateState() { + Log.d(LOGTAG, "updateState"); + Log.d(LOGTAG, "mEnabled="+mEnabled+", mHaveSurface="+mHaveSurface); + boolean willStart = mEnabled && mHaveSurface && mView.getVisibility() == View.VISIBLE; + if (willStart != mIsStarted) { + if(willStart) doStart(); + else doStop(); + } else { + Log.d(LOGTAG, "keeping State unchanged"); + } + Log.d(LOGTAG, "updateState end"); + } + + protected synchronized void doStart() { + Log.d(LOGTAG, "doStart"); + initSurfaceTexture(); + openCamera(mCameraIndex); + mIsStarted = true; + if(mCameraWidth>0 && mCameraHeight>0) + setPreviewSize(mCameraWidth, mCameraHeight); // start preview and call listener.onCameraViewStarted() + } + + + protected void doStop() { + Log.d(LOGTAG, "doStop"); + synchronized(this) { + mUpdateST = false; + mIsStarted = false; + mHaveFBO = false; + closeCamera(); + deleteSurfaceTexture(); + } + CameraTextureListener listener = mView.getCameraTextureListener(); + if(listener != null) listener.onCameraViewStopped(); + + } + + protected void setPreviewSize(int width, int height) { + synchronized(this) { + mHaveFBO = false; + mCameraWidth = width; + mCameraHeight = height; + setCameraPreviewSize(width, height); // can change mCameraWidth & mCameraHeight + initFBO(mCameraWidth, mCameraHeight); + mHaveFBO = true; + } + + CameraTextureListener listener = mView.getCameraTextureListener(); + if(listener != null) listener.onCameraViewStarted(mCameraWidth, mCameraHeight); + } + + public void setCameraIndex(int cameraIndex) { + disableView(); + mCameraIndex = cameraIndex; + enableView(); + } + + public void setMaxCameraPreviewSize(int maxWidth, int maxHeight) { + disableView(); + mMaxCameraWidth = maxWidth; + mMaxCameraHeight = maxHeight; + enableView(); + } + + public void onResume() { + Log.i(LOGTAG, "onResume"); + } + + public void onPause() { + Log.i(LOGTAG, "onPause"); + mHaveSurface = false; + updateState(); + mCameraWidth = mCameraHeight = -1; + } + +} diff --git a/modules/java/generator/src/java/android+CameraGLSurfaceView.java b/modules/java/generator/src/java/android+CameraGLSurfaceView.java new file mode 100644 index 000000000..05f950b47 --- /dev/null +++ b/modules/java/generator/src/java/android+CameraGLSurfaceView.java @@ -0,0 +1,119 @@ +package org.opencv.android; + +import org.opencv.R; + +import android.content.Context; +import android.content.res.TypedArray; +import android.opengl.GLSurfaceView; +import android.util.AttributeSet; +import android.util.Log; +import android.view.SurfaceHolder; + +public class CameraGLSurfaceView extends GLSurfaceView { + + private static final String LOGTAG = "CameraGLSurfaceView"; + + public interface CameraTextureListener { + /** + * This method is invoked when camera preview has started. After this method is invoked + * the frames will start to be delivered to client via the onCameraFrame() callback. + * @param width - the width of the frames that will be delivered + * @param height - the height of the frames that will be delivered + */ + public void onCameraViewStarted(int width, int height); + + /** + * This method is invoked when camera preview has been stopped for some reason. + * No frames will be delivered via onCameraFrame() callback after this method is called. + */ + public void onCameraViewStopped(); + + /** + * This method is invoked when a new preview frame from Camera is ready. + * @param texIn - the OpenGL texture ID that contains frame in RGBA format + * @param texOut - the OpenGL texture ID that can be used to store modified frame image t display + * @param width - the width of the frame + * @param height - the height of the frame + * @return `true` if `texOut` should be displayed, `false` - to show `texIn` + */ + public boolean onCameraTexture(int texIn, int texOut, int width, int height); + }; + + private CameraTextureListener mTexListener; + private CameraGLRendererBase mRenderer; + + public CameraGLSurfaceView(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs, R.styleable.CameraBridgeViewBase); + int cameraIndex = styledAttrs.getInt(R.styleable.CameraBridgeViewBase_camera_id, -1); + styledAttrs.recycle(); + + if(android.os.Build.VERSION.SDK_INT >= 21) + mRenderer = new Camera2Renderer(this); + else + mRenderer = new CameraRenderer(this); + + setCameraIndex(cameraIndex); + + setEGLContextClientVersion(2); + setRenderer(mRenderer); + setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); + } + + public void setCameraTextureListener(CameraTextureListener texListener) + { + mTexListener = texListener; + } + + public CameraTextureListener getCameraTextureListener() + { + return mTexListener; + } + + public void setCameraIndex(int cameraIndex) { + mRenderer.setCameraIndex(cameraIndex); + } + + public void setMaxCameraPreviewSize(int maxWidth, int maxHeight) { + mRenderer.setMaxCameraPreviewSize(maxWidth, maxHeight); + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + super.surfaceCreated(holder); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + mRenderer.mHaveSurface = false; + super.surfaceDestroyed(holder); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + } + + @Override + public void onResume() { + Log.i(LOGTAG, "onResume"); + super.onResume(); + mRenderer.onResume(); + } + + @Override + public void onPause() { + Log.i(LOGTAG, "onPause"); + mRenderer.onPause(); + super.onPause(); + } + + public void enableView() { + mRenderer.enableView(); + } + + public void disableView() { + mRenderer.disableView(); + } +} diff --git a/modules/java/generator/src/java/android+CameraRenderer.java b/modules/java/generator/src/java/android+CameraRenderer.java new file mode 100644 index 000000000..2d668ffa6 --- /dev/null +++ b/modules/java/generator/src/java/android+CameraRenderer.java @@ -0,0 +1,166 @@ +package org.opencv.android; + +import java.io.IOException; +import java.util.List; + +import android.annotation.TargetApi; +import android.hardware.Camera; +import android.hardware.Camera.Size; +import android.os.Build; +import android.util.Log; + +@TargetApi(15) +@SuppressWarnings("deprecation") +public class CameraRenderer extends CameraGLRendererBase { + + public static final String LOGTAG = "CameraRenderer"; + + private Camera mCamera; + private boolean mPreviewStarted = false; + + CameraRenderer(CameraGLSurfaceView view) { + super(view); + } + + @Override + protected synchronized void closeCamera() { + Log.i(LOGTAG, "closeCamera"); + if(mCamera != null) { + mCamera.stopPreview(); + mPreviewStarted = false; + mCamera.release(); + mCamera = null; + } + } + + @Override + protected synchronized void openCamera(int id) { + Log.i(LOGTAG, "openCamera"); + closeCamera(); + if (id == CameraBridgeViewBase.CAMERA_ID_ANY) { + Log.d(LOGTAG, "Trying to open camera with old open()"); + try { + mCamera = Camera.open(); + } + catch (Exception e){ + Log.e(LOGTAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage()); + } + + if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + boolean connected = false; + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Log.d(LOGTAG, "Trying to open camera with new open(" + camIdx + ")"); + try { + mCamera = Camera.open(camIdx); + connected = true; + } catch (RuntimeException e) { + Log.e(LOGTAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage()); + } + if (connected) break; + } + } + } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + int localCameraIndex = mCameraIndex; + if (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_BACK) { + Log.i(LOGTAG, "Trying to open BACK camera"); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Camera.getCameraInfo( camIdx, cameraInfo ); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { + localCameraIndex = camIdx; + break; + } + } + } else if (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT) { + Log.i(LOGTAG, "Trying to open FRONT camera"); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Camera.getCameraInfo( camIdx, cameraInfo ); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + localCameraIndex = camIdx; + break; + } + } + } + if (localCameraIndex == CameraBridgeViewBase.CAMERA_ID_BACK) { + Log.e(LOGTAG, "Back camera not found!"); + } else if (localCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT) { + Log.e(LOGTAG, "Front camera not found!"); + } else { + Log.d(LOGTAG, "Trying to open camera with new open(" + localCameraIndex + ")"); + try { + mCamera = Camera.open(localCameraIndex); + } catch (RuntimeException e) { + Log.e(LOGTAG, "Camera #" + localCameraIndex + "failed to open: " + e.getLocalizedMessage()); + } + } + } + } + if(mCamera == null) { + Log.e(LOGTAG, "Error: can't open camera"); + return; + } + Camera.Parameters params = mCamera.getParameters(); + List FocusModes = params.getSupportedFocusModes(); + if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) + { + params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + } + mCamera.setParameters(params); + + try { + mCamera.setPreviewTexture(mSTexture); + } catch (IOException ioe) { + Log.e(LOGTAG, "setPreviewTexture() failed: " + ioe.getMessage()); + } + } + + @Override + public synchronized void setCameraPreviewSize(int width, int height) { + Log.i(LOGTAG, "setCameraPreviewSize: "+width+"x"+height); + if(mCamera == null) { + Log.e(LOGTAG, "Camera isn't initialized!"); + return; + } + + if(mMaxCameraWidth > 0 && mMaxCameraWidth < width) width = mMaxCameraWidth; + if(mMaxCameraHeight > 0 && mMaxCameraHeight < height) height = mMaxCameraHeight; + + Camera.Parameters param = mCamera.getParameters(); + List psize = param.getSupportedPreviewSizes(); + int bestWidth = 0, bestHeight = 0; + if (psize.size() > 0) { + float aspect = (float)width / height; + for (Size size : psize) { + int w = size.width, h = size.height; + Log.d(LOGTAG, "checking camera preview size: "+w+"x"+h); + if ( w <= width && h <= height && + w >= bestWidth && h >= bestHeight && + Math.abs(aspect - (float)w/h) < 0.2 ) { + bestWidth = w; + bestHeight = h; + } + } + if(bestWidth <= 0 || bestHeight <= 0) { + bestWidth = psize.get(0).width; + bestHeight = psize.get(0).height; + Log.e(LOGTAG, "Error: best size was not selected, using "+bestWidth+" x "+bestHeight); + } else { + Log.i(LOGTAG, "Selected best size: "+bestWidth+" x "+bestHeight); + } + + if(mPreviewStarted) { + mCamera.stopPreview(); + mPreviewStarted = false; + } + mCameraWidth = bestWidth; + mCameraHeight = bestHeight; + param.setPreviewSize(bestWidth, bestHeight); + } + param.set("orientation", "landscape"); + mCamera.setParameters(param); + mCamera.startPreview(); + mPreviewStarted = true; + } +} \ No newline at end of file diff --git a/modules/java/generator/src/java/android+JavaCameraView.java b/modules/java/generator/src/java/android+JavaCameraView.java index fca29db6e..f4405c350 100644 --- a/modules/java/generator/src/java/android+JavaCameraView.java +++ b/modules/java/generator/src/java/android+JavaCameraView.java @@ -328,6 +328,7 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb @Override public void run() { do { + boolean hasFrame = false; synchronized (JavaCameraView.this) { try { while (!mCameraFrameReady && !mStopThread) { @@ -337,11 +338,14 @@ public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallb e.printStackTrace(); } if (mCameraFrameReady) + { mChainIdx = 1 - mChainIdx; + mCameraFrameReady = false; + hasFrame = true; + } } - if (!mStopThread && mCameraFrameReady) { - mCameraFrameReady = false; + if (!mStopThread && hasFrame) { if (!mFrameChain[1 - mChainIdx].empty()) deliverAndDrawFrame(mCameraFrame[1 - mChainIdx]); } diff --git a/modules/java/pure_test/CMakeLists.txt b/modules/java/pure_test/CMakeLists.txt index 6c9766c7d..7d7841499 100644 --- a/modules/java/pure_test/CMakeLists.txt +++ b/modules/java/pure_test/CMakeLists.txt @@ -24,7 +24,7 @@ file(GLOB_RECURSE test_files RELATIVE "${test_dir}" "${test_dir}/src/*") file(GLOB_RECURSE test_lib_files RELATIVE "${test_dir}" "${test_dir}/lib/*.jar") foreach(f ${test_files} ${test_lib_files}) add_custom_command(OUTPUT "${opencv_test_java_bin_dir}/${f}" - COMMAND ${CMAKE_COMMAND} -E copy "${test_dir}/${f}" "${opencv_test_java_bin_dir}/${f}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${test_dir}/${f}" "${opencv_test_java_bin_dir}/${f}" DEPENDS "${test_dir}/${f}" COMMENT "Copying ${f}" ) @@ -33,13 +33,13 @@ endforeach() # Copy the OpenCV jar after it has been generated. add_custom_command(OUTPUT "${opencv_test_java_bin_dir}/bin/${JAR_NAME}" - COMMAND ${CMAKE_COMMAND} -E copy "${JAR_FILE}" "${opencv_test_java_bin_dir}/bin/${JAR_NAME}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${JAR_FILE}" "${opencv_test_java_bin_dir}/bin/${JAR_NAME}" DEPENDS "${JAR_FILE}" COMMENT "Copying the OpenCV jar" ) add_custom_command(OUTPUT "${opencv_test_java_bin_dir}/build.xml" - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/build.xml" "${opencv_test_java_bin_dir}/build.xml" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/build.xml" "${opencv_test_java_bin_dir}/build.xml" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/build.xml" COMMENT "Copying build.xml" ) diff --git a/modules/ml/src/em.cpp b/modules/ml/src/em.cpp index 59c1352e4..0ee3c4a71 100644 --- a/modules/ml/src/em.cpp +++ b/modules/ml/src/em.cpp @@ -61,7 +61,7 @@ public: void setClustersNumber(int val) { nclusters = val; - CV_Assert(nclusters > 1); + CV_Assert(nclusters >= 1); } int getClustersNumber() const @@ -379,7 +379,7 @@ public: } else if(covMatType == COV_MAT_DIAGONAL) { - covsEigenValues[clusterIndex] = svd.w; + covsEigenValues[clusterIndex] = covs[clusterIndex].diag().clone(); //Preserve the original order of eigen values. } else //COV_MAT_GENERIC { diff --git a/modules/ml/src/gbt.cpp b/modules/ml/src/gbt.cpp index 0ebe19ea3..76baa0001 100644 --- a/modules/ml/src/gbt.cpp +++ b/modules/ml/src/gbt.cpp @@ -243,7 +243,7 @@ CvGBTrees::train( const CvMat* _train_data, int _tflag, for (int i=1; idata.fl[i]) - class_labels->data.i[k]) && (kdata.fl[i]) - class_labels->data.i[k])) k++; if (k == j) { @@ -1274,13 +1274,18 @@ CvGBTrees::calc_error( CvMLData* _data, int type, std::vector *resp ) return -FLT_MAX; float* pred_resp = 0; + bool needsFreeing = false; + if (resp) { resp->resize(n); pred_resp = &((*resp)[0]); } else + { pred_resp = new float[n]; + needsFreeing = true; + } Sample_predictor predictor = Sample_predictor(this, pred_resp, _data->get_values(), _data->get_missing(), _sample_idx); @@ -1313,6 +1318,9 @@ CvGBTrees::calc_error( CvMLData* _data, int type, std::vector *resp ) err = err / (float)n; } + if (needsFreeing) + delete[]pred_resp; + return err; } diff --git a/modules/ml/src/inner_functions.cpp b/modules/ml/src/inner_functions.cpp index 52f368874..b39d40343 100644 --- a/modules/ml/src/inner_functions.cpp +++ b/modules/ml/src/inner_functions.cpp @@ -151,21 +151,28 @@ static void Cholesky( const Mat& A, Mat& S ) average row vector, - symmetric covariation matrix */ void randMVNormal( InputArray _mean, InputArray _cov, int nsamples, OutputArray _samples ) { + // check mean vector and covariance matrix Mat mean = _mean.getMat(), cov = _cov.getMat(); - int dim = (int)mean.total(); + int dim = (int)mean.total(); // dimensionality + CV_Assert(mean.rows == 1 || mean.cols == 1); + CV_Assert(cov.rows == dim && cov.cols == dim); + mean = mean.reshape(1,1); // ensure a row vector + // generate n-samples of the same dimension, from ~N(0,1) _samples.create(nsamples, dim, CV_32F); Mat samples = _samples.getMat(); - randu(samples, 0., 1.); + randn(samples, Scalar::all(0), Scalar::all(1)); + // decompose covariance using Cholesky: cov = U'*U + // (cov must be square, symmetric, and positive semi-definite matrix) Mat utmat; Cholesky(cov, utmat); - int flags = mean.cols == 1 ? 0 : GEMM_3_T; + // transform random numbers using specified mean and covariance for( int i = 0; i < nsamples; i++ ) { Mat sample = samples.row(i); - gemm(sample, utmat, 1, mean, 1, sample, flags); + sample = sample * utmat + mean; } } diff --git a/modules/ml/src/svm.cpp b/modules/ml/src/svm.cpp index 812e2839b..402de3f1d 100644 --- a/modules/ml/src/svm.cpp +++ b/modules/ml/src/svm.cpp @@ -1795,10 +1795,10 @@ public: if( !do_train( temp_train_samples, temp_train_responses )) continue; - for( i = 0; i < train_sample_count; i++ ) + for( i = 0; i < test_sample_count; i++ ) { j = sidx[(i+start+train_sample_count) % sample_count]; - memcpy(temp_train_samples.ptr(i), samples.ptr(j), sample_size); + memcpy(temp_test_samples.ptr(i), samples.ptr(j), sample_size); } predict(temp_test_samples, temp_test_responses, 0); diff --git a/modules/ml/test/test_svmtrainauto.cpp b/modules/ml/test/test_svmtrainauto.cpp index 918d2b711..3c4b72924 100644 --- a/modules/ml/test/test_svmtrainauto.cpp +++ b/modules/ml/test/test_svmtrainauto.cpp @@ -87,3 +87,34 @@ void CV_SVMTrainAutoTest::run( int /*start_from*/ ) } TEST(ML_SVM, trainauto) { CV_SVMTrainAutoTest test; test.safe_run(); } + + +TEST(ML_SVM, trainAuto_regression_5369) +{ + int datasize = 100; + cv::Mat samples = cv::Mat::zeros( datasize, 2, CV_32FC1 ); + cv::Mat responses = cv::Mat::zeros( datasize, 1, CV_32S ); + + RNG rng(0); // fixed! + for (int i = 0; i < datasize; ++i) + { + int response = rng.uniform(0, 2); // Random from {0, 1}. + samples.at( i, 0 ) = 0; + samples.at( i, 1 ) = (0.5f - response) * rng.uniform(0.f, 1.2f) + response; + responses.at( i, 0 ) = response; + } + + cv::Ptr data = TrainData::create( samples, cv::ml::ROW_SAMPLE, responses ); + cv::Ptr svm = SVM::create(); + svm->trainAuto( data, 10 ); // 2-fold cross validation. + + float test_data0[2] = {0.25f, 0.25f}; + cv::Mat test_point0 = cv::Mat( 1, 2, CV_32FC1, test_data0 ); + float result0 = svm->predict( test_point0 ); + float test_data1[2] = {0.75f, 0.75f}; + cv::Mat test_point1 = cv::Mat( 1, 2, CV_32FC1, test_data1 ); + float result1 = svm->predict( test_point1 ); + + EXPECT_EQ(0., result0); + EXPECT_EQ(1., result1); +} diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index 20800ae52..9d7ccfed1 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -1051,7 +1051,7 @@ bool CascadeClassifierImpl::ocl_detectMultiScaleNoGrouping( const std::vectorgetLocalBufSize(); - size_t localsize[] = { localsz.width, localsz.height }; + size_t localsize[] = { (size_t)localsz.width, (size_t)localsz.height }; const int grp_per_CU = 12; size_t globalsize[] = { grp_per_CU*ocl::Device::getDefault().maxComputeUnits()*localsize[0], localsize[1] }; bool ok = false; diff --git a/modules/objdetect/src/haar.cpp b/modules/objdetect/src/haar.cpp index 09928264a..66ea517c3 100644 --- a/modules/objdetect/src/haar.cpp +++ b/modules/objdetect/src/haar.cpp @@ -165,7 +165,11 @@ icvReleaseHidHaarClassifierCascade( CvHidHaarClassifierCascade** _cascade ) for( i = 0; i < cascade->count; i++ ) { if( cascade->ipp_stages[i] ) +#if IPP_VERSION_X100 < 900 ippiHaarClassifierFree_32f( (IppiHaarClassifier_32f*)cascade->ipp_stages[i] ); +#else + cvFree(&cascade->ipp_stages[i]); +#endif } } cvFree( &cascade->ipp_stages ); diff --git a/modules/objdetect/src/hog.cpp b/modules/objdetect/src/hog.cpp index 057387b3e..a6ff7e2ce 100644 --- a/modules/objdetect/src/hog.cpp +++ b/modules/objdetect/src/hog.cpp @@ -1092,7 +1092,7 @@ static bool ocl_compute_gradients_8UC1(int height, int width, InputArray _img, f UMat img = _img.getUMat(); size_t localThreads[3] = { NTHREADS, 1, 1 }; - size_t globalThreads[3] = { width, height, 1 }; + size_t globalThreads[3] = { (size_t)width, (size_t)height, 1 }; char correctGamma = (correct_gamma) ? 1 : 0; int grad_quadstep = (int)grad.step >> 3; int qangle_elem_size = CV_ELEM_SIZE1(qangle.type()); @@ -1152,7 +1152,7 @@ static bool ocl_compute_hists(int nbins, int block_stride_x, int block_stride_y, int qangle_step = (int)qangle.step / qangle_elem_size; int blocks_in_group = 4; - size_t localThreads[3] = { blocks_in_group * 24, 2, 1 }; + size_t localThreads[3] = { (size_t)blocks_in_group * 24, 2, 1 }; size_t globalThreads[3] = {((img_block_width * img_block_height + blocks_in_group - 1)/blocks_in_group) * localThreads[0], 2, 1 }; int hists_size = (nbins * CELLS_PER_BLOCK_X * CELLS_PER_BLOCK_Y * 12) * sizeof(float); @@ -1271,7 +1271,7 @@ static bool ocl_extract_descrs_by_rows(int win_height, int win_width, int block_ int descriptors_quadstep = (int)descriptors.step >> 2; - size_t globalThreads[3] = { img_win_width * NTHREADS, img_win_height, 1 }; + size_t globalThreads[3] = { (size_t)img_win_width * NTHREADS, (size_t)img_win_height, 1 }; size_t localThreads[3] = { NTHREADS, 1, 1 }; int idx = 0; @@ -1305,7 +1305,7 @@ static bool ocl_extract_descrs_by_cols(int win_height, int win_width, int block_ int descriptors_quadstep = (int)descriptors.step >> 2; - size_t globalThreads[3] = { img_win_width * NTHREADS, img_win_height, 1 }; + size_t globalThreads[3] = { (size_t)img_win_width * NTHREADS, (size_t)img_win_height, 1 }; size_t localThreads[3] = { NTHREADS, 1, 1 }; int idx = 0; @@ -1704,8 +1704,8 @@ static bool ocl_classify_hists(int win_height, int win_width, int block_stride_y int img_block_width = (width - CELLS_PER_BLOCK_X * CELL_WIDTH + block_stride_x) / block_stride_x; - size_t globalThreads[3] = { img_win_width * nthreads, img_win_height, 1 }; - size_t localThreads[3] = { nthreads, 1, 1 }; + size_t globalThreads[3] = { (size_t)img_win_width * nthreads, (size_t)img_win_height, 1 }; + size_t localThreads[3] = { (size_t)nthreads, 1, 1 }; idx = k.set(idx, block_hist_size); idx = k.set(idx, img_win_width); diff --git a/modules/objdetect/src/main.cpp b/modules/objdetect/src/main.cpp new file mode 100644 index 000000000..127f86b26 --- /dev/null +++ b/modules/objdetect/src/main.cpp @@ -0,0 +1,52 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +// +// Library initialization file +// + +#include "precomp.hpp" + +IPP_INITIALIZER_AUTO + +/* End of file. */ diff --git a/modules/photo/src/fast_nlmeans_denoising_opencl.hpp b/modules/photo/src/fast_nlmeans_denoising_opencl.hpp index 1c511f37b..f012de507 100644 --- a/modules/photo/src/fast_nlmeans_denoising_opencl.hpp +++ b/modules/photo/src/fast_nlmeans_denoising_opencl.hpp @@ -77,7 +77,7 @@ static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight, almostDist2ActualDistMultiplier, fixedPointMult, ocl::KernelArg::Constant(den, (hn == 3 ? 4 : hn)*sizeof(FT)), WEIGHT_THRESHOLD); - size_t globalsize[1] = { almostMaxDist }; + size_t globalsize[1] = { (size_t)almostMaxDist }; return k.run(1, globalsize, NULL, false); } @@ -172,7 +172,7 @@ static bool ocl_fastNlMeansDenoising(InputArray _src, OutputArray _dst, const fl ocl::KernelArg::PtrReadOnly(almostDist2Weight), ocl::KernelArg::PtrReadOnly(buffer), almostTemplateWindowSizeSqBinShift); - size_t globalsize[2] = { nblocksx * ctaSize, nblocksy }, localsize[2] = { ctaSize, 1 }; + size_t globalsize[2] = { (size_t)nblocksx * ctaSize, (size_t)nblocksy }, localsize[2] = { (size_t)ctaSize, 1 }; if (!k.run(2, globalsize, localsize, false)) return false; if (cn == 3) { diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index 82f1c8b9f..cbe285222 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -1,6 +1,6 @@ #if defined(_MSC_VER) && (_MSC_VER >= 1800) // eliminating duplicated round() declaration -#define HAVE_ROUND +#define HAVE_ROUND 1 #endif #include diff --git a/modules/stitching/src/blenders.cpp b/modules/stitching/src/blenders.cpp index 82e65fa38..1d2fe9e59 100644 --- a/modules/stitching/src/blenders.cpp +++ b/modules/stitching/src/blenders.cpp @@ -267,7 +267,7 @@ static bool ocl_MultiBandBlender_feed(InputArray _src, InputArray _weight, ocl::KernelArg::ReadWrite(_dst_weight.getUMat()) ); - size_t globalsize[2] = {src.cols, src.rows }; + size_t globalsize[2] = {(size_t)src.cols, (size_t)src.rows }; return k.run(2, globalsize, NULL, false); } #endif @@ -469,7 +469,7 @@ static bool ocl_normalizeUsingWeightMap(InputArray _weight, InputOutputArray _ma ocl::KernelArg::ReadOnly(_weight.getUMat()) ); - size_t globalsize[2] = {mat.cols, mat.rows }; + size_t globalsize[2] = {(size_t)mat.cols, (size_t)mat.rows }; return k.run(2, globalsize, NULL, false); } #endif diff --git a/modules/stitching/src/warpers.cpp b/modules/stitching/src/warpers.cpp index 141fdec35..e69f8d25d 100644 --- a/modules/stitching/src/warpers.cpp +++ b/modules/stitching/src/warpers.cpp @@ -124,7 +124,7 @@ Rect PlaneWarper::buildMaps(Size src_size, InputArray K, InputArray R, InputArra ocl::KernelArg::PtrReadOnly(uk_rinv), ocl::KernelArg::PtrReadOnly(ut), dst_tl.x, dst_tl.y, 1/projector_.scale, rowsPerWI); - size_t globalsize[2] = { dsize.width, (dsize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dsize.width, ((size_t)dsize.height + rowsPerWI - 1) / rowsPerWI }; if (k.run(2, globalsize, NULL, true)) { CV_IMPL_ADD(CV_IMPL_OCL); @@ -331,7 +331,7 @@ Rect SphericalWarper::buildMaps(Size src_size, InputArray K, InputArray R, Outpu k.args(ocl::KernelArg::WriteOnlyNoSize(uxmap), ocl::KernelArg::WriteOnly(uymap), ocl::KernelArg::PtrReadOnly(uk_rinv), dst_tl.x, dst_tl.y, 1/projector_.scale, rowsPerWI); - size_t globalsize[2] = { dsize.width, (dsize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dsize.width, ((size_t)dsize.height + rowsPerWI - 1) / rowsPerWI }; if (k.run(2, globalsize, NULL, true)) { CV_IMPL_ADD(CV_IMPL_OCL); @@ -380,7 +380,7 @@ Rect CylindricalWarper::buildMaps(Size src_size, InputArray K, InputArray R, Out ocl::KernelArg::PtrReadOnly(uk_rinv), dst_tl.x, dst_tl.y, 1/projector_.scale, rowsPerWI); - size_t globalsize[2] = { dsize.width, (dsize.height + rowsPerWI - 1) / rowsPerWI }; + size_t globalsize[2] = { (size_t)dsize.width, ((size_t)dsize.height + rowsPerWI - 1) / rowsPerWI }; if (k.run(2, globalsize, NULL, true)) { CV_IMPL_ADD(CV_IMPL_OCL); diff --git a/modules/superres/src/btv_l1.cpp b/modules/superres/src/btv_l1.cpp index 291fa1bcb..d47453f0d 100644 --- a/modules/superres/src/btv_l1.cpp +++ b/modules/superres/src/btv_l1.cpp @@ -185,7 +185,7 @@ namespace ocl::KernelArg::WriteOnlyNoSize(forwardMap), ocl::KernelArg::WriteOnly(backwardMap)); - size_t globalsize[2] = { size.width, size.height }; + size_t globalsize[2] = { (size_t)size.width, (size_t)size.height }; return k.run(2, globalsize, NULL, false); } @@ -258,7 +258,7 @@ namespace k.args(ocl::KernelArg::ReadOnly(src), ocl::KernelArg::ReadWriteNoSize(dst), scale); - size_t globalsize[2] = { src.cols, src.rows }; + size_t globalsize[2] = { (size_t)src.cols, (size_t)src.rows }; return k.run(2, globalsize, NULL, false); } @@ -316,7 +316,7 @@ namespace ocl::KernelArg::ReadOnlyNoSize(src2), ocl::KernelArg::WriteOnly(dst, cn)); - size_t globalsize[2] = { src1.cols * cn, src1.rows }; + size_t globalsize[2] = { (size_t)src1.cols * cn, (size_t)src1.rows }; return k.run(2, globalsize, NULL, false); } @@ -436,7 +436,7 @@ namespace k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), ksize, ocl::KernelArg::PtrReadOnly(ubtvWeights)); - size_t globalsize[2] = { src.cols, src.rows }; + size_t globalsize[2] = { (size_t)src.cols, (size_t)src.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/superres/src/input_array_utility.cpp b/modules/superres/src/input_array_utility.cpp index ec20673b4..a823e43cd 100644 --- a/modules/superres/src/input_array_utility.cpp +++ b/modules/superres/src/input_array_utility.cpp @@ -205,11 +205,11 @@ namespace static const double maxVals[] = { - std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::max(), + (double)std::numeric_limits::max(), + (double)std::numeric_limits::max(), + (double)std::numeric_limits::max(), + (double)std::numeric_limits::max(), + (double)std::numeric_limits::max(), 1.0, 1.0, }; diff --git a/modules/ts/misc/run.py b/modules/ts/misc/run.py index f25922d94..a3a13145a 100755 --- a/modules/ts/misc/run.py +++ b/modules/ts/misc/run.py @@ -1,940 +1,87 @@ #!/usr/bin/env python -import sys, os, platform, xml, re, tempfile, glob, datetime, getpass, shutil -from optparse import OptionParser -from subprocess import Popen, PIPE - -hostos = os.name # 'nt', 'posix' -hostmachine = platform.machine() # 'x86', 'AMD64', 'x86_64' - -errorCode = 0 - -SIMD_DETECTION_PROGRAM=""" -#if __SSE5__ -# error SSE5 -#endif -#if __AVX2__ -# error AVX2 -#endif -#if __AVX__ -# error AVX -#endif -#if __SSE4_2__ -# error SSE4.2 -#endif -#if __SSE4_1__ -# error SSE4.1 -#endif -#if __SSSE3__ -# error SSSE3 -#endif -#if __SSE3__ -# error SSE3 -#endif -#if __AES__ -# error AES -#endif -#if __SSE2__ -# error SSE2 -#endif -#if __SSE__ -# error SSE -#endif -#if __3dNOW__ -# error 3dNOW -#endif -#if __MMX__ -# error MMX -#endif -#if __ARM_NEON__ -# error NEON -#endif -#error NOSIMD -""" - -parse_patterns = ( - {'name': "has_perf_tests", 'default': "OFF", 'pattern': re.compile("^BUILD_PERF_TESTS:BOOL=(ON)$")}, - {'name': "has_accuracy_tests", 'default': "OFF", 'pattern': re.compile("^BUILD_TESTS:BOOL=(ON)$")}, - {'name': "cmake_home", 'default': None, 'pattern': re.compile("^CMAKE_HOME_DIRECTORY:INTERNAL=(.+)$")}, - {'name': "opencv_home", 'default': None, 'pattern': re.compile("^OpenCV_SOURCE_DIR:STATIC=(.+)$")}, - {'name': "tests_dir", 'default': None, 'pattern': re.compile("^EXECUTABLE_OUTPUT_PATH:PATH=(.+)$")}, - {'name': "build_type", 'default': "Release", 'pattern': re.compile("^CMAKE_BUILD_TYPE:STRING=(.*)$")}, - {'name': "svnversion_path", 'default': None, 'pattern': re.compile("^SVNVERSION_PATH:FILEPATH=(.*)$")}, - {'name': "git_executable", 'default': None, 'pattern': re.compile("^GIT_EXECUTABLE:FILEPATH=(.*)$")}, - {'name': "cxx_flags", 'default': "", 'pattern': re.compile("^CMAKE_CXX_FLAGS:STRING=(.*)$")}, - {'name': "cxx_flags_debug", 'default': "", 'pattern': re.compile("^CMAKE_CXX_FLAGS_DEBUG:STRING=(.*)$")}, - {'name': "cxx_flags_release", 'default': "", 'pattern': re.compile("^CMAKE_CXX_FLAGS_RELEASE:STRING=(.*)$")}, - {'name': "opencv_cxx_flags", 'default': "", 'pattern': re.compile("^OPENCV_EXTRA_C_FLAGS:INTERNAL=(.*)$")}, - {'name': "opencv_cxx_flags_debug", 'default': "", 'pattern': re.compile("^OPENCV_EXTRA_C_FLAGS_DEBUG:INTERNAL=(.*)$")}, - {'name': "opencv_cxx_flags_release", 'default': "", 'pattern': re.compile("^OPENCV_EXTRA_C_FLAGS_RELEASE:INTERNAL=(.*)$")}, - {'name': "cxx_flags_android", 'default': None, 'pattern': re.compile("^ANDROID_CXX_FLAGS:INTERNAL=(.*)$")}, - {'name': "ndk_path", 'default': None, 'pattern': re.compile("^(?:ANDROID_NDK|ANDROID_STANDALONE_TOOLCHAIN)?:PATH=(.*)$")}, - {'name': "android_abi", 'default': None, 'pattern': re.compile("^ANDROID_ABI:STRING=(.*)$")}, - {'name': "android_executable", 'default': None, 'pattern': re.compile("^ANDROID_EXECUTABLE:FILEPATH=(.*android.*)$")}, - {'name': "ant_executable", 'default': None, 'pattern': re.compile("^ANT_EXECUTABLE:FILEPATH=(.*ant.*)$")}, - {'name': "java_test_binary_dir", 'default': None, 'pattern': re.compile("^opencv_test_java_BINARY_DIR:STATIC=(.*)$")}, - {'name': "is_x64", 'default': "OFF", 'pattern': re.compile("^CUDA_64_BIT_DEVICE_CODE:BOOL=(ON)$")},#ugly( - {'name': "cmake_generator", 'default': None, 'pattern': re.compile("^CMAKE_GENERATOR:INTERNAL=(.+)$")}, - {'name': "cxx_compiler", 'default': None, 'pattern': re.compile("^CMAKE_CXX_COMPILER:FILEPATH=(.+)$")}, - {'name': "cxx_compiler_arg1", 'default': None, 'pattern': re.compile("^CMAKE_CXX_COMPILER_ARG1:[A-Z]+=(.+)$")}, - {'name': "with_cuda", 'default': "OFF", 'pattern': re.compile("^WITH_CUDA:BOOL=(ON)$")}, - {'name': "cuda_library", 'default': None, 'pattern': re.compile("^CUDA_CUDA_LIBRARY:FILEPATH=(.+)$")}, - {'name': "core_dependencies", 'default': None, 'pattern': re.compile("^opencv_core_LIB_DEPENDS:STATIC=(.+)$")}, -) - -def query_yes_no(stdout, question, default="yes"): - valid = {"yes":True, "y":True, "ye":True, "no":False, "n":False} - if default == None: - prompt = " [y/n] " - elif default == "yes": - prompt = " [Y/n] " - elif default == "no": - prompt = " [y/N] " - else: - raise ValueError("invalid default answer: '%s'" % default) - - while True: - stdout.write(os.linesep + question + prompt) - choice = raw_input().lower() - if default is not None and choice == '': - return valid[default] - elif choice in valid: - return valid[choice] - else: - stdout.write("Please respond with 'yes' or 'no' "\ - "(or 'y' or 'n').\n") - -def getRunningProcessExePathByName_win32(name): - from ctypes import windll, POINTER, pointer, Structure, sizeof - from ctypes import c_long , c_int , c_uint , c_char , c_ubyte , c_char_p , c_void_p - - class PROCESSENTRY32(Structure): - _fields_ = [ ( 'dwSize' , c_uint ) , - ( 'cntUsage' , c_uint) , - ( 'th32ProcessID' , c_uint) , - ( 'th32DefaultHeapID' , c_uint) , - ( 'th32ModuleID' , c_uint) , - ( 'cntThreads' , c_uint) , - ( 'th32ParentProcessID' , c_uint) , - ( 'pcPriClassBase' , c_long) , - ( 'dwFlags' , c_uint) , - ( 'szExeFile' , c_char * 260 ) , - ( 'th32MemoryBase' , c_long) , - ( 'th32AccessKey' , c_long ) ] - - class MODULEENTRY32(Structure): - _fields_ = [ ( 'dwSize' , c_long ) , - ( 'th32ModuleID' , c_long ), - ( 'th32ProcessID' , c_long ), - ( 'GlblcntUsage' , c_long ), - ( 'ProccntUsage' , c_long ) , - ( 'modBaseAddr' , c_long ) , - ( 'modBaseSize' , c_long ) , - ( 'hModule' , c_void_p ) , - ( 'szModule' , c_char * 256 ), - ( 'szExePath' , c_char * 260 ) ] - - TH32CS_SNAPPROCESS = 2 - TH32CS_SNAPMODULE = 0x00000008 - - ## CreateToolhelp32Snapshot - CreateToolhelp32Snapshot= windll.kernel32.CreateToolhelp32Snapshot - CreateToolhelp32Snapshot.reltype = c_long - CreateToolhelp32Snapshot.argtypes = [ c_int , c_int ] - ## Process32First - Process32First = windll.kernel32.Process32First - Process32First.argtypes = [ c_void_p , POINTER( PROCESSENTRY32 ) ] - Process32First.rettype = c_int - ## Process32Next - Process32Next = windll.kernel32.Process32Next - Process32Next.argtypes = [ c_void_p , POINTER(PROCESSENTRY32) ] - Process32Next.rettype = c_int - ## CloseHandle - CloseHandle = windll.kernel32.CloseHandle - CloseHandle.argtypes = [ c_void_p ] - CloseHandle.rettype = c_int - ## Module32First - Module32First = windll.kernel32.Module32First - Module32First.argtypes = [ c_void_p , POINTER(MODULEENTRY32) ] - Module32First.rettype = c_int - - hProcessSnap = c_void_p(0) - hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ) - - pe32 = PROCESSENTRY32() - pe32.dwSize = sizeof( PROCESSENTRY32 ) - ret = Process32First( hProcessSnap , pointer( pe32 ) ) - path = None - - while ret : - if name + ".exe" == pe32.szExeFile: - hModuleSnap = c_void_p(0) - me32 = MODULEENTRY32() - me32.dwSize = sizeof( MODULEENTRY32 ) - hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pe32.th32ProcessID ) - - ret = Module32First( hModuleSnap, pointer(me32) ) - path = me32.szExePath - CloseHandle( hModuleSnap ) - if path: - break - ret = Process32Next( hProcessSnap, pointer(pe32) ) - CloseHandle( hProcessSnap ) - return path - -def getRunningProcessExePathByName_posix(name): - pids= [pid for pid in os.listdir('/proc') if pid.isdigit()] - for pid in pids: - try: - path = os.readlink(os.path.join('/proc', pid, 'exe')) - if path and path.endswith(name): - return path - except: - pass - -def getRunningProcessExePathByName(name): - try: - if hostos == "nt": - return getRunningProcessExePathByName_win32(name) - elif hostos == "posix": - return getRunningProcessExePathByName_posix(name) - else: - return None - except: - return None - -class TestSuite(object): - def __init__(self, options, path = None): - self.options = options - self.path = path - self.error = None - self.setUp = None - self.tearDown = None - self.adb = None - self.targetos = None - self.nameprefix = "opencv_" + self.options.mode + "_" - for p in parse_patterns: - setattr(self, p["name"], p["default"]) - - if self.path: - cachefile = open(os.path.join(self.path, "CMakeCache.txt"), "rt") - try: - for l in cachefile.readlines(): - ll = l.strip() - if not ll or ll.startswith("#"): - continue - for p in parse_patterns: - match = p["pattern"].match(ll) - if match: - value = match.groups()[0] - if value and not value.endswith("-NOTFOUND"): - setattr(self, p["name"], value) - except: - pass - cachefile.close() - - # detect target platform - if self.android_executable or self.android_abi or self.ndk_path: - self.targetos = "android" - else: - self.targetos = hostos - - self.initialize() - - def initialize(self): - # fix empty tests dir - if not self.tests_dir: - self.tests_dir = self.path - self.tests_dir = os.path.normpath(self.tests_dir) - - # compute path to adb - if self.android_executable: - self.adb = os.path.join(os.path.dirname(os.path.dirname(self.android_executable)), ("platform-tools/adb","platform-tools/adb.exe")[hostos == 'nt']) - if not os.path.isfile(self.adb) or not os.access(self.adb, os.X_OK): - self.adb = None - else: - self.adb = None - - if self.targetos == "android": - # fix adb tool location - if not self.adb: - self.adb = getRunningProcessExePathByName("adb") - if not self.adb: - self.adb = "adb" - if self.options.adb_serial: - self.adb = [self.adb, "-s", self.options.adb_serial] - else: - self.adb = [self.adb] - try: - output = Popen(self.adb + ["shell", "ls"], stdout=PIPE, stderr=PIPE).communicate() - except OSError: - self.adb = [] - # remember current device serial. Needed if another device is connected while this script runs - if self.adb and not self.options.adb_serial: - adb_res = self.runAdb("devices") - if not adb_res: - self.error = "Could not run adb command: %s (for %s)" % (self.error, self.path) - self.adb = [] - else: - # assume here that device name may consists of any characters except newline - connected_devices = re.findall(r"^[^\n]+[ \t]+device\r?$", adb_res, re.MULTILINE) - if not connected_devices: - self.error = "Android device not found" - self.adb = [] - elif len(connected_devices) != 1: - self.error = "Too many (%s) devices are connected. Please specify single device using --serial option:\n\n" % (len(connected_devices)) + adb_res - self.adb = [] - else: - self.options.adb_serial = connected_devices[0].split("\t")[0] - self.adb = self.adb + ["-s", self.options.adb_serial] - if self.adb: - # construct name for aapt tool - self.aapt = [os.path.join(os.path.dirname(self.adb[0]), ("aapt","aapt.exe")[hostos == 'nt'])] - if not os.path.isfile(self.aapt[0]): - # it's moved in SDK r22 - sdk_dir = os.path.dirname( os.path.dirname(self.adb[0]) ) - aapt_fn = ("aapt", "aapt.exe")[hostos == 'nt'] - for r, ds, fs in os.walk( os.path.join(sdk_dir, 'build-tools') ): - if aapt_fn in fs: - self.aapt = [ os.path.join(r, aapt_fn) ] - break - else: - self.error = "Can't find '%s' tool!" % aapt_fn - - # fix has_perf_tests param - self.has_perf_tests = self.has_perf_tests == "ON" - self.has_accuracy_tests = self.has_accuracy_tests == "ON" - # fix is_x64 flag - self.is_x64 = self.is_x64 == "ON" - if not self.is_x64 and ("X64" in "%s %s %s" % (self.cxx_flags, self.cxx_flags_release, self.cxx_flags_debug) or "Win64" in self.cmake_generator): - self.is_x64 = True - - # fix test path - if "Visual Studio" in self.cmake_generator: - if self.options.configuration: - self.tests_dir = os.path.join(self.tests_dir, self.options.configuration) - else: - self.tests_dir = os.path.join(self.tests_dir, self.build_type) - elif not self.is_x64 and self.cxx_compiler: - #one more attempt to detect x64 compiler - try: - compiler = [self.cxx_compiler] - if self.cxx_compiler_arg1: - compiler.append(self.cxx_compiler_arg1) - output = Popen(compiler + ["-v"], stdout=PIPE, stderr=PIPE).communicate() - if not output[0] and "x86_64" in output[1]: - self.is_x64 = True - except OSError: - pass - - # detect target arch - if self.targetos == "android": - if "armeabi-v7a" in self.android_abi: - self.targetarch = "armv7a" - elif "armeabi-v6" in self.android_abi: - self.targetarch = "armv6" - elif "armeabi" in self.android_abi: - self.targetarch = "armv5te" - elif "x86" in self.android_abi: - self.targetarch = "x86" - elif "mips" in self.android_abi: - self.targetarch = "mips" - else: - self.targetarch = "ARM" - elif self.is_x64 and hostmachine in ["AMD64", "x86_64"]: - self.targetarch = "x64" - elif hostmachine in ["x86", "AMD64", "x86_64"]: - self.targetarch = "x86" - else: - self.targetarch = "unknown" - - # fix CUDA attributes - self.with_cuda = self.with_cuda == "ON" - if self.cuda_library and self.cuda_library.endswith("-NOTFOUND"): - self.cuda_library = None - self.has_cuda = self.with_cuda and self.cuda_library and self.targetarch in ["x86", "x64"] - - self.hardware = None - - self.cmake_home_vcver = self.getVCVersion(self.cmake_home) - if self.opencv_home == self.cmake_home: - self.opencv_home_vcver = self.cmake_home_vcver - else: - self.opencv_home_vcver = self.getVCVersion(self.opencv_home) - - self.tests = self.getAvailableTestApps() - - def getVCVersion(self, root_path): - if not root_path: - return None - if os.path.isdir(os.path.join(root_path, ".svn")): - return self.getSvnVersion(root_path) - elif os.path.isdir(os.path.join(root_path, ".git")): - return self.getGitHash(root_path) - return None - - def getGitHash(self, path): - if not path or not self.git_executable: - return None - try: - output = Popen([self.git_executable, "rev-parse", "--short", "HEAD"], stdout=PIPE, stderr=PIPE, cwd = path).communicate() - if not output[1]: - return output[0].strip() - else: - return None - except OSError: - return None - - def getSvnVersion(self, path): - if not path: - val = None - elif not self.svnversion_path and hostos == 'nt': - val = self.tryGetSvnVersionWithTortoise(path) - else: - svnversion = self.svnversion_path - if not svnversion: - svnversion = "svnversion" - try: - output = Popen([svnversion, "-n", path], stdout=PIPE, stderr=PIPE).communicate() - if not output[1]: - val = output[0] - else: - val = None - except OSError: - val = None - if val: - val = val.replace(" ", "_") - return val - - def tryGetSvnVersionWithTortoise(self, path): - try: - wcrev = "SubWCRev.exe" - dir = tempfile.mkdtemp() - #print dir - tmpfilename = os.path.join(dir, "svn.tmp") - tmpfilename2 = os.path.join(dir, "svn_out.tmp") - tmpfile = open(tmpfilename, "w") - tmpfile.write("$WCRANGE$$WCMODS?M:$") - tmpfile.close(); - output = Popen([wcrev, path, tmpfilename, tmpfilename2, "-f"], stdout=PIPE, stderr=PIPE).communicate() - if "is not a working copy" in output[0]: - version = "exported" - else: - tmpfile = open(tmpfilename2, "r") - version = tmpfile.read() - tmpfile.close() - return version - except: - return None - finally: - if dir: - shutil.rmtree(dir) - - def isTest(self, fullpath): - if not os.path.isfile(fullpath): - return False - if self.targetos == "nt" and not fullpath.endswith(".exe"): - return False - if hostos == self.targetos: - return os.access(fullpath, os.X_OK) - if self.targetos == "android" and fullpath.endswith(".apk"): - return True - return True - - def getAvailableTestApps(self): - if self.tests_dir and os.path.isdir(self.tests_dir): - files = glob.glob(os.path.join(self.tests_dir, self.nameprefix + "*")) - files = [f for f in files if self.isTest(f)] - if self.ant_executable and self.java_test_binary_dir: - files.append("java") - return files - return [] - - def getLogName(self, app, timestamp): - app = os.path.basename(app) - if app.endswith(".exe"): - if app.endswith("d.exe"): - app = app[:-5] - else: - app = app[:-4] - if app.startswith(self.nameprefix): - app = app[len(self.nameprefix):] - - if self.cmake_home_vcver: - if self.cmake_home_vcver == self.opencv_home_vcver: - rev = self.cmake_home_vcver - elif self.opencv_home_vcver: - rev = self.cmake_home_vcver + "-" + self.opencv_home_vcver - else: - rev = self.cmake_home_vcver - else: - rev = None - if rev: - rev = rev.replace(":","to") - else: - rev = "" - - if self.options.useLongNames: - if not rev: - rev = "unknown" - tstamp = timestamp.strftime("%Y%m%d-%H%M%S") - - features = [] - #OS - _os = "" - if self.targetos == "android": - _os = "Android" + self.runAdb("shell", "getprop ro.build.version.release").strip() - else: - mv = platform.mac_ver() - if mv[0]: - _os = "Darwin" + mv[0] - else: - wv = platform.win32_ver() - if wv[0]: - _os = "Windows" + wv[0] - else: - lv = platform.linux_distribution() - if lv[0]: - _os = lv[0] + lv[1] - else: - _os = self.targetos - features.append(_os) - - #HW(x86, x64, ARMv7a) - if self.targetarch: - features.append(self.targetarch) - - #TBB - if ";tbb;" in self.core_dependencies: - features.append("TBB") - - #CUDA - if self.has_cuda: - #TODO: determine compute capability - features.append("CUDA") - - #SIMD - compiler_output = "" - try: - tmpfile = tempfile.mkstemp(suffix=".cpp", text = True) - fd = os.fdopen(tmpfile[0], "w+b") - fd.write(SIMD_DETECTION_PROGRAM) - fd.close(); - options = [self.cxx_compiler] - if self.cxx_compiler_arg1: - options.append(self.cxx_compiler_arg1) - cxx_flags = self.cxx_flags + " " + self.cxx_flags_release + " " + self.opencv_cxx_flags + " " + self.opencv_cxx_flags_release - if self.targetos == "android" and self.cxx_flags_android: - cxx_flags = self.cxx_flags_android + " " + cxx_flags - - prev_option = None - for opt in cxx_flags.split(" "): - if opt.count('\"') % 2 == 1: - if prev_option is None: - prev_option = opt - else: - options.append(prev_option + " " + opt) - prev_option = None - elif prev_option is None: - options.append(opt) - else: - prev_option = prev_option + " " + opt - options.append(tmpfile[1]) - output = Popen(options, stdout=PIPE, stderr=PIPE).communicate() - compiler_output = output[1] - os.remove(tmpfile[1]) - except OSError: - pass - if compiler_output: - m = re.search("#error\W+(\w+)", compiler_output) - if m: - features.append(m.group(1)) - - #fin - return "%s__%s__%s__%s.xml" % (app, rev, tstamp, "_".join(features)) - else: - if rev: - rev = rev + "_" - if self.hardware: - hw = str(self.hardware).replace(" ", "_") + "_" - elif self.has_cuda: - hw = "CUDA_" - else: - hw = "" - tstamp = timestamp.strftime("%Y%m%d-%H%M%S") - lname = "%s_%s_%s_%s%s%s.xml" % (app, self.targetos, self.targetarch, hw, rev, tstamp) - lname = str.replace(lname, '(', '_') - lname = str.replace(lname, ')', '_') - return lname - - def getTest(self, name): - # full path - if self.isTest(name): - return name - - # name only - fullname = os.path.join(self.tests_dir, name) - if self.isTest(fullname): - return fullname - - # name without extension - fullname += ".exe" - if self.isTest(fullname): - return fullname - if self.targetos == "android": - fullname += ".apk" - if self.isTest(fullname): - return fullname - - # short name for OpenCV tests - for t in self.tests: - if t == name: - return t - fname = os.path.basename(t) - if fname == name: - return t - if fname.endswith(".exe") or (self.targetos == "android" and fname.endswith(".apk")): - fname = fname[:-4] - if fname == name: - return t - if self.options.configuration == "Debug" and fname == name + 'd': - return t - if fname.startswith(self.nameprefix): - fname = fname[len(self.nameprefix):] - if fname == name: - return t - if self.options.configuration == "Debug" and fname == name + 'd': - return t - return None - - def runAdb(self, *args): - cmd = self.adb[:] - cmd.extend(args) - try: - output = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate() - if not output[1]: - return output[0] - self.error = output[1] - except OSError: - pass - return None - - def isRunnable(self): - if self.error: - return False - if self.targetarch == "x64" and hostmachine == "x86": - self.error = "Target architecture is incompatible with current platform (at %s)" % self.path - return False - if self.targetos == "android": - if not self.adb: - self.error = "Could not find adb executable (for %s)" % self.path - return False - if "armeabi-v7a" in self.android_abi: - adb_res = self.runAdb("shell", "cat /proc/cpuinfo") - if not adb_res: - self.error = "Could not get info about Android platform: %s (for %s)" % (self.error, self.path) - return False - if "ARMv7" not in adb_res: - self.error = "Android device does not support ARMv7 commands, but tests are built for armeabi-v7a (for %s)" % self.path - return False - if "NEON" in self.android_abi and "neon" not in adb_res: - self.error = "Android device has no NEON, but tests are built for %s (for %s)" % (self.android_abi, self.path) - return False - hw = re.search(r"^Hardware[ \t]*:[ \t]*(.*?)$", adb_res, re.MULTILINE) - if hw: - self.hardware = hw.groups()[0].strip() - return True - - def runTest(self, path, workingDir, _stdout, _stderr, args = []): - global errorCode - - if self.error: - return - args = args[:] - timestamp = datetime.datetime.now() - logfile = self.getLogName(path, timestamp) - exe = os.path.abspath(path) - - userlog = [a for a in args if a.startswith("--gtest_output=")] - if len(userlog) == 0: - args.append("--gtest_output=xml:" + logfile) - else: - logfile = userlog[0][userlog[0].find(":")+1:] - - if self.targetos == "android" and exe.endswith(".apk"): - print "Run java tests:", exe - try: - # get package info - output = Popen(self.aapt + ["dump", "xmltree", exe, "AndroidManifest.xml"], stdout=PIPE, stderr=_stderr).communicate() - if not output[0]: - print >> _stderr, "fail to dump manifest from", exe - return - tags = re.split(r"[ ]+E: ", output[0]) - # get package name - manifest_tag = [t for t in tags if t.startswith("manifest ")] - if not manifest_tag: - print >> _stderr, "fail to read package name from", exe - return - pkg_name = re.search(r"^[ ]+A: package=\"(?P.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", manifest_tag[0], flags=re.MULTILINE).group("pkg") - # get test instrumentation info - instrumentation_tag = [t for t in tags if t.startswith("instrumentation ")] - if not instrumentation_tag: - print >> _stderr, "can not find instrumentation detials in", exe - return - pkg_runner = re.search(r"^[ ]+A: android:name\(0x[0-9a-f]{8}\)=\"(?P.*?)\" \(Raw: \"(?P=runner)\"\)\r?$", instrumentation_tag[0], flags=re.MULTILINE).group("runner") - pkg_target = re.search(r"^[ ]+A: android:targetPackage\(0x[0-9a-f]{8}\)=\"(?P.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", instrumentation_tag[0], flags=re.MULTILINE).group("pkg") - if not pkg_name or not pkg_runner or not pkg_target: - print >> _stderr, "can not find instrumentation detials in", exe - return - if self.options.junit_package: - if self.options.junit_package.startswith("."): - pkg_target += self.options.junit_package - else: - pkg_target = self.options.junit_package - # uninstall previously installed package - print >> _stderr, "Uninstalling old", pkg_name, "from device..." - Popen(self.adb + ["uninstall", pkg_name], stdout=PIPE, stderr=_stderr).communicate() - print >> _stderr, "Installing new", exe, "to device...", - output = Popen(self.adb + ["install", exe], stdout=PIPE, stderr=PIPE).communicate() - if output[0] and output[0].strip().endswith("Success"): - print >> _stderr, "Success" - else: - print >> _stderr, "Failure" - print >> _stderr, "Failed to install", exe, "to device" - return - print >> _stderr, "Running jUnit tests for ", pkg_target - if self.setUp: - self.setUp() - Popen(self.adb + ["shell", "am instrument -w -e package " + pkg_target + " " + pkg_name + "/" + pkg_runner], stdout=_stdout, stderr=_stderr).wait() - if self.tearDown: - self.tearDown() - except OSError: - pass - return - elif self.targetos == "android": - hostlogpath = "" - usercolor = [a for a in args if a.startswith("--gtest_color=")] - if len(usercolor) == 0 and _stdout.isatty() and hostos != "nt": - args.append("--gtest_color=yes") - try: - tempdir = "/data/local/tmp/" - andoidcwd = tempdir + getpass.getuser().replace(" ","") + "_" + self.options.mode +"/" - exename = os.path.basename(exe) - androidexe = andoidcwd + exename - # upload - _stderr.write("Uploading... ") - output = Popen(self.adb + ["push", exe, androidexe], stdout=_stdout, stderr=_stderr).wait() - if output != 0: - print >> _stderr, "adb finishes unexpectedly with error code", output - return - # chmod - output = Popen(self.adb + ["shell", "chmod 777 " + androidexe], stdout=_stdout, stderr=_stderr).wait() - if output != 0: - print >> _stderr, "adb finishes unexpectedly with error code", output - return - # run - if self.options.help: - command = exename + " --help" - else: - command = exename + " " + " ".join(args) - print >> _stderr, "Run command:", command - if self.setUp: - self.setUp() - env = self.options.android_env.copy() - env['OPENCV_TEST_DATA_PATH'] = self.options.test_data_path - if self.options.android_propagate_opencv_env: - for k, v in os.environ.items(): - if k.startswith('OPENCV') and not k in env: - env[k] = v - print >> _stderr, "Android environment variables: \n", '\n'.join([' %s=%s' % (k, v) for k, v in env.items()]) - commandPrefix = ''.join(['export %s=%s && ' % (k, v) for k, v in env.items()]) - Popen(self.adb + ["shell", commandPrefix + "cd " + andoidcwd + "&& ./" + command], stdout=_stdout, stderr=_stderr).wait() - if self.tearDown: - self.tearDown() - # try get log - if not self.options.help: - #_stderr.write("Pull log... ") - hostlogpath = os.path.join(workingDir, logfile) - output = Popen(self.adb + ["pull", andoidcwd + logfile, hostlogpath], stdout=_stdout, stderr=PIPE).wait() - if output != 0: - print >> _stderr, "adb finishes unexpectedly with error code", output - return - #rm log - Popen(self.adb + ["shell", "rm " + andoidcwd + logfile], stdout=PIPE, stderr=PIPE).wait() - - # clean temporary files - Popen(self.adb + ["shell", "rm " + tempdir + "__opencv_temp.*"], stdout=PIPE, stderr=PIPE).wait() - except OSError: - pass - if os.path.isfile(hostlogpath): - return hostlogpath - return None - elif path == "java": - cmd = [self.ant_executable, - "-Dopencv.build.type=" - + (self.options.configuration if self.options.configuration else self.build_type), - "buildAndTest"] - - print >> _stderr, "Run command:", " ".join(cmd) - try: - errorCode = Popen(cmd, stdout=_stdout, stderr=_stderr, cwd = self.java_test_binary_dir + "/.build").wait() - except: - print "Unexpected error:", sys.exc_info()[0] - - return None - else: - cmd = [exe] - if self.options.help: - cmd.append("--help") - else: - cmd.extend(args) - - orig_temp_path = os.environ.get('OPENCV_TEMP_PATH') - temp_path = tempfile.mkdtemp(prefix="__opencv_temp.", dir=orig_temp_path or None) - os.environ['OPENCV_TEMP_PATH'] = temp_path - - print >> _stderr, "Run command:", " ".join(cmd) - try: - errorCode = Popen(cmd, stdout=_stdout, stderr=_stderr, cwd = workingDir).wait() - except: - print "Unexpected error:", sys.exc_info()[0] - - # clean temporary files - if orig_temp_path: - os.environ['OPENCV_TEMP_PATH'] = orig_temp_path - else: - del os.environ['OPENCV_TEMP_PATH'] - - try: - shutil.rmtree(temp_path) - pass - except: - pass - - logpath = os.path.join(workingDir, logfile) - if os.path.isfile(logpath): - return logpath - return None - - def runTests(self, tests, _stdout, _stderr, workingDir, args = []): - if not self.isRunnable(): - print >> _stderr, "Error:", self.error - if self.error: - return [] - if self.adb and self.targetos == "android": - print "adb command:", " ".join(self.adb) - if not tests: - tests = self.tests - logs = [] - for test in tests: - t = self.getTest(test) - if t: - logfile = self.runTest(t, workingDir, _stdout, _stderr, args) - if logfile: - logs.append(os.path.relpath(logfile, ".")) - else: - print >> _stderr, "Error: Test \"%s\" is not found in %s" % (test, self.tests_dir) - return logs - -def getRunArgs(args): - run_args = [] - for path in args: - path = os.path.abspath(path) - while (True): - if os.path.isdir(path) and os.path.isfile(os.path.join(path, "CMakeCache.txt")): - run_args.append(path) - break - npath = os.path.dirname(path) - if npath == path: - break - path = npath - return run_args - -if hostos == "nt": - def moveTests(instance, destination): - src = os.path.dirname(instance.tests_dir) - # new binaries path - newBinPath = os.path.join(destination, "bin") - - try: - # copy binaries and CMakeCache.txt to the specified destination - shutil.copytree(src, newBinPath) - shutil.copy(os.path.join(instance.path, "CMakeCache.txt"), os.path.join(destination, "CMakeCache.txt")) - except Exception, e: - print "Copying error occurred:", str(e) - exit(e.errno) - - # pattern of CMakeCache.txt string to be replaced - replacePattern = re.compile("EXECUTABLE_OUTPUT_PATH:PATH=(.+)") - - with open(os.path.join(destination, "CMakeCache.txt"), "r") as cachefile: - try: - cachedata = cachefile.read() - if hostos == 'nt': - # fix path slashes on nt systems - newBinPath = re.sub(r"\\", r"/", newBinPath) - # replace old binaries path in CMakeCache.txt - cachedata = re.sub(re.search(replacePattern, cachedata).group(1), newBinPath, cachedata) - except Exception, e: - print "Reading error occurred:", str(e) - exit(e.errno) - - with open(os.path.join(destination, "CMakeCache.txt"), "w") as cachefile: - try: - cachefile.write(cachedata) - except Exception, e: - print "Writing error occurred:", str(e) - exit(e.errno) - exit() +import os, sys +import argparse +import logging +from run_utils import Err, CMakeCache, log, execute +from run_suite import TestSuite +from run_android import AndroidTestSuite + +epilog = ''' +NOTE: +Additional options starting with "--gtest_" and "--perf_" will be passed directly to the test executables. +''' if __name__ == "__main__": - test_args = [a for a in sys.argv if a.startswith("--perf_") or a.startswith("--gtest_")] - argv = [a for a in sys.argv if not(a.startswith("--perf_") or a.startswith("--gtest_"))] - parser = OptionParser(usage="run.py [options] [build_path]", description="Note: build_path is required if running not from CMake build directory") - parser.add_option("-t", "--tests", dest="tests", help="comma-separated list of modules to test", metavar="SUITS", default="") - if hostos == "nt": - parser.add_option("-m", "--move_tests", dest="move", help="location to move current tests build", metavar="PATH", default="") - parser.add_option("-w", "--cwd", dest="cwd", help="working directory for tests", metavar="PATH", default=".") - parser.add_option("-a", "--accuracy", dest="accuracy", help="look for accuracy tests instead of performance tests", action="store_true", default=False) - parser.add_option("-l", "--longname", dest="useLongNames", action="store_true", help="generate log files with long names", default=False) - parser.add_option("", "--android_test_data_path", dest="test_data_path", help="OPENCV_TEST_DATA_PATH for Android run", metavar="PATH", default="/sdcard/opencv_testdata/") - parser.add_option("", "--android_env", dest="android_env_array", help="Environment variable for Android run (NAME=VALUE)", action='append') - parser.add_option("", "--android_propagate_opencv_env", dest="android_propagate_opencv_env", help="Propagate OPENCV* environment variables for Android run", action="store_true", default=False) - parser.add_option("", "--configuration", dest="configuration", help="force Debug or Release configuration", metavar="CFG", default="") - parser.add_option("", "--serial", dest="adb_serial", help="Android: directs command to the USB device or emulator with the given serial number", metavar="serial number", default="") - parser.add_option("", "--package", dest="junit_package", help="Android: run jUnit tests for specified package", metavar="package", default="") - parser.add_option("", "--help-tests", dest="help", help="Show help for test executable", action="store_true", default=False) - parser.add_option("", "--check", dest="check", help="Shortcut for '--perf_min_samples=1 --perf_force_samples=1'", action="store_true", default=False) - parser.add_option("", "--list", dest="list", help="List available tests", action="store_true", default=False) + # log.basicConfig(format='[%(levelname)s] %(message)s', level = log.DEBUG) + # log.basicConfig(format='[%(levelname)s] %(message)s', level = log.INFO) - (options, args) = parser.parse_args(argv) + parser = argparse.ArgumentParser( + description='OpenCV test runner script', + epilog=epilog, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument("build_path", nargs = "*", default = ["."], help="Path to build directory (should contain CMakeCache.txt, default is current) or to directory with tests (all platform checks will be disabled in this case)") + parser.add_argument("-t", "--tests", metavar="MODULES", default="", help="Comma-separated list of modules to test (example: -t core,imgproc,java)") + parser.add_argument("-b", "--blacklist", metavar="MODULES", default="", help="Comma-separated list of modules to exclude from test (example: -b java)") + parser.add_argument("-a", "--accuracy", action="store_true", default=False, help="Look for accuracy tests instead of performance tests") + parser.add_argument("--check", action="store_true", default=False, help="Shortcut for '--perf_min_samples=1 --perf_force_samples=1'") + parser.add_argument("-w", "--cwd", metavar="PATH", default=".", help="Working directory for tests (default is current)") + parser.add_argument("-l", "--longname", action="store_true", default=False, help="Generate log files with long names") + parser.add_argument("--list", action="store_true", default=False, help="List available tests (executables)") + parser.add_argument("--list_short", action="store_true", default=False, help="List available tests (aliases)") + parser.add_argument("--list_short_main", action="store_true", default=False, help="List available tests (main repository, aliases)") + parser.add_argument("--configuration", metavar="CFG", default="", help="Visual Studio: force Debug or Release configuration") + parser.add_argument("-n", "--dry_run", action="store_true", help="Do not run the tests") + parser.add_argument("-v", "--verbose", action="store_true", default=False, help="Print more debug information") - if options.accuracy: - options.mode = "test" - else: - options.mode = "perf" + # Valgrind + parser.add_argument("--valgrind", action="store_true", default=False, help="Run C++ tests in valgrind") + parser.add_argument("--valgrind_supp", metavar="FILE", help="Path to valgrind suppression file (example: --valgrind_supp opencv/platforms/scripts/valgrind.supp)") + parser.add_argument("--valgrind_opt", metavar="OPT", action="append", default=[], help="Add command line option to valgrind (example: --valgrind_opt=--leak-check=full)") - run_args = getRunArgs(args[1:] or ['.']) + # Android + parser.add_argument("--android", action="store_true", default=False, help="Android: force all tests to run on device") + parser.add_argument("--android_sdk", metavar="PATH", help="Android: path to SDK to use adb and aapt tools") + parser.add_argument("--android_test_data_path", metavar="PATH", default="/sdcard/opencv_testdata/", help="Android: path to testdata on device") + parser.add_argument("--android_env", action='append', help="Android: add environment variable (NAME=VALUE)") + parser.add_argument("--android_propagate_opencv_env", action="store_true", default=False, help="Android: propagate OPENCV* environment variables") + parser.add_argument("--serial", metavar="serial number", default="", help="Android: directs command to the USB device or emulator with the given serial number") + parser.add_argument("--package", metavar="package", default="", help="Android: run jUnit tests for specified package") - if len(run_args) == 0: - print >> sys.stderr, "Usage:", os.path.basename(sys.argv[0]), "[options] [build_path]" - print >> sys.stderr, "Please specify build_path or run script from CMake build directory" + args, other_args = parser.parse_known_args() + + log.setLevel(logging.DEBUG if args.verbose else logging.INFO) + + test_args = [a for a in other_args if a.startswith("--perf_") or a.startswith("--gtest_")] + bad_args = [a for a in other_args if a not in test_args] + if len(bad_args) > 0: + log.error("Error: Bad arguments: %s", bad_args) exit(1) - options.android_env = {} - if options.android_env_array: - for entry in options.android_env_array: - k, v = entry.split("=", 1) - options.android_env[k] = v + args.mode = "test" if args.accuracy else "perf" - tests = [s.strip() for s in options.tests.split(",") if s] + android_env = [] + if args.android_env: + android_env.extend([entry.split("=", 1) for entry in args.android_env]) + if args.android_propagate_opencv_env: + android_env.extend([entry for entry in os.environ.items() if entry[0].startswith('OPENCV')]) + android_env = dict(android_env) + if args.android_test_data_path: + android_env['OPENCV_TEST_DATA_PATH'] = args.android_test_data_path - if len(tests) != 1 or len(run_args) != 1: - # remove --gtest_output from params + if args.valgrind: + try: + ver = execute(["valgrind", "--version"], silent=True) + log.debug("Using %s", ver) + except OSError as e: + log.error("Failed to run valgrind: %s", e) + exit(1) + + if len(args.build_path) != 1: test_args = [a for a in test_args if not a.startswith("--gtest_output=")] - if options.check: + if args.check: if not [a for a in test_args if a.startswith("--perf_min_samples=")] : test_args.extend(["--perf_min_samples=1"]) if not [a for a in test_args if a.startswith("--perf_force_samples=")] : @@ -942,26 +89,46 @@ if __name__ == "__main__": if not [a for a in test_args if a.startswith("--perf_verify_sanity")] : test_args.extend(["--perf_verify_sanity"]) + ret = 0 logs = [] - test_list = [] - for path in run_args: - suite = TestSuite(options, path) + for path in args.build_path: + try: + if not os.path.isdir(path): + raise Err("Not a directory (should contain CMakeCache.txt ot test executables)") + cache = CMakeCache() + fname = os.path.join(path, "CMakeCache.txt") - if hostos == "nt": - if(options.move): - moveTests(suite, options.move) - #print vars(suite),"\n" - if options.list: - test_list.extend(suite.tests) - else: - logs.extend(suite.runTests(tests, sys.stdout, sys.stderr, options.cwd, test_args)) + if os.path.isfile(fname): + log.debug("Reading cmake cache file: %s", fname) + cache.read(path, fname, args.configuration) + else: + log.debug("Assuming folder contains tests: %s", path) + cache.setDummy(path) - if options.list: - print os.linesep.join(test_list) or "No tests found" + if args.android or cache.getOS() == "android": + log.debug("Creating Android test runner") + suite = AndroidTestSuite(args, cache, android_env) + else: + log.debug("Creating native test runner") + suite = TestSuite(args, cache) + + if args.list or args.list_short or args.list_short_main: + suite.listTests(args.list_short or args.list_short_main, args.list_short_main) + else: + log.debug("Running tests in '%s', working dir: '%s'", path, args.cwd) + def parseTests(s): + return [o.strip() for o in s.split(",") if o] + l, r = suite.runTests(parseTests(args.tests), parseTests(args.blacklist), args.cwd, test_args) + logs.extend(l) + if r != 0: + ret = r + except Err as e: + log.error("ERROR: test path '%s' ==> %s", path, e.msg) + ret = -1 if logs: - print >> sys.stderr, "Collected: ", " ".join(logs) + log.warning("Collected: %s", ", ".join(logs)) - if errorCode != 0: - print "Error code: ", errorCode, (" (0x%x)" % (errorCode & 0xffffffff)) - exit(errorCode) + if ret != 0: + log.error("ERROR: some tests have failed") + exit(ret) diff --git a/modules/ts/misc/run_android.py b/modules/ts/misc/run_android.py new file mode 100644 index 000000000..d03721774 --- /dev/null +++ b/modules/ts/misc/run_android.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python + +import sys +from run_utils import * +from run_suite import TestSuite + +def exe(program): + return program + ".exe" if hostos == 'nt' else program + +class ApkInfo: + def __init__(self): + self.pkg_name = None + self.pkg_target = None + self.pkg_runner = None + + def forcePackage(self, package): + if package: + if package.startswith("."): + self.pkg_target += package + else: + self.pkg_target = package + +#============================================================================== + +class Tool: + def __init__(self): + self.cmd = [] + + def run(self, args = [], silent = False): + cmd = self.cmd[:] + cmd.extend(args) + return execute(self.cmd + args, silent) + + +#============================================================================== + +class Adb(Tool): + def __init__(self, sdk_dir): + Tool.__init__(self) + exe_path = os.path.join(sdk_dir, exe("platform-tools/adb")) + if not os.path.isfile(exe_path) or not os.access(exe_path, os.X_OK): + exe_path = None + # fix adb tool location + if not exe_path: + exe_path = getRunningProcessExePathByName("adb") + if not exe_path: + exe_path = "adb" + self.cmd = [exe_path] + self.cpuinfo = "" + + def init(self, serial): + # remember current device serial. Needed if another device is connected while this script runs + if not serial: + serial = self.detectSerial() + if serial: + self.cmd.extend(["-s", serial]) + # read device cpuinfo + self.cpuinfo = self.run(["shell", "cat /proc/cpuinfo"], silent = True) + if not self.cpuinfo: + raise Err("Can not get cpuinfo from Android device") + + def detectSerial(self): + adb_res = self.run(["devices"], silent = True) + # assume here that device name may consists of any characters except newline + connected_devices = re.findall(r"^[^\n]+[ \t]+device\r?$", adb_res, re.MULTILINE) + if not connected_devices: + raise Err("Can not find Android device") + elif len(connected_devices) != 1: + raise Err("Too many (%s) devices are connected. Please specify single device using --serial option:\n\n%s", len(connected_devices), adb_res) + else: + return connected_devices[0].split("\t")[0] + + def getOSIdentifier(self): + return "Android" + self.run(["shell", "getprop ro.build.version.release"], silent = True).strip() + + def getHardware(self): + hw = re.search(r"^Hardware[ \t]*:[ \t]*(.*?)$", self.cpuinfo, re.MULTILINE) + if hw: + return hw.group(1).strip() + + def checkArmHardware(self, expected_abi): + if expected_abi and "armeabi-v7a" in expected_abi: + if "ARMv7" not in self.cpuinfo: + raise Err("Android device does not support ARMv7 commands, but tests are built for armeabi-v7a") + if "NEON" in expected_abi and "neon" not in self.cpuinfo: + raise Err("Android device has no NEON, but tests are built for %s", expected_abi) + + +#============================================================================== + +class Aapt(Tool): + def __init__(self, sdk_dir): + Tool.__init__(self) + aapt_fn = exe("aapt") + aapt = None + for r, ds, fs in os.walk( os.path.join(sdk_dir, 'build-tools') ): + if aapt_fn in fs: + aapt = os.path.join(r, aapt_fn) + break + if not aapt: + raise Err("Can not find aapt tool: %s", aapt_fn) + self.cmd = [aapt] + + def dump(self, exe): + res = ApkInfo() + output = self.run(["dump", "xmltree", exe, "AndroidManifest.xml"], silent = True) + if not output: + raise Err("Can not dump manifest from %s", exe) + tags = re.split(r"[ ]+E: ", output) + # get package name + manifest_tag = [t for t in tags if t.startswith("manifest ")] + if not manifest_tag: + raise Err("Can not read package name from: %s", exe) + res.pkg_name = re.search(r"^[ ]+A: package=\"(?P.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", manifest_tag[0], flags=re.MULTILINE).group("pkg") + # get test instrumentation info + instrumentation_tag = [t for t in tags if t.startswith("instrumentation ")] + if not instrumentation_tag: + raise Err("Can not find instrumentation detials in: %s", exe) + res.pkg_runner = re.search(r"^[ ]+A: android:name\(0x[0-9a-f]{8}\)=\"(?P.*?)\" \(Raw: \"(?P=runner)\"\)\r?$", instrumentation_tag[0], flags=re.MULTILINE).group("runner") + res.pkg_target = re.search(r"^[ ]+A: android:targetPackage\(0x[0-9a-f]{8}\)=\"(?P.*?)\" \(Raw: \"(?P=pkg)\"\)\r?$", instrumentation_tag[0], flags=re.MULTILINE).group("pkg") + if not res.pkg_name or not res.pkg_runner or not res.pkg_target: + raise Err("Can not find instrumentation detials in: %s", exe) + return res + +#=================================================================================================== + +class AndroidTestSuite(TestSuite): + def __init__(self, options, cache, android_env = {}): + TestSuite.__init__(self, options, cache) + sdk_dir = options.android_sdk or os.environ.get("ANDROID_SDK", False) or os.path.dirname(os.path.dirname(self.cache.android_executable)) + log.debug("Detecting Android tools in directory: %s", sdk_dir) + self.adb = Adb(sdk_dir) + self.aapt = Aapt(sdk_dir) + self.env = android_env + + def isTest(self, fullpath): + if os.path.isfile(fullpath): + if fullpath.endswith(".apk") or os.access(fullpath, os.X_OK): + return True + return False + + def getOS(self): + return self.adb.getOSIdentifier() + + def getHardware(self): + return [self.adb.getHardware()] + + def checkPrerequisites(self): + self.adb.init(self.options.serial) + self.adb.checkArmHardware(self.cache.android_abi) + + def runTest(self, path, logfile, workingDir, args = []): + args = args[:] + exe = os.path.abspath(path) + + if exe.endswith(".apk"): + info = self.aapt.dump(exe) + if not info: + raise Err("Can not read info from test package: %s", exe) + info.forcePackage(self.options.package) + self.adb.run(["uninstall", info.pkg_name]) + + output = self.adb.run(["install", exe], silent = True) + if not (output and "Success" in output): + raise Err("Can not install package: %s", exe) + + params = ["-e package %s" % info.pkg_target] + ret = self.adb.run(["shell", "am instrument -w %s %s/%s" % (" ".join(params), info.pkg_name, info.pkg_runner)]) + return None, ret + else: + device_dir = getpass.getuser().replace(" ","") + "_" + self.options.mode +"/" + if isColorEnabled(args): + args.append("--gtest_color=yes") + tempdir = "/data/local/tmp/" + android_dir = tempdir + device_dir + exename = os.path.basename(exe) + android_exe = android_dir + exename + self.adb.run(["push", exe, android_exe]) + self.adb.run(["shell", "chmod 777 " + android_exe]) + env_pieces = ["export %s=%s" % (a,b) for a,b in self.env.items()] + pieces = ["cd %s" % android_dir, "./%s %s" % (exename, " ".join(args))] + log.warning("Run: %s" % " && ".join(pieces)) + ret = self.adb.run(["shell", " && ".join(env_pieces + pieces)]) + # try get log + hostlogpath = os.path.join(workingDir, logfile) + self.adb.run(["pull", android_dir + logfile, hostlogpath]) + # cleanup + self.adb.run(["shell", "rm " + android_dir + logfile]) + self.adb.run(["shell", "rm " + tempdir + "__opencv_temp.*"], silent = True) + if os.path.isfile(hostlogpath): + return hostlogpath, ret + return None, ret + +#=================================================================================================== + +if __name__ == "__main__": + log.error("This is utility file, please execute run.py script") diff --git a/modules/ts/misc/run_suite.py b/modules/ts/misc/run_suite.py new file mode 100644 index 000000000..c3d715e16 --- /dev/null +++ b/modules/ts/misc/run_suite.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python + +import datetime +from run_utils import * + +class TestSuite(object): + def __init__(self, options, cache): + self.options = options + self.cache = cache + self.nameprefix = "opencv_" + self.options.mode + "_" + self.tests = self.cache.gatherTests(self.nameprefix + "*", self.isTest) + + def getOS(self): + return getPlatformVersion() or self.cache.getOS() + + def getHardware(self): + res = [] + if self.cache.getArch() in ["x86", "x64"] and self.cache.withCuda(): + res.append("CUDA") + return res + + def getLogName(self, app, timestamp): + app = self.getAlias(app) + rev = self.cache.getGitVersion() + if isinstance(timestamp, datetime.datetime): + timestamp = timestamp.strftime("%Y%m%d-%H%M%S") + if self.options.longname: + small_pieces = [self.getOS(), self.cache.getArch()] + self.cache.getDependencies() + self.getHardware() + [self.cache.getSIMDFeatures()] + big_pieces = [app, str(rev), timestamp, "_".join([p for p in small_pieces if p])] + l = "__".join(big_pieces) + else: + pieces = [app, self.cache.getOS(), self.cache.getArch()] + self.getHardware() + [rev, timestamp] + lname = "_".join([p for p in pieces if p]) + lname = re.sub(r'[\(\)\[\]\s,]', '_', lname) + l = re.sub(r'_+', '_', lname) + return l + ".xml" + + def listTests(self, short = False, main = False): + if len(self.tests) == 0: + raise Err("No tests found") + for t in self.tests: + if short: + t = self.getAlias(t) + if not main or self.cache.isMainModule(t): + log.info("%s", t) + + def getAlias(self, fname): + return sorted(self.getAliases(fname), key = len)[0] + + def getAliases(self, fname): + # input is full path ('/home/.../bin/opencv_test_core') or 'java' + res = [fname] + fname = os.path.basename(fname) + res.append(fname) # filename (opencv_test_core.exe) + noext = re.sub(r"\.(exe|apk)$", '', fname) + res.append(noext) # filename w/o extension (opencv_test_core) + nopref = None + if fname.startswith(self.nameprefix): + nopref = fname[len(self.nameprefix):] + res.append(nopref) # filename w/o prefix (core) + if noext.startswith(self.nameprefix): + res.append(noext[len(self.nameprefix):]) + if self.options.configuration == "Debug": + res.append(re.sub(r"d$", '', noext)) # MSVC debug config, remove 'd' suffix + if nopref: + res.append(re.sub(r"d$", '', nopref)) # MSVC debug config, remove 'd' suffix + return set(res) + + def getTest(self, name): + # return stored test name by provided alias + for t in self.tests: + if name in self.getAliases(t): + return t + raise Err("Can not find test: %s", name) + + def getTestList(self, white, black): + res = [t for t in white or self.tests if self.getAlias(t) not in black] + if len(res) == 0: + raise Err("No tests found") + return set(res) + + def isTest(self, fullpath): + if fullpath == "java": + return True + if not os.path.isfile(fullpath): + return False + if self.cache.getOS() == "nt" and not fullpath.endswith(".exe"): + return False + return os.access(fullpath, os.X_OK) + + def wrapInValgrind(self, cmd = []): + if self.options.valgrind: + res = ['valgrind'] + if self.options.valgrind_supp: + res.append("--suppressions=%s" % self.options.valgrind_supp) + res.extend(self.options.valgrind_opt) + return res + cmd + return cmd + + def runTest(self, path, logfile, workingDir, args = []): + args = args[:] + exe = os.path.abspath(path) + if path == "java": + cfg = self.cache.build_type + if self.options.configuration: + cfg = self.options.configuration + cmd = [self.cache.ant_executable, "-Dopencv.build.type=%s" % cfg, "buildAndTest"] + ret = execute(cmd, cwd = self.cache.java_test_binary_dir + "/.build") + return None, ret + else: + if isColorEnabled(args): + args.append("--gtest_color=yes") + cmd = self.wrapInValgrind([exe] + args) + tempDir = TempEnvDir('OPENCV_TEMP_PATH', "__opencv_temp.") + tempDir.init() + log.warning("Run: %s" % " ".join(cmd)) + ret = execute(cmd, cwd = workingDir) + tempDir.clean() + hostlogpath = os.path.join(workingDir, logfile) + if os.path.isfile(hostlogpath): + return hostlogpath, ret + return None, ret + + def checkPrerequisites(self): + if self.cache.getArch() == "x64" and hostmachine == "x86": + raise Err("Target architecture is incompatible with current platform") + + def runTests(self, tests, black, workingDir, args = []): + self.checkPrerequisites() + args = args[:] + logs = [] + test_list = self.getTestList(tests, black) + date = datetime.datetime.now() + if len(test_list) != 1: + args = [a for a in args if not a.startswith("--gtest_output=")] + ret = 0 + for test in test_list: + more_args = [] + exe = self.getTest(test) + + userlog = [a for a in args if a.startswith("--gtest_output=")] + if len(userlog) == 0: + logname = self.getLogName(exe, date) + more_args.append("--gtest_output=xml:" + logname) + else: + logname = userlog[0][userlog[0].find(":")+1:] + + log.debug("Running the test: %s (%s) ==> %s in %s", exe, args + more_args, logname, workingDir) + if self.options.dry_run: + logfile, r = None, 0 + else: + logfile, r = self.runTest(exe, logname, workingDir, args + more_args) + log.debug("Test returned: %s ==> %s", r, logfile) + + if r != 0: + ret = r + if logfile: + logs.append(os.path.relpath(logfile, workingDir)) + return logs, ret + +#=================================================================================================== + +if __name__ == "__main__": + log.error("This is utility file, please execute run.py script") diff --git a/modules/ts/misc/run_utils.py b/modules/ts/misc/run_utils.py new file mode 100644 index 000000000..dca951d17 --- /dev/null +++ b/modules/ts/misc/run_utils.py @@ -0,0 +1,447 @@ +#!/usr/bin/env python + +import sys, os, platform, re, tempfile, glob, getpass, logging +from subprocess import check_call, check_output, CalledProcessError, STDOUT + +hostos = os.name # 'nt', 'posix' +hostmachine = platform.machine() # 'x86', 'AMD64', 'x86_64' + +def initLogger(): + l = logging.getLogger("run.py") + l.setLevel(logging.DEBUG) + ch = logging.StreamHandler(sys.stderr) + ch.setFormatter(logging.Formatter("%(message)s")) + l.addHandler(ch) + return l + +log = initLogger() + +#=================================================================================================== + +class Err(Exception): + def __init__(self, msg, *args): + self.msg = msg % args + +def execute(cmd, silent = False, cwd = "."): + try: + log.debug("Run: %s", cmd) + if silent: + return check_output(cmd, stderr = STDOUT, cwd = cwd).decode("latin-1") + else: + return check_call(cmd, cwd = cwd) + except CalledProcessError as e: + if silent: + log.debug("Process returned: %d", e.returncode) + return e.output.decode("latin-1") + else: + log.error("Process returned: %d", e.returncode) + return e.returncode + +def isColorEnabled(args): + usercolor = [a for a in args if a.startswith("--gtest_color=")] + return len(usercolor) == 0 and sys.stdout.isatty() and hostos != "nt" + +#=================================================================================================== + +def getPlatformVersion(): + mv = platform.mac_ver() + if mv[0]: + return "Darwin" + mv[0] + else: + wv = platform.win32_ver() + if wv[0]: + return "Windows" + wv[0] + else: + lv = platform.linux_distribution() + if lv[0]: + return lv[0] + lv[1] + return None + +def readGitVersion(git, path): + if not path or not git or not os.path.isdir(os.path.join(path, ".git")): + return None + try: + output = execute([git, "-C", path, "rev-parse", "--short", "HEAD"], silent = True) + return output.strip() + except OSError: + log.warning("Git version read failed") + return None + +SIMD_DETECTION_PROGRAM=""" +#if __SSE5__ +# error SSE5 +#endif +#if __AVX2__ +# error AVX2 +#endif +#if __AVX__ +# error AVX +#endif +#if __SSE4_2__ +# error SSE4.2 +#endif +#if __SSE4_1__ +# error SSE4.1 +#endif +#if __SSSE3__ +# error SSSE3 +#endif +#if __SSE3__ +# error SSE3 +#endif +#if __AES__ +# error AES +#endif +#if __SSE2__ +# error SSE2 +#endif +#if __SSE__ +# error SSE +#endif +#if __3dNOW__ +# error 3dNOW +#endif +#if __MMX__ +# error MMX +#endif +#if __ARM_NEON__ +# error NEON +#endif +#error NOSIMD +""" + +def testSIMD(compiler, cxx_flags, compiler_arg = None): + if not compiler: + return None + compiler_output = "" + try: + _, tmpfile = tempfile.mkstemp(suffix=".cpp", text = True) + with open(tmpfile, "w+") as fd: + fd.write(SIMD_DETECTION_PROGRAM) + options = [compiler] + if compiler_arg: + options.append(compiler_arg) + + prev_option = None + for opt in " ".join(cxx_flags).split(): + if opt.count('\"') % 2 == 1: + if prev_option is None: + prev_option = opt + else: + options.append(prev_option + " " + opt) + prev_option = None + elif prev_option is None: + options.append(opt) + else: + prev_option = prev_option + " " + opt + options.append(tmpfile) + compiler_output = execute(options, silent = True) + os.remove(tmpfile) + m = re.search("#error\W+(\w+)", compiler_output) + if m: + return m.group(1) + except OSError: + pass + log.debug("SIMD detection failed") + return None + +#============================================================================== + +parse_patterns = ( + {'name': "cmake_home", 'default': None, 'pattern': re.compile(r"^CMAKE_HOME_DIRECTORY:INTERNAL=(.+)$")}, + {'name': "opencv_home", 'default': None, 'pattern': re.compile(r"^OpenCV_SOURCE_DIR:STATIC=(.+)$")}, + {'name': "opencv_build", 'default': None, 'pattern': re.compile(r"^OpenCV_BINARY_DIR:STATIC=(.+)$")}, + {'name': "tests_dir", 'default': None, 'pattern': re.compile(r"^EXECUTABLE_OUTPUT_PATH:PATH=(.+)$")}, + {'name': "build_type", 'default': "Release", 'pattern': re.compile(r"^CMAKE_BUILD_TYPE:STRING=(.*)$")}, + {'name': "git_executable", 'default': None, 'pattern': re.compile(r"^GIT_EXECUTABLE:FILEPATH=(.*)$")}, + {'name': "cxx_flags", 'default': "", 'pattern': re.compile(r"^CMAKE_CXX_FLAGS:STRING=(.*)$")}, + {'name': "cxx_flags_debug", 'default': "", 'pattern': re.compile(r"^CMAKE_CXX_FLAGS_DEBUG:STRING=(.*)$")}, + {'name': "cxx_flags_release", 'default': "", 'pattern': re.compile(r"^CMAKE_CXX_FLAGS_RELEASE:STRING=(.*)$")}, + {'name': "opencv_cxx_flags", 'default': "", 'pattern': re.compile(r"^OPENCV_EXTRA_C_FLAGS:INTERNAL=(.*)$")}, + {'name': "cxx_flags_android", 'default': None, 'pattern': re.compile(r"^ANDROID_CXX_FLAGS:INTERNAL=(.*)$")}, + {'name': "android_abi", 'default': None, 'pattern': re.compile(r"^ANDROID_ABI:STRING=(.*)$")}, + {'name': "android_executable", 'default': None, 'pattern': re.compile(r"^ANDROID_EXECUTABLE:FILEPATH=(.*android.*)$")}, + {'name': "ant_executable", 'default': None, 'pattern': re.compile(r"^ANT_EXECUTABLE:FILEPATH=(.*ant.*)$")}, + {'name': "java_test_binary_dir", 'default': None, 'pattern': re.compile(r"^opencv_test_java_BINARY_DIR:STATIC=(.*)$")}, + {'name': "is_x64", 'default': "OFF", 'pattern': re.compile(r"^CUDA_64_BIT_DEVICE_CODE:BOOL=(ON)$")},#ugly( + {'name': "cmake_generator", 'default': None, 'pattern': re.compile(r"^CMAKE_GENERATOR:INTERNAL=(.+)$")}, + {'name': "cxx_compiler", 'default': None, 'pattern': re.compile(r"^CMAKE_CXX_COMPILER:\w*PATH=(.+)$")}, + {'name': "cxx_compiler_arg1", 'default': None, 'pattern': re.compile(r"^CMAKE_CXX_COMPILER_ARG1:[A-Z]+=(.+)$")}, + {'name': "with_cuda", 'default': "OFF", 'pattern': re.compile(r"^WITH_CUDA:BOOL=(ON)$")}, + {'name': "cuda_library", 'default': None, 'pattern': re.compile(r"^CUDA_CUDA_LIBRARY:FILEPATH=(.+)$")}, + {'name': "cuda_version", 'default': None, 'pattern': re.compile(r"^CUDA_VERSION:STRING=(.+)$")}, + {'name': "core_dependencies", 'default': None, 'pattern': re.compile(r"^opencv_core_LIB_DEPENDS:STATIC=(.+)$")}, +) + +class CMakeCache: + def __init__(self): + self.setDefaultAttrs() + self.cmake_home_vcver = None + self.opencv_home_vcver = None + self.featuresSIMD = None + self.main_modules = [] + + def setDummy(self, path): + self.tests_dir = os.path.normpath(path) + + def read(self, path, fname, cfg): + rx = re.compile(r'^opencv_(\w+)_SOURCE_DIR:STATIC=(.*)$') + module_paths = {} # name -> path + with open(fname, "rt") as cachefile: + for l in cachefile.readlines(): + ll = l.strip() + if not ll or ll.startswith("#"): + continue + for p in parse_patterns: + match = p["pattern"].match(ll) + if match: + value = match.groups()[0] + if value and not value.endswith("-NOTFOUND"): + setattr(self, p["name"], value) + # log.debug("cache value: %s = %s", p["name"], value) + + match = rx.search(ll) + if match: + module_paths[match.group(1)] = match.group(2) + + if not self.tests_dir: + self.tests_dir = path + else: + rel = os.path.relpath(self.tests_dir, self.opencv_build) + self.tests_dir = os.path.join(path, rel) + self.tests_dir = os.path.normpath(self.tests_dir) + + # fix VS test binary path (add Debug or Release) + if "Visual Studio" in self.cmake_generator: + if cfg: + self.tests_dir = os.path.join(self.tests_dir, self.options.configuration) + else: + self.tests_dir = os.path.join(self.tests_dir, self.build_type) + + self.cmake_home_vcver = readGitVersion(self.git_executable, self.cmake_home) + if self.opencv_home == self.cmake_home: + self.opencv_home_vcver = self.cmake_home_vcver + else: + self.opencv_home_vcver = readGitVersion(self.git_executable, self.opencv_home) + + for module,path in module_paths.items(): + rel = os.path.relpath(path, self.opencv_home) + if not ".." in rel: + self.main_modules.append(module) + + self.flags = [ + self.cxx_flags_android, + self.cxx_flags, + self.cxx_flags_release, + self.opencv_cxx_flags, + self.cxx_flags_release] + self.flags = [f for f in self.flags if f] + self.featuresSIMD = testSIMD(self.cxx_compiler, self.flags, self.cxx_compiler_arg1) + + def setDefaultAttrs(self): + for p in parse_patterns: + setattr(self, p["name"], p["default"]) + + def gatherTests(self, mask, isGood = None): + if self.tests_dir and os.path.isdir(self.tests_dir): + d = os.path.abspath(self.tests_dir) + files = glob.glob(os.path.join(d, mask)) + if not self.getOS() == "android" and self.withJava(): + files.append("java") + return [f for f in files if isGood(f)] + return [] + + def isMainModule(self, name): + return name in self.main_modules + + def withCuda(self): + return self.cuda_version and self.with_cuda == "ON" and self.cuda_library and not self.cuda_library.endswith("-NOTFOUND") + + def withJava(self): + return self.ant_executable and self.java_test_binary_dir + + def getGitVersion(self): + if self.cmake_home_vcver: + if self.cmake_home_vcver == self.opencv_home_vcver: + rev = self.cmake_home_vcver + elif self.opencv_home_vcver: + rev = self.cmake_home_vcver + "-" + self.opencv_home_vcver + else: + rev = self.cmake_home_vcver + else: + rev = None + if rev: + rev = rev.replace(":","to") + else: + rev = "" + return rev + + def getTestFullName(self, shortname): + return os.path.join(self.tests_dir, shortname) + + def getSIMDFeatures(self): + return self.featuresSIMD + + def getOS(self): + if self.android_executable: + return "android" + else: + return hostos + + def getArch(self): + arch = "unknown" + if self.getOS() == "android": + if "armeabi-v7a" in self.android_abi: + arch = "armv7a" + elif "armeabi-v6" in self.android_abi: + arch = "armv6" + elif "armeabi" in self.android_abi: + arch = "armv5te" + elif "x86" in self.android_abi: + arch = "x86" + elif "mips" in self.android_abi: + arch = "mips" + else: + arch = "ARM" + elif self.is_x64 and hostmachine in ["AMD64", "x86_64"]: + arch = "x64" + elif hostmachine in ["x86", "AMD64", "x86_64"]: + arch = "x86" + return arch + + def getDependencies(self): + if self.core_dependencies: + candidates = ["tbb", "ippicv", "ipp", "pthreads"] + return [a for a in self.core_dependencies.split(";") if a and a in candidates] + return [] + + +#============================================================================== + +def getRunningProcessExePathByName_win32(name): + from ctypes import windll, POINTER, pointer, Structure, sizeof + from ctypes import c_long , c_int , c_uint , c_char , c_ubyte , c_char_p , c_void_p + + class PROCESSENTRY32(Structure): + _fields_ = [ ( 'dwSize' , c_uint ) , + ( 'cntUsage' , c_uint) , + ( 'th32ProcessID' , c_uint) , + ( 'th32DefaultHeapID' , c_uint) , + ( 'th32ModuleID' , c_uint) , + ( 'cntThreads' , c_uint) , + ( 'th32ParentProcessID' , c_uint) , + ( 'pcPriClassBase' , c_long) , + ( 'dwFlags' , c_uint) , + ( 'szExeFile' , c_char * 260 ) , + ( 'th32MemoryBase' , c_long) , + ( 'th32AccessKey' , c_long ) ] + + class MODULEENTRY32(Structure): + _fields_ = [ ( 'dwSize' , c_long ) , + ( 'th32ModuleID' , c_long ), + ( 'th32ProcessID' , c_long ), + ( 'GlblcntUsage' , c_long ), + ( 'ProccntUsage' , c_long ) , + ( 'modBaseAddr' , c_long ) , + ( 'modBaseSize' , c_long ) , + ( 'hModule' , c_void_p ) , + ( 'szModule' , c_char * 256 ), + ( 'szExePath' , c_char * 260 ) ] + + TH32CS_SNAPPROCESS = 2 + TH32CS_SNAPMODULE = 0x00000008 + + ## CreateToolhelp32Snapshot + CreateToolhelp32Snapshot= windll.kernel32.CreateToolhelp32Snapshot + CreateToolhelp32Snapshot.reltype = c_long + CreateToolhelp32Snapshot.argtypes = [ c_int , c_int ] + ## Process32First + Process32First = windll.kernel32.Process32First + Process32First.argtypes = [ c_void_p , POINTER( PROCESSENTRY32 ) ] + Process32First.rettype = c_int + ## Process32Next + Process32Next = windll.kernel32.Process32Next + Process32Next.argtypes = [ c_void_p , POINTER(PROCESSENTRY32) ] + Process32Next.rettype = c_int + ## CloseHandle + CloseHandle = windll.kernel32.CloseHandle + CloseHandle.argtypes = [ c_void_p ] + CloseHandle.rettype = c_int + ## Module32First + Module32First = windll.kernel32.Module32First + Module32First.argtypes = [ c_void_p , POINTER(MODULEENTRY32) ] + Module32First.rettype = c_int + + hProcessSnap = c_void_p(0) + hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ) + + pe32 = PROCESSENTRY32() + pe32.dwSize = sizeof( PROCESSENTRY32 ) + ret = Process32First( hProcessSnap , pointer( pe32 ) ) + path = None + + while ret : + if name + ".exe" == pe32.szExeFile: + hModuleSnap = c_void_p(0) + me32 = MODULEENTRY32() + me32.dwSize = sizeof( MODULEENTRY32 ) + hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pe32.th32ProcessID ) + + ret = Module32First( hModuleSnap, pointer(me32) ) + path = me32.szExePath + CloseHandle( hModuleSnap ) + if path: + break + ret = Process32Next( hProcessSnap, pointer(pe32) ) + CloseHandle( hProcessSnap ) + return path + + +def getRunningProcessExePathByName_posix(name): + pids= [pid for pid in os.listdir('/proc') if pid.isdigit()] + for pid in pids: + try: + path = os.readlink(os.path.join('/proc', pid, 'exe')) + if path and path.endswith(name): + return path + except: + pass + +def getRunningProcessExePathByName(name): + try: + if hostos == "nt": + return getRunningProcessExePathByName_win32(name) + elif hostos == "posix": + return getRunningProcessExePathByName_posix(name) + else: + return None + except: + return None + + +class TempEnvDir: + def __init__(self, envname, prefix): + self.envname = envname + self.prefix = prefix + self.saved_name = None + self.new_name = None + + def init(self): + self.saved_name = os.environ.get(self.envname) + self.new_name = tempfile.mkdtemp(prefix=self.prefix, dir=self.saved_name or None) + os.environ[self.envname] = self.new_name + + def clean(self): + if self.saved_name: + os.environ[self.envname] = self.saved_name + else: + del os.environ[self.envname] + try: + shutil.rmtree(self.new_name) + except: + pass + +#=================================================================================================== + +if __name__ == "__main__": + log.error("This is utility file, please execute run.py script") diff --git a/modules/ts/src/ts_func.cpp b/modules/ts/src/ts_func.cpp index f5fed678d..b6409ad37 100644 --- a/modules/ts/src/ts_func.cpp +++ b/modules/ts/src/ts_func.cpp @@ -980,12 +980,12 @@ minMaxLoc_(const _Tp* src, size_t total, size_t startidx, for( size_t i = 0; i < total; i++ ) { _Tp val = src[i]; - if( minval > val ) + if( minval > val || !minpos ) { minval = val; minpos = startidx + i; } - if( maxval < val ) + if( maxval < val || !maxpos ) { maxval = val; maxpos = startidx + i; @@ -997,12 +997,12 @@ minMaxLoc_(const _Tp* src, size_t total, size_t startidx, for( size_t i = 0; i < total; i++ ) { _Tp val = src[i]; - if( minval > val && mask[i] ) + if( (minval > val || !minpos) && mask[i] ) { minval = val; minpos = startidx + i; } - if( maxval < val && mask[i] ) + if( (maxval < val || !maxpos) && mask[i] ) { maxval = val; maxpos = startidx + i; @@ -1049,8 +1049,8 @@ void minMaxLoc(const Mat& src, double* _minval, double* _maxval, size_t startidx = 1, total = planes[0].total(); size_t i, nplanes = it.nplanes; int depth = src.depth(); - double maxval = depth < CV_32F ? INT_MIN : depth == CV_32F ? -FLT_MAX : -DBL_MAX; - double minval = depth < CV_32F ? INT_MAX : depth == CV_32F ? FLT_MAX : DBL_MAX; + double minval = 0; + double maxval = 0; size_t maxidx = 0, minidx = 0; for( i = 0; i < nplanes; i++, ++it, startidx += total ) @@ -1093,9 +1093,6 @@ void minMaxLoc(const Mat& src, double* _minval, double* _maxval, } } - if( minidx == 0 ) - minval = maxval = 0; - if( _maxval ) *_maxval = maxval; if( _minval ) @@ -2954,6 +2951,9 @@ MatComparator::operator()(const char* expr1, const char* expr2, void printVersionInfo(bool useStdOut) { + // Tell CTest not to discard any output + if(useStdOut) std::cout << "CTEST_FULL_OUTPUT" << std::endl; + ::testing::Test::RecordProperty("cv_version", CV_VERSION); if(useStdOut) std::cout << "OpenCV version: " << CV_VERSION << std::endl; diff --git a/modules/ts/src/ts_perf.cpp b/modules/ts/src/ts_perf.cpp index ef8f0af9a..1a959f176 100644 --- a/modules/ts/src/ts_perf.cpp +++ b/modules/ts/src/ts_perf.cpp @@ -783,7 +783,7 @@ void TestBase::Init(const std::vector & availableImpls, ; cv::CommandLineParser args(argc, argv, command_line_keys); - if (args.has("help")) + if (args.get("help")) { args.printMessage(); return; @@ -791,7 +791,7 @@ void TestBase::Init(const std::vector & availableImpls, ::testing::AddGlobalTestEnvironment(new PerfEnvironment); - param_impl = args.has("perf_run_cpu") ? "plain" : args.get("perf_impl"); + param_impl = args.get("perf_run_cpu") ? "plain" : args.get("perf_impl"); std::string perf_strategy = args.get("perf_strategy"); if (perf_strategy == "default") { @@ -816,24 +816,22 @@ void TestBase::Init(const std::vector & availableImpls, param_seed = args.get("perf_seed"); param_time_limit = std::max(0., args.get("perf_time_limit")); param_force_samples = args.get("perf_force_samples"); - param_write_sanity = args.has("perf_write_sanity"); - param_verify_sanity = args.has("perf_verify_sanity"); + param_write_sanity = args.get("perf_write_sanity"); + param_verify_sanity = args.get("perf_verify_sanity"); -#ifndef WINRT - test_ipp_check = !args.has("perf_ipp_check") ? getenv("OPENCV_IPP_CHECK") != NULL : true; -#else - test_ipp_check = false; +#ifdef HAVE_IPP + test_ipp_check = !args.get("perf_ipp_check") ? getenv("OPENCV_IPP_CHECK") != NULL : true; #endif param_threads = args.get("perf_threads"); #ifdef CV_COLLECT_IMPL_DATA - param_collect_impl = args.has("perf_collect_impl"); + param_collect_impl = args.get("perf_collect_impl"); #endif #ifdef ANDROID param_affinity_mask = args.get("perf_affinity_mask"); log_power_checkpoints = args.has("perf_log_power_checkpoints"); #endif - bool param_list_impls = args.has("perf_list_impls"); + bool param_list_impls = args.get("perf_list_impls"); if (param_list_impls) { @@ -861,7 +859,7 @@ void TestBase::Init(const std::vector & availableImpls, #ifdef HAVE_CUDA - bool printOnly = args.has("perf_cuda_info_only"); + bool printOnly = args.get("perf_cuda_info_only"); if (printOnly) exit(0); @@ -916,7 +914,7 @@ void TestBase::Init(const std::vector & availableImpls, if (!args.check()) { args.printErrors(); - return; + exit(1); } timeLimitDefault = param_time_limit == 0.0 ? 1 : (int64)(param_time_limit * cv::getTickFrequency()); diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index 226af9dc0..5932d9c9e 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -787,7 +787,7 @@ bool BackgroundSubtractorMOG2Impl::ocl_apply(InputArray _image, OutputArray _fgm if (bShadowDetection) kernel_apply.set(idxArg, nShadowDetection); - size_t globalsize[] = {frame.cols, frame.rows, 1}; + size_t globalsize[] = {(size_t)frame.cols, (size_t)frame.rows, 1}; return kernel_apply.run(2, globalsize, NULL, true); } @@ -805,7 +805,7 @@ bool BackgroundSubtractorMOG2Impl::ocl_getBackgroundImage(OutputArray _backgroun idxArg = kernel_getBg.set(idxArg, ocl::KernelArg::WriteOnly(dst)); kernel_getBg.set(idxArg, backgroundRatio); - size_t globalsize[2] = {u_bgmodelUsedModes.cols, u_bgmodelUsedModes.rows}; + size_t globalsize[2] = {(size_t)u_bgmodelUsedModes.cols, (size_t)u_bgmodelUsedModes.rows}; return kernel_getBg.run(2, globalsize, NULL, false); } diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 43dde7df7..ccbedc534 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -976,7 +976,7 @@ namespace cv int ptcount, int level) { size_t localThreads[3] = { 8, 8}; - size_t globalThreads[3] = { 8 * ptcount, 8}; + size_t globalThreads[3] = { 8 * (size_t)ptcount, 8}; char calcErr = (0 == level) ? 1 : 0; cv::String build_options; @@ -1009,7 +1009,7 @@ namespace cv idxArg = kernel.set(idxArg, (int)winSize.height); // int c_winSize_y idxArg = kernel.set(idxArg, (int)iters); // int c_iters idxArg = kernel.set(idxArg, (char)calcErr); //char calcErr - return kernel.run(2, globalThreads, localThreads, false); + return kernel.run(2, globalThreads, localThreads, true); // sync=true because ocl::Image2D lifetime is not handled well for temp UMat } private: inline static bool isDeviceCPU() diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index 1d6524e30..740894619 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -845,7 +845,7 @@ private: #else size_t localsize[2] = { 256, 1}; #endif - size_t globalsize[2] = { src.cols, src.rows}; + size_t globalsize[2] = { (size_t)src.cols, (size_t)src.rows}; int smem_size = (int)((localsize[0] + 2*ksizeHalf) * sizeof(float)); ocl::Kernel kernel; if (!kernel.create("gaussianBlur", cv::ocl::video::optical_flow_farneback_oclsrc, "")) @@ -872,7 +872,7 @@ private: #else size_t localsize[2] = { 256, 1}; #endif - size_t globalsize[2] = { src.cols, height}; + size_t globalsize[2] = { (size_t)src.cols, (size_t)height}; int smem_size = (int)((localsize[0] + 2*ksizeHalf) * 5 * sizeof(float)); ocl::Kernel kernel; if (!kernel.create("gaussianBlur5", cv::ocl::video::optical_flow_farneback_oclsrc, "")) @@ -897,7 +897,7 @@ private: #else size_t localsize[2] = { 256, 1}; #endif - size_t globalsize[2] = { DIVUP(src.cols, localsize[0] - 2*polyN) * localsize[0], src.rows}; + size_t globalsize[2] = { DIVUP((size_t)src.cols, localsize[0] - 2*polyN) * localsize[0], (size_t)src.rows}; #if 0 const cv::ocl::Device &device = cv::ocl::Device::getDefault(); @@ -934,7 +934,7 @@ private: #else size_t localsize[2] = { 256, 1}; #endif - size_t globalsize[2] = { src.cols, height}; + size_t globalsize[2] = { (size_t)src.cols, (size_t)height}; ocl::Kernel kernel; if (!kernel.create("boxFilter5", cv::ocl::video::optical_flow_farneback_oclsrc, "")) @@ -961,7 +961,7 @@ private: #else size_t localsize[2] = { 32, 8}; #endif - size_t globalsize[2] = { flowx.cols, flowx.rows}; + size_t globalsize[2] = { (size_t)flowx.cols, (size_t)flowx.rows}; ocl::Kernel kernel; if (!kernel.create("updateFlow", cv::ocl::video::optical_flow_farneback_oclsrc, "")) @@ -985,7 +985,7 @@ private: #else size_t localsize[2] = { 32, 8}; #endif - size_t globalsize[2] = { flowx.cols, flowx.rows}; + size_t globalsize[2] = { (size_t)flowx.cols, (size_t)flowx.rows}; ocl::Kernel kernel; if (!kernel.create("updateMatrices", cv::ocl::video::optical_flow_farneback_oclsrc, "")) diff --git a/modules/video/src/tvl1flow.cpp b/modules/video/src/tvl1flow.cpp index 90fe48f47..1bbc12f0b 100644 --- a/modules/video/src/tvl1flow.cpp +++ b/modules/video/src/tvl1flow.cpp @@ -216,7 +216,7 @@ namespace cv_ocl_tvl1flow bool cv_ocl_tvl1flow::centeredGradient(const UMat &src, UMat &dx, UMat &dy) { - size_t globalsize[2] = { src.cols, src.rows }; + size_t globalsize[2] = { (size_t)src.cols, (size_t)src.rows }; ocl::Kernel kernel; if (!kernel.create("centeredGradientKernel", cv::ocl::video::optical_flow_tvl1_oclsrc, "")) @@ -237,7 +237,7 @@ bool cv_ocl_tvl1flow::warpBackward(const UMat &I0, const UMat &I1, UMat &I1x, UM UMat &u1, UMat &u2, UMat &I1w, UMat &I1wx, UMat &I1wy, UMat &grad, UMat &rho) { - size_t globalsize[2] = { I0.cols, I0.rows }; + size_t globalsize[2] = { (size_t)I0.cols, (size_t)I0.rows }; ocl::Kernel kernel; if (!kernel.create("warpBackwardKernel", cv::ocl::video::optical_flow_tvl1_oclsrc, "")) @@ -281,7 +281,7 @@ bool cv_ocl_tvl1flow::estimateU(UMat &I1wx, UMat &I1wy, UMat &grad, UMat &p21, UMat &p22, UMat &u1, UMat &u2, UMat &error, float l_t, float theta, char calc_error) { - size_t globalsize[2] = { I1wx.cols, I1wx.rows }; + size_t globalsize[2] = { (size_t)I1wx.cols, (size_t)I1wx.rows }; ocl::Kernel kernel; if (!kernel.create("estimateUKernel", cv::ocl::video::optical_flow_tvl1_oclsrc, "")) @@ -322,7 +322,7 @@ bool cv_ocl_tvl1flow::estimateU(UMat &I1wx, UMat &I1wy, UMat &grad, bool cv_ocl_tvl1flow::estimateDualVariables(UMat &u1, UMat &u2, UMat &p11, UMat &p12, UMat &p21, UMat &p22, float taut) { - size_t globalsize[2] = { u1.cols, u1.rows }; + size_t globalsize[2] = { (size_t)u1.cols, (size_t)u1.rows }; ocl::Kernel kernel; if (!kernel.create("estimateDualVariablesKernel", cv::ocl::video::optical_flow_tvl1_oclsrc, "")) diff --git a/modules/videoio/CMakeLists.txt b/modules/videoio/CMakeLists.txt index 2f5bed972..9e91a8a60 100644 --- a/modules/videoio/CMakeLists.txt +++ b/modules/videoio/CMakeLists.txt @@ -249,16 +249,16 @@ if(WIN32 AND WITH_FFMPEG) if(MSVC_IDE) add_custom_command(TARGET ${the_module} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Release/${ffmpeg_bare_name_ver}" - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Debug/${ffmpeg_bare_name_ver}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Release/${ffmpeg_bare_name_ver}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/Debug/${ffmpeg_bare_name_ver}" COMMENT "Copying ${ffmpeg_path} to the output directory") elseif(MSVC AND (CMAKE_GENERATOR MATCHES "Visual")) add_custom_command(TARGET ${the_module} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/${ffmpeg_bare_name_ver}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${CMAKE_BUILD_TYPE}/${ffmpeg_bare_name_ver}" COMMENT "Copying ${ffmpeg_path} to the output directory") else() add_custom_command(TARGET ${the_module} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${ffmpeg_bare_name_ver}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ffmpeg_path}" "${EXECUTABLE_OUTPUT_PATH}/${ffmpeg_bare_name_ver}" COMMENT "Copying ${ffmpeg_path} to the output directory") endif() diff --git a/modules/videoio/include/opencv2/videoio.hpp b/modules/videoio/include/opencv2/videoio.hpp index f37a8036c..503fd5be6 100644 --- a/modules/videoio/include/opencv2/videoio.hpp +++ b/modules/videoio/include/opencv2/videoio.hpp @@ -133,7 +133,9 @@ enum { CAP_PROP_POS_MSEC =0, CAP_PROP_TILT =34, CAP_PROP_ROLL =35, CAP_PROP_IRIS =36, - CAP_PROP_SETTINGS =37 + CAP_PROP_SETTINGS =37, + CAP_PROP_BUFFERSIZE =38, + CAP_PROP_AUTOFOCUS =39 }; diff --git a/modules/videoio/include/opencv2/videoio/cap_ios.h b/modules/videoio/include/opencv2/videoio/cap_ios.h index cf7f2e4ff..1a9875b25 100644 --- a/modules/videoio/include/opencv2/videoio/cap_ios.h +++ b/modules/videoio/include/opencv2/videoio/cap_ios.h @@ -71,6 +71,7 @@ @property (nonatomic, readonly) BOOL captureSessionLoaded; @property (nonatomic, assign) int defaultFPS; +@property (nonatomic, readonly) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer; @property (nonatomic, assign) AVCaptureDevicePosition defaultAVCaptureDevicePosition; @property (nonatomic, assign) AVCaptureVideoOrientation defaultAVCaptureVideoOrientation; @property (nonatomic, assign) BOOL useAVCaptureVideoPreviewLayer; @@ -145,6 +146,7 @@ - (void)layoutPreviewLayer; - (void)saveVideo; - (NSURL *)videoFileURL; +- (NSString *)videoFileString; @end diff --git a/modules/videoio/include/opencv2/videoio/videoio_c.h b/modules/videoio/include/opencv2/videoio/videoio_c.h index 0365b9223..ae0259fe7 100644 --- a/modules/videoio/include/opencv2/videoio/videoio_c.h +++ b/modules/videoio/include/opencv2/videoio/videoio_c.h @@ -189,6 +189,9 @@ enum CV_CAP_PROP_IRIS =36, CV_CAP_PROP_SETTINGS =37, CV_CAP_PROP_BUFFERSIZE =38, + CV_CAP_PROP_AUTOFOCUS =39, + CV_CAP_PROP_SAR_NUM =40, + CV_CAP_PROP_SAR_DEN =41, CV_CAP_PROP_AUTOGRAB =1024, // property for videoio class CvCapture_Android only CV_CAP_PROP_SUPPORTED_PREVIEW_SIZES_STRING=1025, // readonly, tricky property, returns cpnst char* indeed diff --git a/modules/videoio/src/cap_ffmpeg_api.hpp b/modules/videoio/src/cap_ffmpeg_api.hpp index e7a956063..0b7f45c8b 100644 --- a/modules/videoio/src/cap_ffmpeg_api.hpp +++ b/modules/videoio/src/cap_ffmpeg_api.hpp @@ -23,7 +23,9 @@ enum CV_FFMPEG_CAP_PROP_FRAME_HEIGHT=4, CV_FFMPEG_CAP_PROP_FPS=5, CV_FFMPEG_CAP_PROP_FOURCC=6, - CV_FFMPEG_CAP_PROP_FRAME_COUNT=7 + CV_FFMPEG_CAP_PROP_FRAME_COUNT=7, + CV_FFMPEG_CAP_PROP_SAR_NUM=40, + CV_FFMPEG_CAP_PROP_SAR_DEN=41 }; diff --git a/modules/videoio/src/cap_ffmpeg_impl.hpp b/modules/videoio/src/cap_ffmpeg_impl.hpp index 93c730a1b..ee1447e0f 100644 --- a/modules/videoio/src/cap_ffmpeg_impl.hpp +++ b/modules/videoio/src/cap_ffmpeg_impl.hpp @@ -127,12 +127,6 @@ extern "C" { #define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__) #endif -/* PIX_FMT_RGBA32 macro changed in newer ffmpeg versions */ -#ifndef PIX_FMT_RGBA32 -#define PIX_FMT_RGBA32 PIX_FMT_RGB32 -#endif - - #if defined WIN32 || defined _WIN32 #include #elif defined __linux__ || defined __APPLE__ @@ -166,6 +160,20 @@ extern "C" { # define CV_CODEC(name) name #endif +#if LIBAVUTIL_BUILD < (LIBAVUTIL_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(51, 74, 100) : CALC_FFMPEG_VERSION(51, 42, 0)) +#define AVPixelFormat PixelFormat +#define AV_PIX_FMT_BGR24 PIX_FMT_BGR24 +#define AV_PIX_FMT_RGB24 PIX_FMT_RGB24 +#define AV_PIX_FMT_GRAY8 PIX_FMT_GRAY8 +#define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P +#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P +#define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P +#define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P +#define AV_PIX_FMT_GRAY16LE PIX_FMT_GRAY16LE +#define AV_PIX_FMT_GRAY16BE PIX_FMT_GRAY16BE +#endif + static int get_number_of_cpus(void) { #if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(52, 111, 0) @@ -242,6 +250,7 @@ struct CvCapture_FFMPEG double get_duration_sec() const; double get_fps() const; int get_bitrate() const; + AVRational get_sample_aspect_ratio(AVStream *stream) const; double r2d(AVRational r) const; int64_t dts_to_frame_number(int64_t dts); @@ -311,8 +320,10 @@ void CvCapture_FFMPEG::close() if( picture ) { - // FFmpeg and Libav added avcodec_free_frame in different versions. #if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1)) + av_frame_free(&picture); +#elif LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \ ? CALC_FFMPEG_VERSION(54, 59, 100) : CALC_FFMPEG_VERSION(54, 28, 0)) avcodec_free_frame(&picture); #else @@ -576,6 +587,7 @@ bool CvCapture_FFMPEG::open( const char* _filename ) if (err < 0) { CV_WARN("Error opening file"); + CV_WARN(_filename); goto exit_func; } err = @@ -629,13 +641,18 @@ bool CvCapture_FFMPEG::open( const char* _filename ) video_stream = i; video_st = ic->streams[i]; +#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1)) + picture = av_frame_alloc(); +#else picture = avcodec_alloc_frame(); +#endif rgb_picture.data[0] = (uint8_t*)malloc( - avpicture_get_size( PIX_FMT_BGR24, + avpicture_get_size( AV_PIX_FMT_BGR24, enc->width, enc->height )); avpicture_fill( (AVPicture*)&rgb_picture, rgb_picture.data[0], - PIX_FMT_BGR24, enc->width, enc->height ); + AV_PIX_FMT_BGR24, enc->width, enc->height ); frame.width = enc->width; frame.height = enc->height; @@ -735,9 +752,6 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* if( !video_st || !picture->data[0] ) return false; - avpicture_fill((AVPicture*)&rgb_picture, rgb_picture.data[0], PIX_FMT_RGB24, - video_st->codec->width, video_st->codec->height); - if( img_convert_ctx == NULL || frame.width != video_st->codec->width || frame.height != video_st->codec->height ) @@ -753,15 +767,24 @@ bool CvCapture_FFMPEG::retrieveFrame(int, unsigned char** data, int* step, int* video_st->codec->width, video_st->codec->height, video_st->codec->pix_fmt, video_st->codec->width, video_st->codec->height, - PIX_FMT_BGR24, + AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL ); if (img_convert_ctx == NULL) return false;//CV_Error(0, "Cannot initialize the conversion context!"); + + rgb_picture.data[0] = (uint8_t*)realloc(rgb_picture.data[0], + avpicture_get_size( AV_PIX_FMT_BGR24, + video_st->codec->width, video_st->codec->height )); + frame.data = rgb_picture.data[0]; } + avpicture_fill((AVPicture*)&rgb_picture, rgb_picture.data[0], AV_PIX_FMT_RGB24, + video_st->codec->width, video_st->codec->height); + frame.step = rgb_picture.linesize[0]; + sws_scale( img_convert_ctx, picture->data, @@ -814,6 +837,10 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const #else return (double)video_st->codec.codec_tag; #endif + case CV_FFMPEG_CAP_PROP_SAR_NUM: + return get_sample_aspect_ratio(ic->streams[video_stream]).num; + case CV_FFMPEG_CAP_PROP_SAR_DEN: + return get_sample_aspect_ratio(ic->streams[video_stream]).den; default: break; } @@ -888,6 +915,28 @@ int64_t CvCapture_FFMPEG::dts_to_frame_number(int64_t dts) return (int64_t)(get_fps() * sec + 0.5); } +AVRational CvCapture_FFMPEG::get_sample_aspect_ratio(AVStream *stream) const +{ + AVRational undef = {0, 1}; + AVRational stream_sample_aspect_ratio = stream ? stream->sample_aspect_ratio : undef; + AVRational frame_sample_aspect_ratio = stream && stream->codec ? stream->codec->sample_aspect_ratio : undef; + + av_reduce(&stream_sample_aspect_ratio.num, &stream_sample_aspect_ratio.den, + stream_sample_aspect_ratio.num, stream_sample_aspect_ratio.den, INT_MAX); + if (stream_sample_aspect_ratio.num <= 0 || stream_sample_aspect_ratio.den <= 0) + stream_sample_aspect_ratio = undef; + + av_reduce(&frame_sample_aspect_ratio.num, &frame_sample_aspect_ratio.den, + frame_sample_aspect_ratio.num, frame_sample_aspect_ratio.den, INT_MAX); + if (frame_sample_aspect_ratio.num <= 0 || frame_sample_aspect_ratio.den <= 0) + frame_sample_aspect_ratio = undef; + + if (stream_sample_aspect_ratio.num) + return stream_sample_aspect_ratio; + else + return frame_sample_aspect_ratio; +} + double CvCapture_FFMPEG::dts_to_sec(int64_t dts) { return (double)(dts - ic->streams[video_stream]->start_time) * @@ -1107,10 +1156,20 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo uint8_t * picture_buf; int size; +#if LIBAVCODEC_BUILD >= (LIBAVCODEC_VERSION_MICRO >= 100 \ + ? CALC_FFMPEG_VERSION(55, 45, 101) : CALC_FFMPEG_VERSION(55, 28, 1)) + picture = av_frame_alloc(); +#else picture = avcodec_alloc_frame(); +#endif if (!picture) return NULL; - size = avpicture_get_size( (PixelFormat) pix_fmt, width, height); + + picture->format = pix_fmt; + picture->width = width; + picture->height = height; + + size = avpicture_get_size( (AVPixelFormat) pix_fmt, width, height); if(alloc){ picture_buf = (uint8_t *) malloc(size); if (!picture_buf) @@ -1119,7 +1178,7 @@ static AVFrame * icv_alloc_picture_FFMPEG(int pix_fmt, int width, int height, bo return NULL; } avpicture_fill((AVPicture *)picture, picture_buf, - (PixelFormat) pix_fmt, width, height); + (AVPixelFormat) pix_fmt, width, height); } else { } @@ -1227,7 +1286,7 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, #endif c->gop_size = 12; /* emit one intra frame every twelve frames at most */ - c->pix_fmt = (PixelFormat) pixel_format; + c->pix_fmt = (AVPixelFormat) pixel_format; if (c->codec_id == CV_CODEC(CODEC_ID_MPEG2VIDEO)) { c->max_b_frames = 2; @@ -1249,7 +1308,8 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc, c->gop_size = -1; c->qmin = -1; c->bit_rate = 0; - av_opt_set(c->priv_data,"crf","23", 0); + if (c->priv_data) + av_opt_set(c->priv_data,"crf","23", 0); } #endif @@ -1402,12 +1462,12 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int #endif // check parameters - if (input_pix_fmt == PIX_FMT_BGR24) { + if (input_pix_fmt == AV_PIX_FMT_BGR24) { if (cn != 3) { return false; } } - else if (input_pix_fmt == PIX_FMT_GRAY8) { + else if (input_pix_fmt == AV_PIX_FMT_GRAY8) { if (cn != 1) { return false; } @@ -1420,13 +1480,13 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int assert( input_picture ); // let input_picture point to the raw data buffer of 'image' avpicture_fill((AVPicture *)input_picture, (uint8_t *) data, - (PixelFormat)input_pix_fmt, width, height); + (AVPixelFormat)input_pix_fmt, width, height); if( !img_convert_ctx ) { img_convert_ctx = sws_getContext(width, height, - (PixelFormat)input_pix_fmt, + (AVPixelFormat)input_pix_fmt, c->width, c->height, c->pix_fmt, @@ -1444,7 +1504,7 @@ bool CvVideoWriter_FFMPEG::writeFrame( const unsigned char* data, int step, int } else{ avpicture_fill((AVPicture *)picture, (uint8_t *) data, - (PixelFormat)input_pix_fmt, width, height); + (AVPixelFormat)input_pix_fmt, width, height); } picture->pts = frame_idx; @@ -1601,10 +1661,10 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, /* determine optimal pixel format */ if (is_color) { - input_pix_fmt = PIX_FMT_BGR24; + input_pix_fmt = AV_PIX_FMT_BGR24; } else { - input_pix_fmt = PIX_FMT_GRAY8; + input_pix_fmt = AV_PIX_FMT_GRAY8; } /* Lookup codec_id for given fourcc */ @@ -1679,21 +1739,21 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc, break; #endif case CV_CODEC(CODEC_ID_HUFFYUV): - codec_pix_fmt = PIX_FMT_YUV422P; + codec_pix_fmt = AV_PIX_FMT_YUV422P; break; case CV_CODEC(CODEC_ID_MJPEG): case CV_CODEC(CODEC_ID_LJPEG): - codec_pix_fmt = PIX_FMT_YUVJ420P; + codec_pix_fmt = AV_PIX_FMT_YUVJ420P; bitrate_scale = 3; break; case CV_CODEC(CODEC_ID_RAWVIDEO): - codec_pix_fmt = input_pix_fmt == PIX_FMT_GRAY8 || - input_pix_fmt == PIX_FMT_GRAY16LE || - input_pix_fmt == PIX_FMT_GRAY16BE ? input_pix_fmt : PIX_FMT_YUV420P; + codec_pix_fmt = input_pix_fmt == AV_PIX_FMT_GRAY8 || + input_pix_fmt == AV_PIX_FMT_GRAY16LE || + input_pix_fmt == AV_PIX_FMT_GRAY16BE ? input_pix_fmt : AV_PIX_FMT_YUV420P; break; default: // good for lossy formats, MPEG, etc. - codec_pix_fmt = PIX_FMT_YUV420P; + codec_pix_fmt = AV_PIX_FMT_YUV420P; break; } @@ -1918,7 +1978,7 @@ struct OutputMediaStream_FFMPEG void write(unsigned char* data, int size, int keyFrame); // add a video output stream to the container - static AVStream* addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format); + static AVStream* addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, AVPixelFormat pixel_format); AVOutputFormat* fmt_; AVFormatContext* oc_; @@ -1965,7 +2025,7 @@ void OutputMediaStream_FFMPEG::close() } } -AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, PixelFormat pixel_format) +AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CV_CODEC_ID codec_id, int w, int h, int bitrate, double fps, AVPixelFormat pixel_format) { AVCodec* codec = avcodec_find_encoder(codec_id); if (!codec) @@ -2108,7 +2168,7 @@ bool OutputMediaStream_FFMPEG::open(const char* fileName, int width, int height, oc_->max_delay = (int)(0.7 * AV_TIME_BASE); // This reduces buffer underrun warnings with MPEG // set a few optimal pixel formats for lossless codecs of interest.. - PixelFormat codec_pix_fmt = PIX_FMT_YUV420P; + AVPixelFormat codec_pix_fmt = AV_PIX_FMT_YUV420P; int bitrate_scale = 64; // TODO -- safe to ignore output audio stream? @@ -2317,15 +2377,15 @@ bool InputMediaStream_FFMPEG::open(const char* fileName, int* codec, int* chroma switch (enc->pix_fmt) { - case PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV420P: *chroma_format = ::VideoChromaFormat_YUV420; break; - case PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV422P: *chroma_format = ::VideoChromaFormat_YUV422; break; - case PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV444P: *chroma_format = ::VideoChromaFormat_YUV444; break; diff --git a/modules/videoio/src/cap_gstreamer.cpp b/modules/videoio/src/cap_gstreamer.cpp index 9d74df6ea..4740126c0 100644 --- a/modules/videoio/src/cap_gstreamer.cpp +++ b/modules/videoio/src/cap_gstreamer.cpp @@ -146,7 +146,6 @@ protected: GstElement* sink; #if GST_VERSION_MAJOR > 0 GstSample* sample; - GstMapInfo* info; #endif GstBuffer* buffer; GstCaps* caps; @@ -169,7 +168,6 @@ void CvCapture_GStreamer::init() sink = NULL; #if GST_VERSION_MAJOR > 0 sample = NULL; - info = new GstMapInfo; #endif buffer = NULL; caps = NULL; @@ -318,17 +316,16 @@ IplImage * CvCapture_GStreamer::retrieveFrame(int) #if GST_VERSION_MAJOR == 0 frame->imageData = (char *)GST_BUFFER_DATA(buffer); #else - // the data ptr in GstMapInfo is only valid throughout the mapifo objects life. - // TODO: check if reusing the mapinfo object is ok. - - gboolean success = gst_buffer_map(buffer,info, (GstMapFlags)GST_MAP_READ); + // info.data ptr is valid until next grabFrame where the associated sample is unref'd + GstMapInfo info = GstMapInfo(); + gboolean success = gst_buffer_map(buffer,&info, (GstMapFlags)GST_MAP_READ); if (!success){ //something weird went wrong here. abort. abort. //fprintf(stderr,"GStreamer: unable to map buffer"); return 0; } - frame->imageData = (char*)info->data; - gst_buffer_unmap(buffer,info); + frame->imageData = (char*)info.data; + gst_buffer_unmap(buffer,&info); #endif return frame; @@ -604,6 +601,8 @@ bool CvCapture_GStreamer::open( int type, const char* filename ) else { CV_WARN("GStreamer: Error opening file\n"); + CV_WARN(filename); + CV_WARN(uri); close(); return false; } diff --git a/modules/videoio/src/cap_ios_video_camera.mm b/modules/videoio/src/cap_ios_video_camera.mm index 0acec6686..1ae70e298 100644 --- a/modules/videoio/src/cap_ios_video_camera.mm +++ b/modules/videoio/src/cap_ios_video_camera.mm @@ -41,7 +41,9 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} -@interface CvVideoCamera () +@interface CvVideoCamera () { + int recordingCountDown; +} - (void)createVideoDataOutput; - (void)createVideoFileOutput; @@ -98,6 +100,7 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} - (void)start; { + recordingCountDown = 10; [super start]; if (self.recordVideo == YES) { @@ -551,7 +554,8 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} }); - if (self.recordVideo == YES) { + recordingCountDown--; + if (self.recordVideo == YES && recordingCountDown < 0) { lastSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); // CMTimeShow(lastSampleTime); if (self.recordAssetWriter.status != AVAssetWriterStatusWriting) { @@ -571,6 +575,8 @@ static CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;} withPresentationTime:lastSampleTime] ) { NSLog(@"Video Writing Error"); } + if (pixelBuffer != nullptr) + CVPixelBufferRelease(pixelBuffer); } } diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index a879de7d5..fc9f6e06a 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -244,6 +244,7 @@ make & enjoy! /* Defaults - If your board can do better, set it here. Set for the most common type inputs. */ #define DEFAULT_V4L_WIDTH 640 #define DEFAULT_V4L_HEIGHT 480 +#define DEFAULT_V4L_FPS 30 #define CHANNEL_NUMBER 1 #define MAX_CAMERAS 8 @@ -271,33 +272,8 @@ struct buffer static unsigned int n_buffers = 0; -/* Additional V4L2 pixelformats support for Sonix SN9C10x base webcams */ -#ifndef V4L2_PIX_FMT_SBGGR8 -#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ -#endif -#ifndef V4L2_PIX_FMT_SN9C10X -#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S','9','1','0') /* SN9C10x cmpr. */ -#endif - -#ifndef V4L2_PIX_FMT_SGBRG -#define V4L2_PIX_FMT_SGBRG v4l2_fourcc('G','B','R','G') /* bayer GBRG GBGB.. RGRG.. */ -#endif - #endif /* HAVE_CAMV4L2 */ -enum PALETTE_TYPE { - PALETTE_BGR24 = 1, - PALETTE_YVU420, - PALETTE_YUV411P, - PALETTE_YUYV, - PALETTE_UYVY, - PALETTE_SBGGR8, - PALETTE_SN9C10X, - PALETTE_MJPEG, - PALETTE_SGBRG, - PALETTE_RGB24 -}; - typedef struct CvCaptureCAM_V4L { int deviceHandle; @@ -314,7 +290,13 @@ typedef struct CvCaptureCAM_V4L IplImage frame; #ifdef HAVE_CAMV4L2 - enum PALETTE_TYPE palette; + __u32 palette; + int index; + int width, height; + __u32 fps; + bool convert_rgb; + bool frame_allocated; + /* V4L2 variables */ buffer buffers[MAX_V4L_BUFFERS + 1]; struct v4l2_capability cap; @@ -330,13 +312,30 @@ typedef struct CvCaptureCAM_V4L struct timeval timestamp; /* V4L2 control variables */ - int v4l2_brightness, v4l2_brightness_min, v4l2_brightness_max; - int v4l2_contrast, v4l2_contrast_min, v4l2_contrast_max; - int v4l2_saturation, v4l2_saturation_min, v4l2_saturation_max; - int v4l2_hue, v4l2_hue_min, v4l2_hue_max; - int v4l2_gain, v4l2_gain_min, v4l2_gain_max; - int v4l2_exposure, v4l2_exposure_min, v4l2_exposure_max; + cv::Range focus, brightness, contrast, saturation, hue, gain, exposure; + cv::Range getRange(int property_id) { + switch (property_id) { + case CV_CAP_PROP_BRIGHTNESS: + return brightness; + case CV_CAP_PROP_CONTRAST: + return contrast; + case CV_CAP_PROP_SATURATION: + return saturation; + case CV_CAP_PROP_HUE: + return hue; + case CV_CAP_PROP_GAIN: + return gain; + case CV_CAP_PROP_EXPOSURE: + return exposure; + case CV_CAP_PROP_FOCUS: + return focus; + case CV_CAP_PROP_AUTOFOCUS: + return cv::Range(0, 1); + default: + return cv::Range(0, 255); + } + } #endif /* HAVE_CAMV4L2 */ } @@ -356,8 +355,6 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int ); static double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id ); static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value ); -static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h); - /*********************** Implementations ***************************************/ static int numCameras = 0; @@ -416,24 +413,20 @@ try_palette(int fd, #ifdef HAVE_CAMV4L2 -static int try_palette_v4l2(CvCaptureCAM_V4L* capture, unsigned long colorspace) +static bool try_palette_v4l2(CvCaptureCAM_V4L* capture) { CLEAR (capture->form); capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - capture->form.fmt.pix.pixelformat = colorspace; + capture->form.fmt.pix.pixelformat = capture->palette; capture->form.fmt.pix.field = V4L2_FIELD_ANY; - capture->form.fmt.pix.width = DEFAULT_V4L_WIDTH; - capture->form.fmt.pix.height = DEFAULT_V4L_HEIGHT; + capture->form.fmt.pix.width = capture->width; + capture->form.fmt.pix.height = capture->height; if (-1 == ioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) - return -1; + return false; - - if (colorspace != capture->form.fmt.pix.pixelformat) - return -1; - else - return 0; + return capture->palette == capture->form.fmt.pix.pixelformat; } #endif /* HAVE_CAMV4L2 */ @@ -541,67 +534,34 @@ static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName) } -static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) -{ - if (try_palette_v4l2(capture, V4L2_PIX_FMT_BGR24) == 0) - { - capture->palette = PALETTE_BGR24; - } - else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_YVU420) == 0) - { - capture->palette = PALETTE_YVU420; - } - else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUV411P) == 0) - { - capture->palette = PALETTE_YUV411P; - } - else - +static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) { + __u32 try_order[] = { + V4L2_PIX_FMT_BGR24, + V4L2_PIX_FMT_YVU420, + V4L2_PIX_FMT_YUV411P, #ifdef HAVE_JPEG - if (try_palette_v4l2(capture, V4L2_PIX_FMT_MJPEG) == 0 || - try_palette_v4l2(capture, V4L2_PIX_FMT_JPEG) == 0) - { - capture->palette = PALETTE_MJPEG; - } - else + V4L2_PIX_FMT_MJPEG, + V4L2_PIX_FMT_JPEG, #endif + V4L2_PIX_FMT_YUYV, + V4L2_PIX_FMT_UYVY, + V4L2_PIX_FMT_SN9C10X, + V4L2_PIX_FMT_SBGGR8, + V4L2_PIX_FMT_SGBRG8, + V4L2_PIX_FMT_RGB24 + }; - if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUYV) == 0) - { - capture->palette = PALETTE_YUYV; - } - else if (try_palette_v4l2(capture, V4L2_PIX_FMT_UYVY) == 0) - { - capture->palette = PALETTE_UYVY; - } - else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_SN9C10X) == 0) - { - capture->palette = PALETTE_SN9C10X; - } else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_SBGGR8) == 0) - { - capture->palette = PALETTE_SBGGR8; - } else - if (try_palette_v4l2(capture, V4L2_PIX_FMT_SGBRG) == 0) - { - capture->palette = PALETTE_SGBRG; - } - else if (try_palette_v4l2(capture, V4L2_PIX_FMT_RGB24) == 0) - { - capture->palette = PALETTE_RGB24; - } - else - { - fprintf(stderr, "VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n"); + for (size_t i = 0; i < sizeof(try_order) / sizeof(__u32); i++) { + capture->palette = try_order[i]; + if (try_palette_v4l2(capture)) { + return 0; + } + } + + fprintf(stderr, + "VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n"); icvCloseCAM_V4L(capture); return -1; - } - - return 0; - } #endif /* HAVE_CAMV4L2 */ @@ -645,158 +605,122 @@ static int autosetup_capture_mode_v4l(CvCaptureCAM_V4L* capture) #ifdef HAVE_CAMV4L2 +static void v4l2_control_range(CvCaptureCAM_V4L* cap, __u32 id) +{ + CLEAR (cap->queryctrl); + cap->queryctrl.id = id; + + if(0 != ioctl(cap->deviceHandle, VIDIOC_QUERYCTRL, &cap->queryctrl)) + { + if (errno != EINVAL) + perror ("VIDIOC_QUERYCTRL"); + return; + } + + if (cap->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) + return; + + cv::Range range(cap->queryctrl.minimum, cap->queryctrl.maximum); + + switch(cap->queryctrl.id) { + case V4L2_CID_BRIGHTNESS: + cap->brightness = range; + break; + case V4L2_CID_CONTRAST: + cap->contrast = range; + break; + case V4L2_CID_SATURATION: + cap->saturation = range; + break; + case V4L2_CID_HUE: + cap->hue = range; + break; + case V4L2_CID_GAIN: + cap->gain = range; + break; + case V4L2_CID_EXPOSURE: + cap->exposure = range; + break; + case V4L2_CID_FOCUS_ABSOLUTE: + cap->focus = range; + break; + } +} static void v4l2_scan_controls(CvCaptureCAM_V4L* capture) { __u32 ctrl_id; - for (ctrl_id = V4L2_CID_BASE; - ctrl_id < V4L2_CID_LASTP1; - ctrl_id++) + for (ctrl_id = V4L2_CID_BASE; ctrl_id < V4L2_CID_LASTP1; ctrl_id++) { - - /* set the id we will query now */ - CLEAR (capture->queryctrl); - capture->queryctrl.id = ctrl_id; - - if (0 == ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL, - &capture->queryctrl)) - { - - if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) - continue; - - if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS) - { - capture->v4l2_brightness = 1; - capture->v4l2_brightness_min = capture->queryctrl.minimum; - capture->v4l2_brightness_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_CONTRAST) - { - capture->v4l2_contrast = 1; - capture->v4l2_contrast_min = capture->queryctrl.minimum; - capture->v4l2_contrast_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_SATURATION) - { - capture->v4l2_saturation = 1; - capture->v4l2_saturation_min = capture->queryctrl.minimum; - capture->v4l2_saturation_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_HUE) - { - capture->v4l2_hue = 1; - capture->v4l2_hue_min = capture->queryctrl.minimum; - capture->v4l2_hue_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_GAIN) - { - capture->v4l2_gain = 1; - capture->v4l2_gain_min = capture->queryctrl.minimum; - capture->v4l2_gain_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_EXPOSURE) - { - capture->v4l2_exposure = 1; - capture->v4l2_exposure_min = capture->queryctrl.minimum; - capture->v4l2_exposure_max = capture->queryctrl.maximum; - } - - - } else { - - if (errno == EINVAL) - continue; - - perror ("VIDIOC_QUERYCTRL"); - - } - + v4l2_control_range(capture, ctrl_id); } for (ctrl_id = V4L2_CID_PRIVATE_BASE;;ctrl_id++) { - - /* set the id we will query now */ - CLEAR (capture->queryctrl); - capture->queryctrl.id = ctrl_id; - - if (0 == ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL, - &capture->queryctrl)) - { - - if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) - continue; - - if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS) - { - capture->v4l2_brightness = 1; - capture->v4l2_brightness_min = capture->queryctrl.minimum; - capture->v4l2_brightness_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_CONTRAST) - { - capture->v4l2_contrast = 1; - capture->v4l2_contrast_min = capture->queryctrl.minimum; - capture->v4l2_contrast_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_SATURATION) - { - capture->v4l2_saturation = 1; - capture->v4l2_saturation_min = capture->queryctrl.minimum; - capture->v4l2_saturation_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_HUE) - { - capture->v4l2_hue = 1; - capture->v4l2_hue_min = capture->queryctrl.minimum; - capture->v4l2_hue_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_GAIN) - { - capture->v4l2_gain = 1; - capture->v4l2_gain_min = capture->queryctrl.minimum; - capture->v4l2_gain_max = capture->queryctrl.maximum; - } - - if (capture->queryctrl.id == V4L2_CID_EXPOSURE) - { - capture->v4l2_exposure = 1; - capture->v4l2_exposure_min = capture->queryctrl.minimum; - capture->v4l2_exposure_max = capture->queryctrl.maximum; - } - - } else { + v4l2_control_range(capture, ctrl_id); if (errno == EINVAL) break; - - perror ("VIDIOC_QUERYCTRL"); - - } - } + v4l2_control_range(capture, V4L2_CID_FOCUS_ABSOLUTE); } -static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) +static int v4l2_set_fps(CvCaptureCAM_V4L* capture) { + v4l2_streamparm setfps; + CLEAR(setfps); + setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + setfps.parm.capture.timeperframe.numerator = 1; + setfps.parm.capture.timeperframe.denominator = capture->fps; + return ioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps); +} + +static int v4l2_num_channels(__u32 palette) { + switch(palette) { + case V4L2_PIX_FMT_MJPEG: + case V4L2_PIX_FMT_JPEG: + return 1; + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_UYVY: + return 2; + default: + return 0; + } +} + +static void v4l2_create_frame(CvCaptureCAM_V4L *capture) { + CvSize size(capture->form.fmt.pix.width, capture->form.fmt.pix.height); + int channels = 3; + + if (!capture->convert_rgb) { + if (capture->palette == V4L2_PIX_FMT_MJPEG || capture->palette == V4L2_PIX_FMT_JPEG) { + size = CvSize(capture->buffers[capture->bufferIndex].length, 1); + } + channels = v4l2_num_channels(capture->palette); + } + + /* Set up Image data */ + cvInitImageHeader(&capture->frame, size, IPL_DEPTH_8U, channels); + + /* Allocate space for pixelformat we convert to. + * If we do not convert frame is just points to the buffer + */ + if(capture->convert_rgb) { + capture->frame.imageData = (char*)cvAlloc(capture->frame.imageSize); + } + + capture->frame_allocated = capture->convert_rgb; +} + +static int _capture_V4L2 (CvCaptureCAM_V4L *capture) { - int detect_v4l2 = 0; + char deviceName[MAX_DEVICE_DRIVER_NAME]; + /* Print the CameraNumber at the end of the string with a width of one character */ + sprintf(deviceName, "/dev/video%1d", capture->index); - detect_v4l2 = try_init_v4l2(capture, deviceName); - - if (detect_v4l2 != 1) { + if (try_init_v4l2(capture, deviceName) != 1) { /* init of the v4l2 device is not OK */ return -1; } @@ -804,30 +728,7 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) /* starting from here, we assume we are in V4L2 mode */ V4L2_SUPPORT = 1; - /* Init V4L2 control variables */ - capture->v4l2_brightness = 0; - capture->v4l2_contrast = 0; - capture->v4l2_saturation = 0; - capture->v4l2_hue = 0; - capture->v4l2_gain = 0; - capture->v4l2_exposure = 0; - - capture->v4l2_brightness_min = 0; - capture->v4l2_contrast_min = 0; - capture->v4l2_saturation_min = 0; - capture->v4l2_hue_min = 0; - capture->v4l2_gain_min = 0; - capture->v4l2_exposure_min = 0; - - capture->v4l2_brightness_max = 0; - capture->v4l2_contrast_max = 0; - capture->v4l2_saturation_max = 0; - capture->v4l2_hue_max = 0; - capture->v4l2_gain_max = 0; - capture->v4l2_exposure_max = 0; - - capture->timestamp.tv_sec = 0; - capture->timestamp.tv_usec = 0; + /* V4L2 control variables are zero (memset above) */ /* Scan V4L2 controls */ v4l2_scan_controls(capture); @@ -869,14 +770,11 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) return -1; } - if (V4L2_SUPPORT == 0) - { - } - if (autosetup_capture_mode_v4l2(capture) == -1) return -1; - icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT); + /* try to set framerate */ + v4l2_set_fps(capture); unsigned int min; @@ -971,17 +869,24 @@ static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName) } } - /* Set up Image data */ - cvInitImageHeader( &capture->frame, - cvSize( capture->form.fmt.pix.width, - capture->form.fmt.pix.height ), - IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 ); - /* Allocate space for RGBA data */ - capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize); + v4l2_create_frame(capture); + + // reinitialize buffers + capture->FirstCapture = 1; return 1; }; /* End _capture_V4L2 */ +/** + * some properties can not be changed while the device is in streaming mode. + * this method closes and re-opens the device to re-start the stream. + * this also causes buffers to be reallocated if the frame size was changed. + */ +static int v4l2_reset( CvCaptureCAM_V4L* capture) { + icvCloseCAM_V4L(capture); + return _capture_V4L2(capture); +} + #endif /* HAVE_CAMV4L2 */ #ifdef HAVE_CAMV4L @@ -1111,8 +1016,6 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) static int autoindex; autoindex = 0; - char deviceName[MAX_DEVICE_DRIVER_NAME]; - if (!numCameras) icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */ if (!numCameras) @@ -1141,8 +1044,7 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) index=autoindex; autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera } - /* Print the CameraNumber at the end of the string with a width of one character */ - sprintf(deviceName, "/dev/video%1d", index); + capture->index = index; /* w/o memset some parts arent initialized - AKA: Fill it with zeros so it is clean */ memset(capture,0,sizeof(CvCaptureCAM_V4L)); @@ -1151,19 +1053,26 @@ static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index) capture->FirstCapture = 1; #ifdef HAVE_CAMV4L2 - if (_capture_V4L2 (capture, deviceName) == -1) { + capture->width = DEFAULT_V4L_WIDTH; + capture->height = DEFAULT_V4L_HEIGHT; + capture->fps = DEFAULT_V4L_FPS; + capture->convert_rgb = true; + + if (_capture_V4L2 (capture) == -1) { icvCloseCAM_V4L(capture); V4L2_SUPPORT = 0; #endif /* HAVE_CAMV4L2 */ #ifdef HAVE_CAMV4L + char deviceName[MAX_DEVICE_DRIVER_NAME]; + /* Print the CameraNumber at the end of the string with a width of one character */ + sprintf(deviceName, "/dev/video%1d", capture->index); + if (_capture_V4L (capture, deviceName) == -1) { icvCloseCAM_V4L(capture); return NULL; } #endif /* HAVE_CAMV4L */ #ifdef HAVE_CAMV4L2 - } else { - V4L2_SUPPORT = 1; } #endif /* HAVE_CAMV4L2 */ @@ -1642,49 +1551,10 @@ yuv411p_to_rgb24(int width, int height, #ifdef HAVE_CAMV4L2 static void -yuyv_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst) -{ - unsigned char *s; - unsigned char *d; - int l, c; - int r, g, b, cr, cg, cb, y1, y2; - - l = height; - s = src; - d = dst; - while (l--) { - c = width >> 1; - while (c--) { - y1 = *s++; - cb = ((*s - 128) * 454) >> 8; - cg = (*s++ - 128) * 88; - y2 = *s++; - cr = ((*s - 128) * 359) >> 8; - cg = (cg + (*s++ - 128) * 183) >> 8; - - r = y1 + cr; - b = y1 + cb; - g = y1 - cg; - SAT(r); - SAT(g); - SAT(b); - - *d++ = b; - *d++ = g; - *d++ = r; - - r = y2 + cr; - b = y2 + cb; - g = y2 - cg; - SAT(r); - SAT(g); - SAT(b); - - *d++ = b; - *d++ = g; - *d++ = r; - } - } +yuyv_to_rgb24(int width, int height, unsigned char* src, unsigned char* dst) { + using namespace cv; + cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst), + COLOR_YUV2BGR_YUYV); } static void @@ -1738,15 +1608,11 @@ uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst) /* convert from mjpeg to rgb24 */ static bool -mjpeg_to_rgb24 (int width, int height, - unsigned char *src, int length, - unsigned char *dst) -{ - cv::Mat temp=cv::imdecode(cv::Mat(std::vector(src, src + length)), 1); - if( !temp.data || temp.cols != width || temp.rows != height ) - return false; - memcpy(dst, temp.data, width*height*3); - return true; +mjpeg_to_rgb24(int width, int height, unsigned char* src, int length, IplImage* dst) { + using namespace cv; + Mat temp = cvarrToMat(dst); + imdecode(Mat(1, length, CV_8U, src), IMREAD_COLOR, &temp); + return temp.data && temp.cols == width && temp.rows == height; } #endif @@ -2108,18 +1974,16 @@ static int sonix_decompress(int width, int height, unsigned char *inp, unsigned static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { #ifdef HAVE_CAMV4L2 - if (V4L2_SUPPORT == 0) -#endif /* HAVE_CAMV4L2 */ #ifdef HAVE_CAMV4L + if (V4L2_SUPPORT == 0) { - /* [FD] this really belongs here */ if (ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) { fprintf( stderr, "VIDEOIO ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno)); } - } #endif /* HAVE_CAMV4L */ +#endif /* HAVE_CAMV4L2 */ /* Now get what has already been captured as a IplImage return */ @@ -2129,15 +1993,19 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { if (V4L2_SUPPORT == 1) { + // we need memory iff convert_rgb is true + bool recreate_frame = capture->frame_allocated != capture->convert_rgb; - if(((unsigned long)capture->frame.width != capture->form.fmt.pix.width) - || ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) { - cvFree(&capture->frame.imageData); - cvInitImageHeader( &capture->frame, - cvSize( capture->form.fmt.pix.width, - capture->form.fmt.pix.height ), - IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 ); - capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize); + if (!capture->convert_rgb) { + // for mjpeg streams the size might change in between, so we have to change the header + recreate_frame += capture->frame.imageSize != (int)capture->buffers[capture->bufferIndex].length; + } + + if(recreate_frame) { + // printf("realloc %d %zu\n", capture->frame.imageSize, capture->buffers[capture->bufferIndex].length); + if(capture->frame_allocated) + cvFree(&capture->frame.imageData); + v4l2_create_frame(capture); } } @@ -2165,59 +2033,65 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { if (V4L2_SUPPORT == 1) { + if(!capture->convert_rgb) { + capture->frame.imageData = (char*)capture->buffers[capture->bufferIndex].start; + return &capture->frame; + } + switch (capture->palette) { - case PALETTE_BGR24: + case V4L2_PIX_FMT_BGR24: memcpy((char *)capture->frame.imageData, (char *)capture->buffers[capture->bufferIndex].start, capture->frame.imageSize); break; - case PALETTE_YVU420: + case V4L2_PIX_FMT_YVU420: yuv420p_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; - case PALETTE_YUV411P: + case V4L2_PIX_FMT_YUV411P: yuv411p_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; #ifdef HAVE_JPEG - case PALETTE_MJPEG: + case V4L2_PIX_FMT_MJPEG: + case V4L2_PIX_FMT_JPEG: if (!mjpeg_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex] .start), capture->buffers[capture->bufferIndex].length, - (unsigned char*)capture->frame.imageData)) + &capture->frame)) return 0; break; #endif - case PALETTE_YUYV: + case V4L2_PIX_FMT_YUYV: yuyv_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; - case PALETTE_UYVY: + case V4L2_PIX_FMT_UYVY: uyvy_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)(capture->buffers[capture->bufferIndex].start), (unsigned char*)capture->frame.imageData); break; - case PALETTE_SBGGR8: + case V4L2_PIX_FMT_SBGGR8: bayer2rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)capture->buffers[capture->bufferIndex].start, (unsigned char*)capture->frame.imageData); break; - case PALETTE_SN9C10X: + case V4L2_PIX_FMT_SN9C10X: sonix_decompress_init(); sonix_decompress(capture->form.fmt.pix.width, capture->form.fmt.pix.height, @@ -2230,13 +2104,13 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { (unsigned char*)capture->frame.imageData); break; - case PALETTE_SGBRG: + case V4L2_PIX_FMT_SGBRG8: sgbrg2rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start, (unsigned char*)capture->frame.imageData); break; - case PALETTE_RGB24: + case V4L2_PIX_FMT_RGB24: rgb24_to_rgb24(capture->form.fmt.pix.width, capture->form.fmt.pix.height, (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start, @@ -2290,6 +2164,31 @@ static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) { return(&capture->frame); } +static inline __u32 capPropertyToV4L2(int prop) { + switch (prop) { +#ifdef HAVE_CAMV4L2 + case CV_CAP_PROP_BRIGHTNESS: + return V4L2_CID_BRIGHTNESS; + case CV_CAP_PROP_CONTRAST: + return V4L2_CID_CONTRAST; + case CV_CAP_PROP_SATURATION: + return V4L2_CID_SATURATION; + case CV_CAP_PROP_HUE: + return V4L2_CID_HUE; + case CV_CAP_PROP_GAIN: + return V4L2_CID_GAIN; + case CV_CAP_PROP_EXPOSURE: + return V4L2_CID_EXPOSURE; + case CV_CAP_PROP_AUTOFOCUS: + return V4L2_CID_FOCUS_AUTO; + case CV_CAP_PROP_FOCUS: + return V4L2_CID_FOCUS_ABSOLUTE; +#endif + default: + return -1; + } +} + static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, int property_id ) { @@ -2299,11 +2198,6 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, if (V4L2_SUPPORT == 1) #endif { - - /* default value for min and max */ - int v4l2_min = 0; - int v4l2_max = 255; - CLEAR (capture->form); capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) { @@ -2317,43 +2211,48 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, return capture->form.fmt.pix.width; case CV_CAP_PROP_FRAME_HEIGHT: return capture->form.fmt.pix.height; + case CV_CAP_PROP_FOURCC: + case CV_CAP_PROP_MODE: + return capture->palette; + case CV_CAP_PROP_FORMAT: + return CV_8UC3; + case CV_CAP_PROP_CONVERT_RGB: + return capture->convert_rgb; + } + + if(property_id == CV_CAP_PROP_FPS) { + struct v4l2_streamparm sp; + CLEAR(sp); + sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl(capture->deviceHandle, VIDIOC_G_PARM, &sp) < 0){ + fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to get camera FPS\n"); + return -1; + } + + return sp.parm.capture.timeperframe.denominator / (double)sp.parm.capture.timeperframe.numerator; } /* initialize the control structure */ - switch (property_id) { - case CV_CAP_PROP_POS_MSEC: + if(property_id == CV_CAP_PROP_POS_MSEC) { if (capture->FirstCapture) { return 0; } else { return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000; } - break; - case CV_CAP_PROP_BRIGHTNESS: - capture->control.id = V4L2_CID_BRIGHTNESS; - break; - case CV_CAP_PROP_CONTRAST: - capture->control.id = V4L2_CID_CONTRAST; - break; - case CV_CAP_PROP_SATURATION: - capture->control.id = V4L2_CID_SATURATION; - break; - case CV_CAP_PROP_HUE: - capture->control.id = V4L2_CID_HUE; - break; - case CV_CAP_PROP_GAIN: - capture->control.id = V4L2_CID_GAIN; - break; - case CV_CAP_PROP_EXPOSURE: - capture->control.id = V4L2_CID_EXPOSURE; - break; - default: - fprintf(stderr, - "VIDEOIO ERROR: V4L2: getting property #%d is not supported\n", - property_id); - return -1; } + __u32 v4l2id = capPropertyToV4L2(property_id); + + if(v4l2id == __u32(-1)) { + fprintf(stderr, + "VIDEOIO ERROR: V4L2: getting property #%d is not supported\n", + property_id); + return -1; + } + + capture->control.id = v4l2id; + if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_CTRL, &capture->control)) { @@ -2377,6 +2276,12 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, case CV_CAP_PROP_EXPOSURE: fprintf (stderr, "Exposure"); break; + case CV_CAP_PROP_AUTOFOCUS: + fprintf (stderr, "Autofocus"); + break; + case CV_CAP_PROP_FOCUS: + fprintf (stderr, "Focus"); + break; } fprintf (stderr, " is not supported by your device\n"); @@ -2384,36 +2289,10 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, } /* get the min/max values */ - switch (property_id) { - - case CV_CAP_PROP_BRIGHTNESS: - v4l2_min = capture->v4l2_brightness_min; - v4l2_max = capture->v4l2_brightness_max; - break; - case CV_CAP_PROP_CONTRAST: - v4l2_min = capture->v4l2_contrast_min; - v4l2_max = capture->v4l2_contrast_max; - break; - case CV_CAP_PROP_SATURATION: - v4l2_min = capture->v4l2_saturation_min; - v4l2_max = capture->v4l2_saturation_max; - break; - case CV_CAP_PROP_HUE: - v4l2_min = capture->v4l2_hue_min; - v4l2_max = capture->v4l2_hue_max; - break; - case CV_CAP_PROP_GAIN: - v4l2_min = capture->v4l2_gain_min; - v4l2_max = capture->v4l2_gain_max; - break; - case CV_CAP_PROP_EXPOSURE: - v4l2_min = capture->v4l2_exposure_min; - v4l2_max = capture->v4l2_exposure_max; - break; - } + cv::Range range = capture->getRange(property_id); /* all was OK, so convert to 0.0 - 1.0 range, and return the value */ - return ((float)capture->control.value - v4l2_min + 1) / (v4l2_max - v4l2_min); + return ((float)capture->control.value - range.start) / range.size(); } #endif /* HAVE_CAMV4L2 */ @@ -2482,113 +2361,6 @@ static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture, }; -static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) { - -#ifdef HAVE_CAMV4L2 - - if (V4L2_SUPPORT == 1) - { - - CLEAR (capture->cropcap); - capture->cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (ioctl (capture->deviceHandle, VIDIOC_CROPCAP, &capture->cropcap) < 0) { - fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: VIDIOC_CROPCAP\n"); - } else { - - CLEAR (capture->crop); - capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - capture->crop.c= capture->cropcap.defrect; - - /* set the crop area, but don't exit if the device don't support croping */ - if (ioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop) < 0) { - fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: VIDIOC_S_CROP\n"); - } - } - - CLEAR (capture->form); - capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - /* read the current setting, mainly to retreive the pixelformat information */ - ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form); - - /* set the values we want to change */ - capture->form.fmt.pix.width = w; - capture->form.fmt.pix.height = h; - capture->form.fmt.win.chromakey = 0; - capture->form.fmt.win.field = V4L2_FIELD_ANY; - capture->form.fmt.win.clips = 0; - capture->form.fmt.win.clipcount = 0; - capture->form.fmt.pix.field = V4L2_FIELD_ANY; - - /* ask the device to change the size - * don't test if the set of the size is ok, because some device - * don't allow changing the size, and we will get the real size - * later */ - ioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form); - - /* try to set framerate to 30 fps */ - struct v4l2_streamparm setfps; - memset (&setfps, 0, sizeof(struct v4l2_streamparm)); - setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - setfps.parm.capture.timeperframe.numerator = 1; - setfps.parm.capture.timeperframe.denominator = 30; - ioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps); - - /* we need to re-initialize some things, like buffers, because the size has - * changed */ - capture->FirstCapture = 1; - - /* Get window info again, to get the real value */ - if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) - { - fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n"); - - icvCloseCAM_V4L(capture); - - return 0; - } - - return 0; - - } -#endif /* HAVE_CAMV4L2 */ -#if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2) - else -#endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */ -#ifdef HAVE_CAMV4L - { - - if (capture==0) return 0; - if (w>capture->capability.maxwidth) { - w=capture->capability.maxwidth; - } - if (h>capture->capability.maxheight) { - h=capture->capability.maxheight; - } - - capture->captureWindow.width=w; - capture->captureWindow.height=h; - - if (ioctl(capture->deviceHandle, VIDIOCSWIN, &capture->captureWindow) < 0) { - icvCloseCAM_V4L(capture); - return 0; - } - - if (ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) { - icvCloseCAM_V4L(capture); - return 0; - } - - capture->FirstCapture = 1; - - } -#endif /* HAVE_CAMV4L */ - - return 0; - -} - static int icvSetControl (CvCaptureCAM_V4L* capture, int property_id, double value) { @@ -2603,111 +2375,24 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, if (V4L2_SUPPORT == 1) { - - /* default value for min and max */ - int v4l2_min = 0; - int v4l2_max = 255; - /* initialisations */ - CLEAR (capture->control); + __u32 v4l2id = capPropertyToV4L2(property_id); - /* set which control we want to set */ - switch (property_id) { - - case CV_CAP_PROP_BRIGHTNESS: - capture->control.id = V4L2_CID_BRIGHTNESS; - break; - case CV_CAP_PROP_CONTRAST: - capture->control.id = V4L2_CID_CONTRAST; - break; - case CV_CAP_PROP_SATURATION: - capture->control.id = V4L2_CID_SATURATION; - break; - case CV_CAP_PROP_HUE: - capture->control.id = V4L2_CID_HUE; - break; - case CV_CAP_PROP_GAIN: - capture->control.id = V4L2_CID_GAIN; - break; - case CV_CAP_PROP_EXPOSURE: - capture->control.id = V4L2_CID_EXPOSURE; - break; - default: + if(v4l2id == __u32(-1)) { fprintf(stderr, "VIDEOIO ERROR: V4L2: setting property #%d is not supported\n", property_id); return -1; } - - /* get the min and max values */ - if (-1 == ioctl (capture->deviceHandle, - VIDIOC_G_CTRL, &capture->control)) { -// perror ("VIDIOC_G_CTRL for getting min/max values"); - return -1; - } + /* set which control we want to set */ + CLEAR (capture->control); + capture->control.id = v4l2id; /* get the min/max values */ - switch (property_id) { - - case CV_CAP_PROP_BRIGHTNESS: - v4l2_min = capture->v4l2_brightness_min; - v4l2_max = capture->v4l2_brightness_max; - break; - case CV_CAP_PROP_CONTRAST: - v4l2_min = capture->v4l2_contrast_min; - v4l2_max = capture->v4l2_contrast_max; - break; - case CV_CAP_PROP_SATURATION: - v4l2_min = capture->v4l2_saturation_min; - v4l2_max = capture->v4l2_saturation_max; - break; - case CV_CAP_PROP_HUE: - v4l2_min = capture->v4l2_hue_min; - v4l2_max = capture->v4l2_hue_max; - break; - case CV_CAP_PROP_GAIN: - v4l2_min = capture->v4l2_gain_min; - v4l2_max = capture->v4l2_gain_max; - break; - case CV_CAP_PROP_EXPOSURE: - v4l2_min = capture->v4l2_exposure_min; - v4l2_max = capture->v4l2_exposure_max; - break; - } - - /* initialisations */ - CLEAR (capture->control); - - /* set which control we want to set */ - switch (property_id) { - - case CV_CAP_PROP_BRIGHTNESS: - capture->control.id = V4L2_CID_BRIGHTNESS; - break; - case CV_CAP_PROP_CONTRAST: - capture->control.id = V4L2_CID_CONTRAST; - break; - case CV_CAP_PROP_SATURATION: - capture->control.id = V4L2_CID_SATURATION; - break; - case CV_CAP_PROP_HUE: - capture->control.id = V4L2_CID_HUE; - break; - case CV_CAP_PROP_GAIN: - capture->control.id = V4L2_CID_GAIN; - break; - case CV_CAP_PROP_EXPOSURE: - capture->control.id = V4L2_CID_EXPOSURE; - break; - default: - fprintf(stderr, - "VIDEOIO ERROR: V4L2: setting property #%d is not supported\n", - property_id); - return -1; - } + cv::Range range = capture->getRange(property_id); /* set the value we want to set to the scaled the value */ - capture->control.value = (int)(value * (v4l2_max - v4l2_min) + v4l2_min); + capture->control.value = (int)(value * range.size() + range.start); /* The driver may clamp the value or return ERANGE, ignored here */ if (-1 == ioctl (capture->deviceHandle, @@ -2775,42 +2460,44 @@ static int icvSetControl (CvCaptureCAM_V4L* capture, static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value ){ static int width = 0, height = 0; - int retval; - - /* initialization */ - retval = 0; + int retval = 0; + bool possible; /* two subsequent calls setting WIDTH and HEIGHT will change the video size */ - /* the first one will return an error, though. */ switch (property_id) { case CV_CAP_PROP_FRAME_WIDTH: width = cvRound(value); if(width !=0 && height != 0) { - retval = icvSetVideoSize( capture, width, height); + capture->width = width; + capture->height = height; + retval = v4l2_reset( capture); width = height = 0; } break; case CV_CAP_PROP_FRAME_HEIGHT: height = cvRound(value); if(width !=0 && height != 0) { - retval = icvSetVideoSize( capture, width, height); + capture->width = width; + capture->height = height; + retval = v4l2_reset( capture); width = height = 0; } break; - case CV_CAP_PROP_BRIGHTNESS: - case CV_CAP_PROP_CONTRAST: - case CV_CAP_PROP_SATURATION: - case CV_CAP_PROP_HUE: - case CV_CAP_PROP_GAIN: - case CV_CAP_PROP_EXPOSURE: - retval = icvSetControl(capture, property_id, value); + case CV_CAP_PROP_FPS: + capture->fps = value; + retval = v4l2_reset( capture); + break; + case CV_CAP_PROP_CONVERT_RGB: + // returns "0" for formats we do not know how to map to IplImage + possible = v4l2_num_channels(capture->palette); + capture->convert_rgb = bool(value) && possible; + retval = !possible && bool(value) ? -1 : 0; break; default: - fprintf(stderr, - "VIDEOIO ERROR: V4L: setting property #%d is not supported\n", - property_id); + retval = icvSetControl(capture, property_id, value); + break; } /* return the the status */ diff --git a/modules/videoio/src/precomp.hpp b/modules/videoio/src/precomp.hpp index d60b00f94..442eaa19a 100644 --- a/modules/videoio/src/precomp.hpp +++ b/modules/videoio/src/precomp.hpp @@ -49,6 +49,7 @@ #include "opencv2/imgcodecs.hpp" +#include "opencv2/imgproc.hpp" #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/imgcodecs/imgcodecs_c.h" #include "opencv2/videoio/videoio_c.h" diff --git a/platforms/android/build-tests/test_ant_build.py b/platforms/android/build-tests/test_ant_build.py index 8ed2bdd66..73ac4d018 100644 --- a/platforms/android/build-tests/test_ant_build.py +++ b/platforms/android/build-tests/test_ant_build.py @@ -17,7 +17,7 @@ class TestAntBuild(unittest.TestCase): self.sample_dir = os.path.join(self.workdir, "project") def shortDescription(self): - return "TARGET: %s, SAMPLE: %s" % (self.target, os.path.basename(self.src_sample_dir)) + return "TARGET: %r, SAMPLE: %s" % (self.target, os.path.basename(self.src_sample_dir)) def setUp(self): if os.path.exists(self.workdir): @@ -32,7 +32,7 @@ class TestAntBuild(unittest.TestCase): shutil.rmtree(self.workdir) def runTest(self): - cmd = [os.path.join(os.environ["ANDROID_SDK"], "tools", "android"), "update", "project", "-p", self.lib_dir, "-t", self.target] + cmd = [os.path.join(os.environ["ANDROID_SDK"], "tools", "android"), "update", "project", "-p", self.lib_dir, "-t", self.target[0]] retcode = subprocess.call(cmd) self.assertEqual(retcode, 0, "android update opencv project failed") @@ -40,7 +40,7 @@ class TestAntBuild(unittest.TestCase): retcode = subprocess.call(cmd) self.assertEqual(retcode, 0, "opencv ant build failed") - cmd = [os.path.join(os.environ["ANDROID_SDK"], "tools", "android"), "update", "project", "-p", self.sample_dir, "-t", self.target, "-l", os.path.relpath(self.lib_dir, self.sample_dir)] + cmd = [os.path.join(os.environ["ANDROID_SDK"], "tools", "android"), "update", "project", "-p", self.sample_dir, "-t", self.target[1], "-l", os.path.relpath(self.lib_dir, self.sample_dir)] retcode = subprocess.call(cmd) self.assertEqual(retcode, 0, "android update sample project failed") @@ -50,7 +50,7 @@ class TestAntBuild(unittest.TestCase): def suite(workdir, opencv_lib_path, opencv_samples_path): suite = unittest.TestSuite() - for target in ["android-14", "android-17"]: + for target in [("android-21", "android-14"), ("android-21", "android-17")]: for item in os.listdir(opencv_samples_path): item = os.path.join(opencv_samples_path, item) if (os.path.exists(os.path.join(item, "AndroidManifest.xml"))): diff --git a/platforms/scripts/valgrind.supp b/platforms/scripts/valgrind.supp new file mode 100644 index 000000000..b37ca2017 --- /dev/null +++ b/platforms/scripts/valgrind.supp @@ -0,0 +1,6 @@ +{ + IPP static init + Memcheck:Cond + fun:ippicvGetCpuFeatures + fun:ippicvStaticInit +} diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 7c45bece7..2b0e74ccd 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -22,8 +22,8 @@ if((NOT ANDROID) AND HAVE_OPENGL) add_subdirectory(opengl) endif() -if(UNIX AND NOT ANDROID AND HAVE_VAAPI) - add_subdirectory(vaapi) +if(UNIX AND NOT ANDROID AND (HAVE_VA OR HAVE_VA_INTEL)) + add_subdirectory(va_intel) endif() if(ANDROID AND BUILD_ANDROID_EXAMPLES) diff --git a/samples/android/tutorial-4-opencl/.cproject b/samples/android/tutorial-4-opencl/.cproject index 9f3b5fd84..90fc6c97f 100644 --- a/samples/android/tutorial-4-opencl/.cproject +++ b/samples/android/tutorial-4-opencl/.cproject @@ -5,6 +5,7 @@ + @@ -12,7 +13,6 @@ - @@ -28,7 +28,7 @@ diff --git a/samples/android/tutorial-4-opencl/CMakeLists.txt b/samples/android/tutorial-4-opencl/CMakeLists.txt index 96bacdeb4..e8036cfbd 100644 --- a/samples/android/tutorial-4-opencl/CMakeLists.txt +++ b/samples/android/tutorial-4-opencl/CMakeLists.txt @@ -15,11 +15,12 @@ else() endif() include_directories(${ANDROID_OPENCL_SDK}/include) -link_directories(${ANDROID_OPENCL_SDK}/lib/${ANDROID_ABI}) +link_directories(${ANDROID_OPENCL_SDK}/lib/${ANDROID_NDK_ABI_NAME}) add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 21 ${ANDROID_SDK_TARGET} NATIVE_DEPS ${native_deps} -lGLESv2 -lEGL -lOpenCL + COPY_LIBS YES ) if(TARGET ${sample}) add_dependencies(opencv_android_examples ${sample}) diff --git a/samples/android/tutorial-4-opencl/jni/Android.mk b/samples/android/tutorial-4-opencl/jni/Android.mk index fa44bf8c5..dacd0f665 100644 --- a/samples/android/tutorial-4-opencl/jni/Android.mk +++ b/samples/android/tutorial-4-opencl/jni/Android.mk @@ -21,7 +21,7 @@ endif LOCAL_C_INCLUDES += $(OPENCL_SDK)/include LOCAL_LDLIBS += -L$(OPENCL_SDK)/lib/$(TARGET_ARCH_ABI) -lOpenCL -LOCAL_MODULE := JNIrender -LOCAL_SRC_FILES := jni.c GLrender.cpp CLprocessor.cpp +LOCAL_MODULE := JNIpart +LOCAL_SRC_FILES := jni.c CLprocessor.cpp LOCAL_LDLIBS += -llog -lGLESv2 -lEGL include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp b/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp index a46cac424..b71dc1018 100644 --- a/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp +++ b/samples/android/tutorial-4-opencl/jni/CLprocessor.cpp @@ -2,6 +2,7 @@ #define CL_USE_DEPRECATED_OPENCL_1_1_APIS /*let's give a chance for OpenCL 1.1 devices*/ #include +#include #include #include @@ -82,7 +83,7 @@ cl::CommandQueue theQueue; cl::Program theProgB2B, theProgI2B, theProgI2I; bool haveOpenCL = false; -void initCL() +extern "C" void initCL() { dumpCLinfo(); @@ -144,14 +145,19 @@ void initCL() LOGD("initCL completed"); } -void closeCL() +extern "C" void closeCL() { } #define GL_TEXTURE_2D 0x0DE1 void procOCL_I2I(int texIn, int texOut, int w, int h) { - if(!haveOpenCL) return; + LOGD("Processing OpenCL Direct (image2d)"); + if(!haveOpenCL) + { + LOGE("OpenCL isn't initialized"); + return; + } LOGD("procOCL_I2I(%d, %d, %d, %d)", texIn, texOut, w, h); cl::ImageGL imgIn (theContext, CL_MEM_READ_ONLY, GL_TEXTURE_2D, 0, texIn); @@ -185,7 +191,12 @@ void procOCL_I2I(int texIn, int texOut, int w, int h) void procOCL_OCV(int texIn, int texOut, int w, int h) { - if(!haveOpenCL) return; + LOGD("Processing OpenCL via OpenCV"); + if(!haveOpenCL) + { + LOGE("OpenCL isn't initialized"); + return; + } int64_t t = getTimeMs(); cl::ImageGL imgIn (theContext, CL_MEM_READ_ONLY, GL_TEXTURE_2D, 0, texIn); @@ -219,3 +230,54 @@ void procOCL_OCV(int texIn, int texOut, int w, int h) cv::ocl::finish(); LOGD("uploading results to texture costs %d ms", getTimeInterval(t)); } + +void drawFrameProcCPU(int w, int h, int texOut) +{ + LOGD("Processing on CPU"); + int64_t t; + + // let's modify pixels in FBO texture in C++ code (on CPU) + static cv::Mat m; + m.create(h, w, CV_8UC4); + + // read + t = getTimeMs(); + // expecting FBO to be bound + glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m.data); + LOGD("glReadPixels() costs %d ms", getTimeInterval(t)); + + // modify + t = getTimeMs(); + cv::Laplacian(m, m, CV_8U); + m *= 10; + LOGD("Laplacian() costs %d ms", getTimeInterval(t)); + + // write back + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texOut); + t = getTimeMs(); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m.data); + LOGD("glTexSubImage2D() costs %d ms", getTimeInterval(t)); +} + + +enum ProcMode {PROC_MODE_NO_PROC=0, PROC_MODE_CPU=1, PROC_MODE_OCL_DIRECT=2, PROC_MODE_OCL_OCV=3}; + +extern "C" void processFrame(int tex1, int tex2, int w, int h, int mode) +{ + switch(mode) + { + //case PROC_MODE_NO_PROC: + case PROC_MODE_CPU: + drawFrameProcCPU(w, h, tex2); + break; + case PROC_MODE_OCL_DIRECT: + procOCL_I2I(tex1, tex2, w, h); + break; + case PROC_MODE_OCL_OCV: + procOCL_OCV(tex1, tex2, w, h); + break; + default: + LOGE("Unexpected processing mode: %d", mode); + } +} diff --git a/samples/android/tutorial-4-opencl/jni/GLrender.cpp b/samples/android/tutorial-4-opencl/jni/GLrender.cpp deleted file mode 100644 index 5c2862026..000000000 --- a/samples/android/tutorial-4-opencl/jni/GLrender.cpp +++ /dev/null @@ -1,375 +0,0 @@ -#include -#include - -#include -#include - -#include "common.hpp" - -float vertices[] = { - -1.0f, -1.0f, - -1.0f, 1.0f, - 1.0f, -1.0f, - 1.0f, 1.0f -}; -float texCoordOES[] = { - 0.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 1.0f, - 1.0f, 0.0f -}; -float texCoord2D[] = { - 0.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 0.0f, - 1.0f, 1.0f -}; - -const char vss[] = \ - "attribute vec2 vPosition;\n" \ - "attribute vec2 vTexCoord;\n" \ - "varying vec2 texCoord;\n" \ - "void main() {\n" \ - " texCoord = vTexCoord;\n" \ - " gl_Position = vec4 ( vPosition, 0.0, 1.0 );\n" \ - "}"; - -const char fssOES[] = \ - "#extension GL_OES_EGL_image_external : require\n" \ - "precision mediump float;\n" \ - "uniform samplerExternalOES sTexture;\n" \ - "varying vec2 texCoord;\n" \ - "void main() {\n" \ - " gl_FragColor = texture2D(sTexture,texCoord);\n" \ - "}"; - -const char fss2D[] = \ - "precision mediump float;\n" \ - "uniform sampler2D sTexture;\n" \ - "varying vec2 texCoord;\n" \ - "void main() {\n" \ - " gl_FragColor = texture2D(sTexture,texCoord);\n" \ - "}"; - -GLuint progOES = 0; -GLuint prog2D = 0; - -GLint vPosOES, vTCOES; -GLint vPos2D, vTC2D; - -GLuint FBOtex = 0, FBOtex2 = 0; -GLuint FBO = 0; - -GLuint texOES = 0; -int texWidth = 0, texHeight = 0; - -enum ProcMode {PROC_MODE_NO_PROC=0, PROC_MODE_CPU=1, PROC_MODE_OCL_DIRECT=2, PROC_MODE_OCL_OCV=3}; - -ProcMode procMode = PROC_MODE_NO_PROC; - -static inline void deleteTex(GLuint* tex) -{ - if(tex && *tex) - { - glDeleteTextures(1, tex); - *tex = 0; - } -} - -static void releaseFBO() -{ - if (FBO != 0) - { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDeleteFramebuffers(1, &FBO); - FBO = 0; - } - deleteTex(&FBOtex); - deleteTex(&FBOtex2); - glDeleteProgram(prog2D); - prog2D = 0; -} - -static inline void logShaderCompileError(GLuint shader, bool isProgram = false) -{ - GLchar msg[512]; - msg[0] = 0; - GLsizei len; - if(isProgram) - glGetProgramInfoLog(shader, sizeof(msg)-1, &len, msg); - else - glGetShaderInfoLog(shader, sizeof(msg)-1, &len, msg); - LOGE("Could not compile shader/program: %s", msg); -} - -static int makeShaderProg(const char* vss, const char* fss) -{ - LOGD("makeShaderProg: setup GL_VERTEX_SHADER"); - GLuint vshader = glCreateShader(GL_VERTEX_SHADER); - const GLchar* text = vss; - glShaderSource(vshader, 1, &text, 0); - glCompileShader(vshader); - GLint compiled; - glGetShaderiv(vshader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - logShaderCompileError(vshader); - glDeleteShader(vshader); - vshader = 0; - } - - LOGD("makeShaderProg: setup GL_FRAGMENT_SHADER"); - GLuint fshader = glCreateShader(GL_FRAGMENT_SHADER); - text = fss; - glShaderSource(fshader, 1, &text, 0); - glCompileShader(fshader); - glGetShaderiv(fshader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - logShaderCompileError(fshader); - glDeleteShader(fshader); - fshader = 0; - } - - LOGD("makeShaderProg: glCreateProgram"); - GLuint program = glCreateProgram(); - glAttachShader(program, vshader); - glAttachShader(program, fshader); - glLinkProgram(program); - GLint linked; - glGetProgramiv(program, GL_LINK_STATUS, &linked); - if (!linked) - { - logShaderCompileError(program, true); - glDeleteProgram(program); - program = 0; - } - glValidateProgram(program); - GLint validated; - glGetProgramiv(program, GL_VALIDATE_STATUS, &validated); - if (!validated) - { - logShaderCompileError(program, true); - glDeleteProgram(program); - program = 0; - } - - if(vshader) glDeleteShader(vshader); - if(fshader) glDeleteShader(fshader); - - return program; -} - - -static void initFBO(int width, int height) -{ - LOGD("initFBO(%d, %d)", width, height); - releaseFBO(); - - glGenTextures(1, &FBOtex2); - glBindTexture(GL_TEXTURE_2D, FBOtex2); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glGenTextures(1, &FBOtex); - glBindTexture(GL_TEXTURE_2D, FBOtex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - //int hFBO; - glGenFramebuffers(1, &FBO); - glBindFramebuffer(GL_FRAMEBUFFER, FBO); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FBOtex, 0); - LOGD("initFBO status: %d", glGetError()); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - LOGE("initFBO failed: %d", glCheckFramebufferStatus(GL_FRAMEBUFFER)); - - prog2D = makeShaderProg(vss, fss2D); - vPos2D = glGetAttribLocation(prog2D, "vPosition"); - vTC2D = glGetAttribLocation(prog2D, "vTexCoord"); - glEnableVertexAttribArray(vPos2D); - glEnableVertexAttribArray(vTC2D); -} - -void drawTex(int tex, GLenum texType, GLuint fbo) -{ - int64_t t = getTimeMs(); - //draw texture to FBO or to screen - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glViewport(0, 0, texWidth, texHeight); - - glClear(GL_COLOR_BUFFER_BIT); - - GLuint prog = texType == GL_TEXTURE_EXTERNAL_OES ? progOES : prog2D; - GLint vPos = texType == GL_TEXTURE_EXTERNAL_OES ? vPosOES : vPos2D; - GLint vTC = texType == GL_TEXTURE_EXTERNAL_OES ? vTCOES : vTC2D; - float* texCoord = texType == GL_TEXTURE_EXTERNAL_OES ? texCoordOES : texCoord2D; - glUseProgram(prog); - glVertexAttribPointer(vPos, 2, GL_FLOAT, false, 4*2, vertices); - glVertexAttribPointer(vTC, 2, GL_FLOAT, false, 4*2, texCoord); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(texType, tex); - glUniform1i(glGetUniformLocation(prog, "sTexture"), 0); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glFlush(); - LOGD("drawTex(%u) costs %d ms", tex, getTimeInterval(t)); -} - -void drawFrameOrig() -{ - drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, 0); -} - -void procCPU(char* buff, int w, int h) -{ - int64_t t = getTimeMs(); - cv::Mat m(h, w, CV_8UC4, buff); - cv::Laplacian(m, m, CV_8U); - m *= 10; - LOGD("procCPU() costs %d ms", getTimeInterval(t)); -} - -void drawFrameProcCPU() -{ - int64_t t; - drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, FBO); - - // let's modify pixels in FBO texture in C++ code (on CPU) - const int BUFF_SIZE = 1<<24;//2k*2k*4; - static char tmpBuff[BUFF_SIZE]; - if(texWidth*texHeight > BUFF_SIZE) - { - LOGE("Internal temp buffer is too small, can't make CPU frame processing"); - return; - } - - // read - t = getTimeMs(); - glReadPixels(0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuff); - LOGD("glReadPixels() costs %d ms", getTimeInterval(t)); - - // modify - procCPU(tmpBuff, texWidth, texHeight); - - // write back - t = getTimeMs(); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuff); - LOGD("glTexSubImage2D() costs %d ms", getTimeInterval(t)); - - // render to screen - drawTex(FBOtex, GL_TEXTURE_2D, 0); -} - -void procOCL_I2I(int texIn, int texOut, int w, int h); -void procOCL_OCV(int texIn, int texOut, int w, int h); -void drawFrameProcOCL() -{ - drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, FBO); - - // modify pixels in FBO texture using OpenCL and CL-GL interop - procOCL_I2I(FBOtex, FBOtex2, texWidth, texHeight); - - // render to screen - drawTex(FBOtex2, GL_TEXTURE_2D, 0); -} - -void drawFrameProcOCLOCV() -{ - drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, FBO); - - // modify pixels in FBO texture using OpenCL and CL-GL interop - procOCL_OCV(FBOtex, FBOtex2, texWidth, texHeight); - - // render to screen - drawTex(FBOtex2, GL_TEXTURE_2D, 0); -} - -extern "C" void drawFrame() -{ - LOGD("*** drawFrame() ***"); - int64_t t = getTimeMs(); - - switch(procMode) - { - case PROC_MODE_NO_PROC: drawFrameOrig(); break; - case PROC_MODE_CPU: drawFrameProcCPU(); break; - case PROC_MODE_OCL_DIRECT: drawFrameProcOCL(); break; - case PROC_MODE_OCL_OCV: drawFrameProcOCLOCV(); break; - default: drawFrameOrig(); - } - - glFinish(); - LOGD("*** drawFrame() costs %d ms ***", getTimeInterval(t)); -} - -void closeCL(); -extern "C" void closeGL() -{ - closeCL(); - LOGD("closeGL"); - deleteTex(&texOES); - - glUseProgram(0); - glDeleteProgram(progOES); - progOES = 0; - - releaseFBO(); -} - -void initCL(); -extern "C" int initGL() -{ - LOGD("initGL"); - - closeGL(); - - const char* vs = (const char*)glGetString(GL_VERSION); - LOGD("GL_VERSION = %s", vs); - - progOES = makeShaderProg(vss, fssOES); - vPosOES = glGetAttribLocation(progOES, "vPosition"); - vTCOES = glGetAttribLocation(progOES, "vTexCoord"); - glEnableVertexAttribArray(vPosOES); - glEnableVertexAttribArray(vTCOES); - - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - - texOES = 0; - glGenTextures(1, &texOES); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, texOES); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - initCL(); - - return texOES; -} - -extern "C" void changeSize(int width, int height) -{ - const int MAX_W=1<<11, MAX_H=1<<11; - LOGD("changeSize: %dx%d", width, height); - texWidth = width <= MAX_W ? width : MAX_W; - texHeight = height <= MAX_H ? height : MAX_H; - initFBO(texWidth, texHeight); -} - -extern "C" void setProcessingMode(int mode) -{ - switch(mode) - { - case PROC_MODE_NO_PROC: procMode = PROC_MODE_NO_PROC; break; - case PROC_MODE_CPU: procMode = PROC_MODE_CPU; break; - case PROC_MODE_OCL_DIRECT: procMode = PROC_MODE_OCL_DIRECT; break; - case PROC_MODE_OCL_OCV: procMode = PROC_MODE_OCL_OCV; break; - } -} diff --git a/samples/android/tutorial-4-opencl/jni/common.hpp b/samples/android/tutorial-4-opencl/jni/common.hpp index 20b882a9f..2923803f2 100644 --- a/samples/android/tutorial-4-opencl/jni/common.hpp +++ b/samples/android/tutorial-4-opencl/jni/common.hpp @@ -1,5 +1,5 @@ #include -#define LOG_TAG "JNIRenderer" +#define LOG_TAG "JNIpart" //#define LOGD(...) #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) diff --git a/samples/android/tutorial-4-opencl/jni/jni.c b/samples/android/tutorial-4-opencl/jni/jni.c index 7be35a000..0c48ab606 100644 --- a/samples/android/tutorial-4-opencl/jni/jni.c +++ b/samples/android/tutorial-4-opencl/jni/jni.c @@ -1,32 +1,20 @@ #include -int initGL(); -void closeGL(); -void changeSize(int width, int height); -void drawFrame(); -void setProcessingMode(int mode); +int initCL(); +void closeCL(); +void processFrame(int tex1, int tex2, int w, int h, int mode); -JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_initGL(JNIEnv * env, jclass cls) +JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial4_NativePart_initCL(JNIEnv * env, jclass cls) { - return initGL(); + return initCL(); } -JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_closeGL(JNIEnv * env, jclass cls) +JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativePart_closeCL(JNIEnv * env, jclass cls) { - closeGL(); + closeCL(); } -JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_changeSize(JNIEnv * env, jclass cls, jint width, jint height) +JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativePart_processFrame(JNIEnv * env, jclass cls, jint tex1, jint tex2, jint w, jint h, jint mode) { - changeSize(width, height); -} - -JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_drawFrame(JNIEnv * env, jclass cls) -{ - drawFrame(); -} - -JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_setProcessingMode(JNIEnv * env, jclass cls, jint mode) -{ - setProcessingMode(mode); + processFrame(tex1, tex2, w, h, mode); } diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/CameraRenderer.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/CameraRenderer.java deleted file mode 100644 index 692ab9884..000000000 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/CameraRenderer.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.opencv.samples.tutorial4; - -import java.io.IOException; -import java.util.List; - -import android.hardware.Camera; -import android.hardware.Camera.Size; -import android.util.Log; - -@SuppressWarnings("deprecation") -public class CameraRenderer extends MyGLRendererBase { - - protected final String LOGTAG = "CameraRenderer"; - private Camera mCamera; - boolean mPreviewStarted = false; - - CameraRenderer(MyGLSurfaceView view) { - super(view); - } - - protected void closeCamera() { - Log.i(LOGTAG, "closeCamera"); - if(mCamera != null) { - mCamera.stopPreview(); - mPreviewStarted = false; - mCamera.release(); - mCamera = null; - } - } - - protected void openCamera() { - Log.i(LOGTAG, "openCamera"); - closeCamera(); - mCamera = Camera.open(); - try { - mCamera.setPreviewTexture(mSTex); - } catch (IOException ioe) { - Log.e(LOGTAG, "setPreviewTexture() failed: " + ioe.getMessage()); - } - } - - public void setCameraPreviewSize(int width, int height) { - Log.i(LOGTAG, "setCameraPreviewSize: "+width+"x"+height); - if(mCamera == null) - return; - if(mPreviewStarted) { - mCamera.stopPreview(); - mPreviewStarted = false; - } - Camera.Parameters param = mCamera.getParameters(); - List psize = param.getSupportedPreviewSizes(); - int bestWidth = 0, bestHeight = 0; - if (psize.size() > 0) { - float aspect = (float)width / height; - for (Size size : psize) { - int w = size.width, h = size.height; - Log.d("Renderer", "checking camera preview size: "+w+"x"+h); - if ( w <= width && h <= height && - w >= bestWidth && h >= bestHeight && - Math.abs(aspect - (float)w/h) < 0.2 ) { - bestWidth = w; - bestHeight = h; - } - } - if(bestWidth > 0 && bestHeight > 0) { - param.setPreviewSize(bestWidth, bestHeight); - Log.i(LOGTAG, "size: "+bestWidth+" x "+bestHeight); - } - } - param.set("orientation", "landscape"); - mCamera.setParameters(param); - mCamera.startPreview(); - mPreviewStarted = true; - } -} diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLRendererBase.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLRendererBase.java deleted file mode 100644 index f3abe87b3..000000000 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLRendererBase.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.opencv.samples.tutorial4; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -import android.graphics.SurfaceTexture; -import android.opengl.GLES20; -import android.opengl.GLSurfaceView; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; -import android.widget.TextView; - -public abstract class MyGLRendererBase implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { - protected final String LOGTAG = "MyGLRendererBase"; - protected int frameCounter; - protected long lastNanoTime; - - protected SurfaceTexture mSTex; - protected MyGLSurfaceView mView; - protected TextView mFpsText; - - protected boolean mGLInit = false; - protected boolean mTexUpdate = false; - - MyGLRendererBase(MyGLSurfaceView view) { - mView = view; - } - - protected abstract void openCamera(); - protected abstract void closeCamera(); - protected abstract void setCameraPreviewSize(int width, int height); - - public void setFpsTextView(TextView fpsTV) - { - mFpsText = fpsTV; - } - - public void onResume() { - Log.i(LOGTAG, "onResume"); - frameCounter = 0; - lastNanoTime = System.nanoTime(); - } - - public void onPause() { - Log.i(LOGTAG, "onPause"); - mGLInit = false; - mTexUpdate = false; - closeCamera(); - if(mSTex != null) { - mSTex.release(); - mSTex = null; - NativeGLRenderer.closeGL(); - } - } - - @Override - public synchronized void onFrameAvailable(SurfaceTexture surfaceTexture) { - //Log.i(LOGTAG, "onFrameAvailable"); - mTexUpdate = true; - mView.requestRender(); - } - - @Override - public void onDrawFrame(GL10 gl) { - //Log.i(LOGTAG, "onDrawFrame"); - if (!mGLInit) - return; - - synchronized (this) { - if (mTexUpdate) { - mSTex.updateTexImage(); - mTexUpdate = false; - } - } - NativeGLRenderer.drawFrame(); - - // log FPS - frameCounter++; - if(frameCounter >= 10) - { - final int fps = (int) (frameCounter * 1e9 / (System.nanoTime() - lastNanoTime)); - Log.i(LOGTAG, "drawFrame() FPS: "+fps); - if(mFpsText != null) { - Runnable fpsUpdater = new Runnable() { - public void run() { - mFpsText.setText("FPS: " + fps); - } - }; - new Handler(Looper.getMainLooper()).post(fpsUpdater); - } - frameCounter = 0; - lastNanoTime = System.nanoTime(); - } - } - - @Override - public void onSurfaceChanged(GL10 gl, int surfaceWidth, int surfaceHeight) { - Log.i(LOGTAG, "onSurfaceChanged("+surfaceWidth+"x"+surfaceHeight+")"); - NativeGLRenderer.changeSize(surfaceWidth, surfaceHeight); - setCameraPreviewSize(surfaceWidth, surfaceHeight); - } - - @Override - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - Log.i(LOGTAG, "onSurfaceCreated"); - String strGLVersion = GLES20.glGetString(GLES20.GL_VERSION); - if (strGLVersion != null) - Log.i(LOGTAG, "OpenGL ES version: " + strGLVersion); - - int hTex = NativeGLRenderer.initGL(); - mSTex = new SurfaceTexture(hTex); - mSTex.setOnFrameAvailableListener(this); - openCamera(); - mGLInit = true; - } -} diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLSurfaceView.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLSurfaceView.java index 8556b4181..edaf34631 100644 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLSurfaceView.java +++ b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/MyGLSurfaceView.java @@ -1,59 +1,29 @@ package org.opencv.samples.tutorial4; +import org.opencv.android.CameraGLSurfaceView; + import android.app.Activity; import android.content.Context; -import android.opengl.GLSurfaceView; +import android.os.Handler; +import android.os.Looper; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.widget.TextView; +import android.widget.Toast; -public class MyGLSurfaceView extends GLSurfaceView { +public class MyGLSurfaceView extends CameraGLSurfaceView implements CameraGLSurfaceView.CameraTextureListener { - MyGLRendererBase mRenderer; + static final String LOGTAG = "MyGLSurfaceView"; + protected int procMode = NativePart.PROCESSING_MODE_NO_PROCESSING; + static final String[] procModeName = new String[] {"No Processing", "CPU", "OpenCL Direct", "OpenCL via OpenCV"}; + protected int frameCounter; + protected long lastNanoTime; + TextView mFpsText = null; public MyGLSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); - - if(android.os.Build.VERSION.SDK_INT >= 21) - mRenderer = new Camera2Renderer(this); - else - mRenderer = new CameraRenderer(this); - - setEGLContextClientVersion(2); - setRenderer(mRenderer); - setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - } - - public void setFpsTextView(TextView tv) { - mRenderer.setFpsTextView(tv); - } - - @Override - public void surfaceCreated(SurfaceHolder holder) { - super.surfaceCreated(holder); - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - super.surfaceDestroyed(holder); - } - - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - super.surfaceChanged(holder, format, w, h); - } - - @Override - public void onResume() { - super.onResume(); - mRenderer.onResume(); - } - - @Override - public void onPause() { - mRenderer.onPause(); - super.onPause(); } @Override @@ -62,4 +32,81 @@ public class MyGLSurfaceView extends GLSurfaceView { ((Activity)getContext()).openOptionsMenu(); return true; } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + super.surfaceCreated(holder); + //NativePart.initCL(); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + //NativePart.closeCL(); + super.surfaceDestroyed(holder); + } + + public void setProcessingMode(int newMode) { + if(newMode>=0 && newMode= 30) + { + final int fps = (int) (frameCounter * 1e9 / (System.nanoTime() - lastNanoTime)); + Log.i(LOGTAG, "drawFrame() FPS: "+fps); + if(mFpsText != null) { + Runnable fpsUpdater = new Runnable() { + public void run() { + mFpsText.setText("FPS: " + fps); + } + }; + new Handler(Looper.getMainLooper()).post(fpsUpdater); + } else { + Log.d(LOGTAG, "mFpsText == null"); + mFpsText = (TextView)((Activity) getContext()).findViewById(R.id.fps_text_view); + } + frameCounter = 0; + lastNanoTime = System.nanoTime(); + } + + + if(procMode == NativePart.PROCESSING_MODE_NO_PROCESSING) + return false; + + NativePart.processFrame(texIn, texOut, width, height, procMode); + return true; + } } diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativeGLRenderer.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativePart.java similarity index 51% rename from samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativeGLRenderer.java rename to samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativePart.java index 8d9216c97..e5f11ba3a 100644 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativeGLRenderer.java +++ b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/NativePart.java @@ -1,10 +1,10 @@ package org.opencv.samples.tutorial4; -public class NativeGLRenderer { +public class NativePart { static { System.loadLibrary("opencv_java3"); - System.loadLibrary("JNIrender"); + System.loadLibrary("JNIpart"); } public static final int PROCESSING_MODE_NO_PROCESSING = 0; @@ -12,9 +12,7 @@ public class NativeGLRenderer { public static final int PROCESSING_MODE_OCL_DIRECT = 2; public static final int PROCESSING_MODE_OCL_OCV = 3; - public static native int initGL(); - public static native void closeGL(); - public static native void drawFrame(); - public static native void changeSize(int width, int height); - public static native void setProcessingMode(int mode); + public static native int initCL(); + public static native void closeCL(); + public static native void processFrame(int tex1, int tex2, int w, int h, int mode); } diff --git a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Tutorial4Activity.java b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Tutorial4Activity.java index 56b416c80..0be55df65 100644 --- a/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Tutorial4Activity.java +++ b/samples/android/tutorial-4-opencl/src/org/opencv/samples/tutorial4/Tutorial4Activity.java @@ -29,8 +29,8 @@ public class Tutorial4Activity extends Activity { //setContentView(mView); setContentView(R.layout.activity); mView = (MyGLSurfaceView) findViewById(R.id.my_gl_surface_view); + mView.setCameraTextureListener(mView); TextView tv = (TextView)findViewById(R.id.fps_text_view); - mView.setFpsTextView(tv); mProcMode = (TextView)findViewById(R.id.proc_mode_text_view); runOnUiThread(new Runnable() { public void run() { @@ -38,7 +38,8 @@ public class Tutorial4Activity extends Activity { } }); - NativeGLRenderer.setProcessingMode(NativeGLRenderer.PROCESSING_MODE_NO_PROCESSING); } + mView.setProcessingMode(NativePart.PROCESSING_MODE_NO_PROCESSING); + } @Override protected void onPause() { @@ -68,7 +69,7 @@ public class Tutorial4Activity extends Activity { mProcMode.setText("Processing mode: No Processing"); } }); - NativeGLRenderer.setProcessingMode(NativeGLRenderer.PROCESSING_MODE_NO_PROCESSING); + mView.setProcessingMode(NativePart.PROCESSING_MODE_NO_PROCESSING); return true; case R.id.cpu: runOnUiThread(new Runnable() { @@ -76,7 +77,7 @@ public class Tutorial4Activity extends Activity { mProcMode.setText("Processing mode: CPU"); } }); - NativeGLRenderer.setProcessingMode(NativeGLRenderer.PROCESSING_MODE_CPU); + mView.setProcessingMode(NativePart.PROCESSING_MODE_CPU); return true; case R.id.ocl_direct: runOnUiThread(new Runnable() { @@ -84,7 +85,7 @@ public class Tutorial4Activity extends Activity { mProcMode.setText("Processing mode: OpenCL direct"); } }); - NativeGLRenderer.setProcessingMode(NativeGLRenderer.PROCESSING_MODE_OCL_DIRECT); + mView.setProcessingMode(NativePart.PROCESSING_MODE_OCL_DIRECT); return true; case R.id.ocl_ocv: runOnUiThread(new Runnable() { @@ -92,7 +93,7 @@ public class Tutorial4Activity extends Activity { mProcMode.setText("Processing mode: OpenCL via OpenCV (TAPI)"); } }); - NativeGLRenderer.setProcessingMode(NativeGLRenderer.PROCESSING_MODE_OCL_OCV); + mView.setProcessingMode(NativePart.PROCESSING_MODE_OCL_OCV); return true; default: return false; diff --git a/samples/cpp/facedetect.cpp b/samples/cpp/facedetect.cpp index 1206245ef..2be4e17e4 100644 --- a/samples/cpp/facedetect.cpp +++ b/samples/cpp/facedetect.cpp @@ -1,17 +1,7 @@ #include "opencv2/objdetect.hpp" -#include "opencv2/imgcodecs.hpp" -#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/core/utility.hpp" - -#include "opencv2/videoio/videoio_c.h" -#include "opencv2/highgui/highgui_c.h" - -#include #include -#include -#include using namespace std; using namespace cv; @@ -28,7 +18,7 @@ static void help() " [--try-flip]\n" " [filename|camera_index]\n\n" "see facedetect.cmd for one call:\n" - "./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye.xml\" --scale=1.3\n\n" + "./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml\" --scale=1.3\n\n" "During execution:\n\tHit any key to quit.\n" "\tUsing OpenCV version " << CV_VERSION << "\n" << endl; } @@ -42,8 +32,8 @@ string nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglas int main( int argc, const char** argv ) { - CvCapture* capture = 0; - Mat frame, frameCopy, image; + VideoCapture capture; + Mat frame, image; const string scaleOpt = "--scale="; size_t scaleOptLen = scaleOpt.length(); const string cascadeOpt = "--cascade="; @@ -103,17 +93,17 @@ int main( int argc, const char** argv ) if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') ) { - capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' ); int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ; - if(!capture) cout << "Capture from CAM " << c << " didn't work" << endl; + if(!capture.open(c)) + cout << "Capture from camera #" << c << " didn't work" << endl; } else if( inputName.size() ) { image = imread( inputName, 1 ); if( image.empty() ) { - capture = cvCaptureFromAVI( inputName.c_str() ); - if(!capture) cout << "Capture from AVI didn't work" << endl; + if(!capture.open( inputName )) + cout << "Could not read " << inputName << endl; } } else @@ -122,36 +112,27 @@ int main( int argc, const char** argv ) if(image.empty()) cout << "Couldn't read ../data/lena.jpg" << endl; } - cvNamedWindow( "result", 1 ); - - if( capture ) + if( capture.isOpened() ) { - cout << "In capture ..." << endl; + cout << "Video capturing has been started ..." << endl; + for(;;) { - IplImage* iplImg = cvQueryFrame( capture ); - frame = cv::cvarrToMat(iplImg); + capture >> frame; if( frame.empty() ) break; - if( iplImg->origin == IPL_ORIGIN_TL ) - frame.copyTo( frameCopy ); - else - flip( frame, frameCopy, 0 ); - detectAndDraw( frameCopy, cascade, nestedCascade, scale, tryflip ); + Mat frame1 = frame.clone(); + detectAndDraw( frame1, cascade, nestedCascade, scale, tryflip ); - if( waitKey( 10 ) >= 0 ) - goto _cleanup_; + int c = waitKey(10); + if( c == 27 || c == 'q' || c == 'Q' ) + break; } - - waitKey(0); - -_cleanup_: - cvReleaseCapture( &capture ); } else { - cout << "In image read" << endl; + cout << "Detecting face(s) in " << inputName << endl; if( !image.empty() ) { detectAndDraw( image, cascade, nestedCascade, scale, tryflip ); @@ -190,8 +171,6 @@ _cleanup_: } } - cvDestroyWindow("result"); - return 0; } @@ -199,21 +178,24 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip ) { - int i = 0; double t = 0; vector faces, faces2; - const static Scalar colors[] = { CV_RGB(0,0,255), - CV_RGB(0,128,255), - CV_RGB(0,255,255), - CV_RGB(0,255,0), - CV_RGB(255,128,0), - CV_RGB(255,255,0), - CV_RGB(255,0,0), - CV_RGB(255,0,255)} ; - Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); + const static Scalar colors[] = + { + Scalar(255,0,0), + Scalar(255,128,0), + Scalar(255,255,0), + Scalar(0,255,0), + Scalar(0,128,255), + Scalar(0,255,255), + Scalar(0,0,255), + Scalar(255,0,255) + }; + Mat gray, smallImg; cvtColor( img, gray, COLOR_BGR2GRAY ); - resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); + double fx = 1 / scale; + resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR ); equalizeHist( smallImg, smallImg ); t = (double)cvGetTickCount(); @@ -221,8 +203,7 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); if( tryflip ) { @@ -231,8 +212,7 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); for( vector::const_iterator r = faces2.begin(); r != faces2.end(); r++ ) { @@ -241,44 +221,45 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, } t = (double)cvGetTickCount() - t; printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) ); - for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) + for ( size_t i = 0; i < faces.size(); i++ ) { + Rect r = faces[i]; Mat smallImgROI; vector nestedObjects; Point center; Scalar color = colors[i%8]; int radius; - double aspect_ratio = (double)r->width/r->height; + double aspect_ratio = (double)r.width/r.height; if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ) { - center.x = cvRound((r->x + r->width*0.5)*scale); - center.y = cvRound((r->y + r->height*0.5)*scale); - radius = cvRound((r->width + r->height)*0.25*scale); + center.x = cvRound((r.x + r.width*0.5)*scale); + center.y = cvRound((r.y + r.height*0.5)*scale); + radius = cvRound((r.width + r.height)*0.25*scale); circle( img, center, radius, color, 3, 8, 0 ); } else - rectangle( img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)), - cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)), + rectangle( img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)), + cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)), color, 3, 8, 0); if( nestedCascade.empty() ) continue; - smallImgROI = smallImg(*r); + smallImgROI = smallImg( r ); nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH //|CASCADE_DO_CANNY_PRUNING - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); - for( vector::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ ) + for ( size_t j = 0; j < nestedObjects.size(); j++ ) { - center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale); - center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale); - radius = cvRound((nr->width + nr->height)*0.25*scale); + Rect nr = nestedObjects[j]; + center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale); + center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale); + radius = cvRound((nr.width + nr.height)*0.25*scale); circle( img, center, radius, color, 3, 8, 0 ); } } - cv::imshow( "result", img ); + imshow( "result", img ); } diff --git a/samples/cpp/smiledetect.cpp b/samples/cpp/smiledetect.cpp index 305cdad8d..d15183fb0 100644 --- a/samples/cpp/smiledetect.cpp +++ b/samples/cpp/smiledetect.cpp @@ -1,15 +1,7 @@ #include "opencv2/objdetect.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/core/utility.hpp" - -#include "opencv2/videoio/videoio_c.h" -#include "opencv2/highgui/highgui_c.h" - -#include #include -#include -#include using namespace std; using namespace cv; @@ -36,11 +28,10 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, string cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml"; string nestedCascadeName = "../../data/haarcascades/haarcascade_smile.xml"; - int main( int argc, const char** argv ) { - CvCapture* capture = 0; - Mat frame, frameCopy, image; + VideoCapture capture; + Mat frame, image; const string scaleOpt = "--scale="; size_t scaleOptLen = scaleOpt.length(); const string cascadeOpt = "--cascade="; @@ -104,44 +95,34 @@ int main( int argc, const char** argv ) if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') ) { - capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' ); int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ; - if(!capture) cout << "Capture from CAM " << c << " didn't work" << endl; + if(!capture.open(c)) + cout << "Capture from camera #" << c << " didn't work" << endl; } else if( inputName.size() ) { - capture = cvCaptureFromAVI( inputName.c_str() ); - if(!capture) cout << "Capture from AVI didn't work" << endl; + if(!capture.open( inputName )) + cout << "Could not read " << inputName << endl; } - cvNamedWindow( "result", 1 ); - - if( capture ) + if( capture.isOpened() ) { - cout << "In capture ..." << endl; + cout << "Video capturing has been started ..." << endl; cout << endl << "NOTE: Smile intensity will only be valid after a first smile has been detected" << endl; for(;;) { - IplImage* iplImg = cvQueryFrame( capture ); - frame = cv::cvarrToMat(iplImg); + capture >> frame; if( frame.empty() ) break; - if( iplImg->origin == IPL_ORIGIN_TL ) - frame.copyTo( frameCopy ); - else - flip( frame, frameCopy, 0 ); - detectAndDraw( frameCopy, cascade, nestedCascade, scale, tryflip ); + Mat frame1 = frame.clone(); + detectAndDraw( frame1, cascade, nestedCascade, scale, tryflip ); - if( waitKey( 10 ) >= 0 ) - goto _cleanup_; + int c = waitKey(10); + if( c == 27 || c == 'q' || c == 'Q' ) + break; } - - waitKey(0); - -_cleanup_: - cvReleaseCapture( &capture ); } else { @@ -150,7 +131,6 @@ _cleanup_: return -1; } - cvDestroyWindow("result"); return 0; } @@ -158,28 +138,31 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, double scale, bool tryflip) { - int i = 0; vector faces, faces2; - const static Scalar colors[] = { CV_RGB(0,0,255), - CV_RGB(0,128,255), - CV_RGB(0,255,255), - CV_RGB(0,255,0), - CV_RGB(255,128,0), - CV_RGB(255,255,0), - CV_RGB(255,0,0), - CV_RGB(255,0,255)} ; - Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); + const static Scalar colors[] = + { + Scalar(255,0,0), + Scalar(255,128,0), + Scalar(255,255,0), + Scalar(0,255,0), + Scalar(0,128,255), + Scalar(0,255,255), + Scalar(0,0,255), + Scalar(255,0,255) + }; + Mat gray, smallImg; cvtColor( img, gray, COLOR_BGR2GRAY ); - resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); + + double fx = 1 / scale; + resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR ); equalizeHist( smallImg, smallImg ); cascade.detectMultiScale( smallImg, faces, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); if( tryflip ) { @@ -188,8 +171,7 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); for( vector::const_iterator r = faces2.begin(); r != faces2.end(); r++ ) { @@ -197,38 +179,38 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, } } - for( vector::iterator r = faces.begin(); r != faces.end(); r++, i++ ) + for ( size_t i = 0; i < faces.size(); i++ ) { + Rect r = faces[i]; Mat smallImgROI; vector nestedObjects; Point center; Scalar color = colors[i%8]; int radius; - double aspect_ratio = (double)r->width/r->height; + double aspect_ratio = (double)r.width/r.height; if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ) { - center.x = cvRound((r->x + r->width*0.5)*scale); - center.y = cvRound((r->y + r->height*0.5)*scale); - radius = cvRound((r->width + r->height)*0.25*scale); + center.x = cvRound((r.x + r.width*0.5)*scale); + center.y = cvRound((r.y + r.height*0.5)*scale); + radius = cvRound((r.width + r.height)*0.25*scale); circle( img, center, radius, color, 3, 8, 0 ); } else - rectangle( img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)), - cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)), + rectangle( img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)), + cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)), color, 3, 8, 0); - const int half_height=cvRound((float)r->height/2); - r->y=r->y + half_height; - r->height = half_height; - smallImgROI = smallImg(*r); + const int half_height=cvRound((float)r.height/2); + r.y=r.y + half_height; + r.height = half_height-1; + smallImgROI = smallImg( r ); nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 1.1, 0, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH //|CASCADE_DO_CANNY_PRUNING - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); // The number of detected neighbors depends on image size (and also illumination, etc.). The @@ -243,9 +225,9 @@ void detectAndDraw( Mat& img, CascadeClassifier& cascade, // Draw rectangle on the left side of the image reflecting smile intensity float intensityZeroOne = ((float)smile_neighbors - min_neighbors) / (max_neighbors - min_neighbors + 1); int rect_height = cvRound((float)img.rows * intensityZeroOne); - CvScalar col = CV_RGB((float)255 * intensityZeroOne, 0, 0); + Scalar col = Scalar((float)255 * intensityZeroOne, 0, 0); rectangle(img, cvPoint(0, img.rows), cvPoint(img.cols/10, img.rows - rect_height), col, -1); } - cv::imshow( "result", img ); + imshow( "result", img ); } diff --git a/samples/cpp/stereo_calib.cpp b/samples/cpp/stereo_calib.cpp index f25a3e139..12ed3ef1e 100644 --- a/samples/cpp/stereo_calib.cpp +++ b/samples/cpp/stereo_calib.cpp @@ -56,7 +56,7 @@ static int print_help() static void -StereoCalib(const vector& imagelist, Size boardSize, bool useCalibrated=true, bool showRectified=true) +StereoCalib(const vector& imagelist, Size boardSize,bool displayCorners = false, bool useCalibrated=true, bool showRectified=true) { if( imagelist.size() % 2 != 0 ) { @@ -64,7 +64,6 @@ StereoCalib(const vector& imagelist, Size boardSize, bool useCalibrated= return; } - bool displayCorners = false;//true; const int maxScale = 2; const float squareSize = 1.f; // Set this to your actual square size // ARRAY AND VECTOR STORAGE: @@ -165,8 +164,8 @@ StereoCalib(const vector& imagelist, Size boardSize, bool useCalibrated= cout << "Running stereo calibration ...\n"; Mat cameraMatrix[2], distCoeffs[2]; - cameraMatrix[0] = Mat::eye(3, 3, CV_64F); - cameraMatrix[1] = Mat::eye(3, 3, CV_64F); + cameraMatrix[0] = initCameraMatrix2D(objectPoints,imagePoints[0],imageSize,0); + cameraMatrix[1] = initCameraMatrix2D(objectPoints,imagePoints[1],imageSize,0); Mat R, T, E, F; double rms = stereoCalibrate(objectPoints, imagePoints[0], imagePoints[1], @@ -175,6 +174,7 @@ StereoCalib(const vector& imagelist, Size boardSize, bool useCalibrated= imageSize, R, T, E, F, CALIB_FIX_ASPECT_RATIO + CALIB_ZERO_TANGENT_DIST + + CALIB_USE_INTRINSIC_GUESS + CALIB_SAME_FOCAL_LENGTH + CALIB_RATIONAL_MODEL + CALIB_FIX_K3 + CALIB_FIX_K4 + CALIB_FIX_K5, @@ -209,7 +209,7 @@ StereoCalib(const vector& imagelist, Size boardSize, bool useCalibrated= } npoints += npt; } - cout << "average reprojection err = " << err/npoints << endl; + cout << "average epipolar err = " << err/npoints << endl; // save intrinsic parameters FileStorage fs("../data/intrinsics.yml", FileStorage::WRITE); @@ -399,6 +399,6 @@ int main(int argc, char** argv) return print_help(); } - StereoCalib(imagelist, boardSize, true, showRectified); + StereoCalib(imagelist, boardSize,false, true, showRectified); return 0; } diff --git a/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml b/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml index 9976bccb3..98269ecb6 100644 --- a/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml +++ b/samples/cpp/tutorial_code/calib3d/camera_calibration/in_VID5.xml @@ -16,7 +16,7 @@ To use an input video -> give the path of the input video, like "/tmp/x.avi" To use an image list -> give the path to the XML or YAML file containing the list of the images, like "/tmp/circles_list.xml" --> - "images/CameraCalibraation/VID5/VID5.xml" + "images/CameraCalibration/VID5/VID5.xml" 0 @@ -43,4 +43,4 @@ 1 - \ No newline at end of file + diff --git a/samples/data/blox.jpg b/samples/data/blox.jpg new file mode 100644 index 000000000..b682b2c0a Binary files /dev/null and b/samples/data/blox.jpg differ diff --git a/samples/data/butterfly.jpg b/samples/data/butterfly.jpg new file mode 100644 index 000000000..67d60f055 Binary files /dev/null and b/samples/data/butterfly.jpg differ diff --git a/samples/data/chessboard.png b/samples/data/chessboard.png new file mode 100644 index 000000000..39bb399e8 Binary files /dev/null and b/samples/data/chessboard.png differ diff --git a/samples/data/home.jpg b/samples/data/home.jpg new file mode 100644 index 000000000..7528a7d77 Binary files /dev/null and b/samples/data/home.jpg differ diff --git a/samples/data/left.jpg b/samples/data/left.jpg new file mode 100644 index 000000000..f4c26303a Binary files /dev/null and b/samples/data/left.jpg differ diff --git a/samples/data/messi5.jpg b/samples/data/messi5.jpg new file mode 100644 index 000000000..cd437610f Binary files /dev/null and b/samples/data/messi5.jpg differ diff --git a/samples/data/right.jpg b/samples/data/right.jpg new file mode 100644 index 000000000..4a4bc5345 Binary files /dev/null and b/samples/data/right.jpg differ diff --git a/samples/gpu/super_resolution.cpp b/samples/gpu/super_resolution.cpp index f106f76d3..026afd971 100644 --- a/samples/gpu/super_resolution.cpp +++ b/samples/gpu/super_resolution.cpp @@ -63,7 +63,7 @@ int main(int argc, const char* argv[]) "{ i iterations | 180 | Iteration count }" "{ t temporal | 4 | Radius of the temporal search area }" "{ f flow | farneback | Optical flow algorithm (farneback, simple, tvl1, brox, pyrlk) }" - "{ g | false | CPU as default device, cuda for CUDA }" + "{ g gpu | false | CPU as default device, cuda for CUDA }" "{ h help | false | Print help message }" ); diff --git a/samples/python2/_coverage.py b/samples/python2/_coverage.py index 4b23370b5..5ec3e18a9 100755 --- a/samples/python2/_coverage.py +++ b/samples/python2/_coverage.py @@ -4,6 +4,9 @@ Utility for measuring python opencv API coverage by samples. ''' +# Python 2/3 compatibility +from __future__ import print_function + from glob import glob import cv2 import re @@ -13,7 +16,7 @@ if __name__ == '__main__': found = set() for fn in glob('*.py'): - print ' --- ', fn + print(' --- ', fn) code = open(fn).read() found |= set(re.findall('cv2?\.\w+', code)) @@ -23,4 +26,4 @@ if __name__ == '__main__': f.write('\n'.join(sorted(cv2_unused))) r = 1.0 * len(cv2_used) / len(cv2_callable) - print '\ncv2 api coverage: %d / %d (%.1f%%)' % ( len(cv2_used), len(cv2_callable), r*100 ) + print('\ncv2 api coverage: %d / %d (%.1f%%)' % ( len(cv2_used), len(cv2_callable), r*100 )) diff --git a/samples/python2/browse.py b/samples/python2/browse.py index 462cd1762..317a8db11 100755 --- a/samples/python2/browse.py +++ b/samples/python2/browse.py @@ -12,6 +12,14 @@ browse.py [image filename] ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 @@ -19,21 +27,21 @@ import cv2 import sys if __name__ == '__main__': - print 'This sample shows how to implement a simple hi resolution image navigation.' - print 'USAGE: browse.py [image filename]' - print + print('This sample shows how to implement a simple hi resolution image navigation.') + print('USAGE: browse.py [image filename]') + print() if len(sys.argv) > 1: fn = sys.argv[1] - print 'loading %s ...' % fn + print('loading %s ...' % fn) img = cv2.imread(fn) if img is None: - print 'Failed to load fn:', fn + print('Failed to load fn:', fn) sys.exit(1) else: sz = 4096 - print 'generating %dx%d procedural image ...' % (sz, sz) + print('generating %dx%d procedural image ...' % (sz, sz)) img = np.zeros((sz, sz), np.uint8) track = np.cumsum(np.random.rand(500000, 2)-0.5, axis=0) track = np.int32(track*10 + (sz/2, sz/2)) diff --git a/samples/python2/calibrate.py b/samples/python2/calibrate.py index 9f6f60cb7..24e4aa7d0 100755 --- a/samples/python2/calibrate.py +++ b/samples/python2/calibrate.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -41,10 +44,10 @@ if __name__ == '__main__': img_points = [] h, w = 0, 0 for fn in img_names: - print 'processing %s...' % fn, + print('processing %s...' % fn,) img = cv2.imread(fn, 0) if img is None: - print "Failed to load", fn + print("Failed to load", fn) continue h, w = img.shape[:2] @@ -58,15 +61,15 @@ if __name__ == '__main__': path, name, ext = splitfn(fn) cv2.imwrite('%s/%s_chess.bmp' % (debug_dir, name), vis) if not found: - print 'chessboard not found' + print('chessboard not found') continue img_points.append(corners.reshape(-1, 2)) obj_points.append(pattern_points) - print 'ok' + print('ok') rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, (w, h), None, None) - print "RMS:", rms - print "camera matrix:\n", camera_matrix - print "distortion coefficients: ", dist_coefs.ravel() + print("RMS:", rms) + print("camera matrix:\n", camera_matrix) + print("distortion coefficients: ", dist_coefs.ravel()) cv2.destroyAllWindows() diff --git a/samples/python2/camshift.py b/samples/python2/camshift.py index 72c790803..867cee9b4 100755 --- a/samples/python2/camshift.py +++ b/samples/python2/camshift.py @@ -22,6 +22,14 @@ Keys: b - toggle back-projected probability visualization ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 @@ -46,6 +54,7 @@ class App(object): if event == cv2.EVENT_LBUTTONDOWN: self.drag_start = (x, y) self.tracking_state = 0 + return if self.drag_start: if flags & cv2.EVENT_FLAG_LBUTTON: h, w = self.frame.shape[:2] @@ -103,7 +112,7 @@ class App(object): try: cv2.ellipse(vis, track_box, (0, 0, 255), 2) except: - print track_box + print(track_box) cv2.imshow('camshift', vis) @@ -121,5 +130,5 @@ if __name__ == '__main__': video_src = sys.argv[1] except: video_src = 0 - print __doc__ + print(__doc__) App(video_src).run() diff --git a/samples/python2/coherence.py b/samples/python2/coherence.py index 46d7414af..8ca61fcb2 100755 --- a/samples/python2/coherence.py +++ b/samples/python2/coherence.py @@ -9,6 +9,14 @@ inspired by http://www.mia.uni-saarland.de/Publications/weickert-dagm03.pdf ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 @@ -16,7 +24,7 @@ def coherence_filter(img, sigma = 11, str_sigma = 11, blend = 0.5, iter_n = 4): h, w = img.shape[:2] for i in xrange(iter_n): - print i, + print(i) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) eigen = cv2.cornerEigenValsAndVecs(gray, str_sigma, 3) @@ -34,7 +42,7 @@ def coherence_filter(img, sigma = 11, str_sigma = 11, blend = 0.5, iter_n = 4): img1 = ero img1[m] = dil[m] img = np.uint8(img*(1.0 - blend) + img1*blend) - print 'done' + print('done') return img @@ -54,7 +62,7 @@ if __name__ == '__main__': sigma = cv2.getTrackbarPos('sigma', 'control')*2+1 str_sigma = cv2.getTrackbarPos('str_sigma', 'control')*2+1 blend = cv2.getTrackbarPos('blend', 'control') / 10.0 - print 'sigma: %d str_sigma: %d blend_coef: %f' % (sigma, str_sigma, blend) + print('sigma: %d str_sigma: %d blend_coef: %f' % (sigma, str_sigma, blend)) dst = coherence_filter(src, sigma=sigma, str_sigma = str_sigma, blend = blend) cv2.imshow('dst', dst) @@ -64,7 +72,7 @@ if __name__ == '__main__': cv2.createTrackbar('str_sigma', 'control', 9, 15, nothing) - print 'Press SPACE to update the image\n' + print('Press SPACE to update the image\n') cv2.imshow('src', src) update() diff --git a/samples/python2/common.py b/samples/python2/common.py index 0ad811ae2..785fb6c8f 100755 --- a/samples/python2/common.py +++ b/samples/python2/common.py @@ -4,6 +4,14 @@ This module contains some common routines used by other samples. ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + from functools import reduce + import numpy as np import cv2 @@ -70,7 +78,8 @@ def mtx2rvec(R): axis = np.cross(vt[0], vt[1]) return axis * np.arctan2(s, c) -def draw_str(dst, (x, y), s): +def draw_str(dst, target, s): + x, y = target cv2.putText(dst, s, (x+1, y+1), cv2.FONT_HERSHEY_PLAIN, 1.0, (0, 0, 0), thickness = 2, lineType=cv2.LINE_AA) cv2.putText(dst, s, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.0, (255, 255, 255), lineType=cv2.LINE_AA) @@ -135,12 +144,12 @@ def clock(): @contextmanager def Timer(msg): - print msg, '...', + print(msg, '...',) start = clock() try: yield finally: - print "%.2f ms" % ((clock()-start)*1000) + print("%.2f ms" % ((clock()-start)*1000)) class StatValue: def __init__(self, smooth_coef = 0.5): @@ -192,7 +201,11 @@ class RectSelector: def grouper(n, iterable, fillvalue=None): '''grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx''' args = [iter(iterable)] * n - return it.izip_longest(fillvalue=fillvalue, *args) + if PY3: + output = it.zip_longest(fillvalue=fillvalue, *args) + else: + output = it.izip_longest(fillvalue=fillvalue, *args) + return output def mosaic(w, imgs): '''Make a grid from images. @@ -201,7 +214,10 @@ def mosaic(w, imgs): imgs -- images (must have same size and format) ''' imgs = iter(imgs) - img0 = imgs.next() + if PY3: + img0 = next(imgs) + else: + img0 = imgs.next() pad = np.zeros_like(img0) imgs = it.chain([img0], imgs) rows = grouper(w, imgs, pad) diff --git a/samples/python2/deconvolution.py b/samples/python2/deconvolution.py index bbb1567bd..ce798538b 100755 --- a/samples/python2/deconvolution.py +++ b/samples/python2/deconvolution.py @@ -30,6 +30,9 @@ Examples: [1] http://en.wikipedia.org/wiki/Wiener_deconvolution ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -63,7 +66,7 @@ def defocus_kernel(d, sz=65): if __name__ == '__main__': - print __doc__ + print(__doc__) import sys, getopt opts, args = getopt.getopt(sys.argv[1:], '', ['circle', 'angle=', 'd=', 'snr=']) opts = dict(opts) @@ -76,7 +79,7 @@ if __name__ == '__main__': img = cv2.imread(fn, 0) if img is None: - print 'Failed to load fn1:', fn1 + print('Failed to load fn1:', fn1) sys.exit(1) img = np.float32(img)/255.0 diff --git a/samples/python2/demo.py b/samples/python2/demo.py index 03d624ddc..864953a31 100755 --- a/samples/python2/demo.py +++ b/samples/python2/demo.py @@ -4,16 +4,25 @@ Sample-launcher application. ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + # local modules from common import splitfn # built-in modules -import sys import webbrowser -import Tkinter as tk from glob import glob from subprocess import Popen -from ScrolledText import ScrolledText + +if PY3: + import tkinter as tk + from tkinter.scrolledtext import ScrolledText +else: + import Tkinter as tk + from ScrolledText import ScrolledText #from IPython.Shell import IPShellEmbed @@ -97,14 +106,17 @@ class App: run_btn.pack() def on_link(self, url): - print url + print(url) webbrowser.open(url) def on_demo_select(self, evt): name = self.demos_lb.get( self.demos_lb.curselection()[0] ) fn = self.samples[name] loc = {} - execfile(fn, loc) + if PY3: + exec(open(fn).read(), loc) + else: + execfile(fn, loc) descr = loc.get('__doc__', 'no-description') self.linker.reset() @@ -152,7 +164,7 @@ class App: def on_run(self, *args): cmd = self.cmd_entry.get() - print 'running:', cmd + print('running:', cmd) Popen(sys.executable + ' ' + cmd, shell=True) def run(self): diff --git a/samples/python2/dft.py b/samples/python2/dft.py index a1622b53e..d617438a8 100755 --- a/samples/python2/dft.py +++ b/samples/python2/dft.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Python 2/3 compatibility +from __future__ import print_function + import cv2 import numpy as np import sys @@ -57,7 +60,7 @@ if __name__ == "__main__": im = cv2.imread(sys.argv[1]) else : im = cv2.imread('../data/baboon.jpg') - print "usage : python dft.py " + print("usage : python dft.py ") # convert to grayscale im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) diff --git a/samples/python2/distrans.py b/samples/python2/distrans.py index 819a06c9b..00e173d52 100755 --- a/samples/python2/distrans.py +++ b/samples/python2/distrans.py @@ -11,6 +11,8 @@ Keys: v - toggle voronoi mode ''' +# Python 2/3 compatibility +from __future__ import print_function import numpy as np import cv2 @@ -23,11 +25,11 @@ if __name__ == '__main__': fn = sys.argv[1] except: fn = '../data/fruits.jpg' - print __doc__ + print(__doc__) img = cv2.imread(fn, 0) if img is None: - print 'Failed to load fn:', fn + print('Failed to load fn:', fn) sys.exit(1) cm = make_cmap('jet') @@ -62,7 +64,7 @@ if __name__ == '__main__': break if ch == ord('v'): voronoi = not voronoi - print 'showing', ['distance', 'voronoi'][voronoi] + print('showing', ['distance', 'voronoi'][voronoi]) update() if need_update: update() diff --git a/samples/python2/edge.py b/samples/python2/edge.py index 413bf8859..61d8466bc 100755 --- a/samples/python2/edge.py +++ b/samples/python2/edge.py @@ -10,6 +10,9 @@ Usage: ''' +# Python 2/3 compatibility +from __future__ import print_function + import cv2 # relative module @@ -20,7 +23,7 @@ import sys if __name__ == '__main__': - print __doc__ + print(__doc__) try: fn = sys.argv[1] diff --git a/samples/python2/facedetect.py b/samples/python2/facedetect.py index 8c6b27ab1..2349087dc 100755 --- a/samples/python2/facedetect.py +++ b/samples/python2/facedetect.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -24,7 +27,7 @@ def draw_rects(img, rects, color): if __name__ == '__main__': import sys, getopt - print help_message + print(help_message) args, video_src = getopt.getopt(sys.argv[1:], '', ['cascade=', 'nested-cascade=']) try: diff --git a/samples/python2/fitline.py b/samples/python2/fitline.py index 1c0d9e770..95fb2b8d1 100755 --- a/samples/python2/fitline.py +++ b/samples/python2/fitline.py @@ -22,6 +22,11 @@ f - change distance function ESC - exit ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + import numpy as np import cv2 @@ -43,7 +48,11 @@ def sample_line(p1, p2, n, noise=0.0): return p1 + (p2-p1)*t + np.random.normal(size=(n, 2))*noise dist_func_names = it.cycle('DIST_L2 DIST_L1 DIST_L12 DIST_FAIR DIST_WELSCH DIST_HUBER'.split()) -cur_func_name = dist_func_names.next() + +if PY3: + cur_func_name = next(dist_func_names) +else: + cur_func_name = dist_func_names.next() def update(_=None): noise = cv2.getTrackbarPos('noise', 'fit line') @@ -71,7 +80,7 @@ def update(_=None): cv2.imshow('fit line', img) if __name__ == '__main__': - print __doc__ + print(__doc__) cv2.namedWindow('fit line') cv2.createTrackbar('noise', 'fit line', 3, 50, update) @@ -81,6 +90,9 @@ if __name__ == '__main__': update() ch = cv2.waitKey(0) & 0xFF if ch == ord('f'): - cur_func_name = dist_func_names.next() + if PY3: + cur_func_name = next(dist_func_names) + else: + cur_func_name = dist_func_names.next() if ch == 27: break diff --git a/samples/python2/floodfill.py b/samples/python2/floodfill.py index 5152f30c1..161c6323f 100755 --- a/samples/python2/floodfill.py +++ b/samples/python2/floodfill.py @@ -14,6 +14,9 @@ Keys: ESC - exit ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -23,11 +26,11 @@ if __name__ == '__main__': fn = sys.argv[1] except: fn = '../data/fruits.jpg' - print __doc__ + print(__doc__) img = cv2.imread(fn, True) if img is None: - print 'Failed to load image file:', fn + print('Failed to load image file:', fn) sys.exit(1) h, w = img.shape[:2] @@ -68,10 +71,10 @@ if __name__ == '__main__': break if ch == ord('f'): fixed_range = not fixed_range - print 'using %s range' % ('floating', 'fixed')[fixed_range] + print('using %s range' % ('floating', 'fixed')[fixed_range]) update() if ch == ord('c'): connectivity = 12-connectivity - print 'connectivity =', connectivity + print('connectivity =', connectivity) update() cv2.destroyAllWindows() diff --git a/samples/python2/gabor_threads.py b/samples/python2/gabor_threads.py index b004fb758..f7d62c17e 100755 --- a/samples/python2/gabor_threads.py +++ b/samples/python2/gabor_threads.py @@ -14,6 +14,9 @@ gabor_threads.py [image filename] ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 from multiprocessing.pool import ThreadPool @@ -48,7 +51,7 @@ if __name__ == '__main__': import sys from common import Timer - print __doc__ + print(__doc__) try: img_fn = sys.argv[1] except: @@ -56,7 +59,7 @@ if __name__ == '__main__': img = cv2.imread(img_fn) if img is None: - print 'Failed to load image file:', img_fn + print('Failed to load image file:', img_fn) sys.exit(1) filters = build_filters() @@ -66,7 +69,7 @@ if __name__ == '__main__': with Timer('running multi-threaded'): res2 = process_threaded(img, filters) - print 'res1 == res2: ', (res1 == res2).all() + print('res1 == res2: ', (res1 == res2).all()) cv2.imshow('img', img) cv2.imshow('result', res2) cv2.waitKey() diff --git a/samples/python2/grabcut.py b/samples/python2/grabcut.py index 2c8aa1ef1..19378e6cc 100644 --- a/samples/python2/grabcut.py +++ b/samples/python2/grabcut.py @@ -27,6 +27,9 @@ Key 's' - To save the results =============================================================================== ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 import sys @@ -72,13 +75,13 @@ def onmouse(event,x,y,flags,param): cv2.rectangle(img,(ix,iy),(x,y),BLUE,2) rect = (min(ix,x),min(iy,y),abs(ix-x),abs(iy-y)) rect_or_mask = 0 - print " Now press the key 'n' a few times until no further change \n" + print(" Now press the key 'n' a few times until no further change \n") # draw touchup curves if event == cv2.EVENT_LBUTTONDOWN: if rect_over == False: - print "first draw rectangle \n" + print("first draw rectangle \n") else: drawing = True cv2.circle(img,(x,y),thickness,value['color'],-1) @@ -98,14 +101,14 @@ def onmouse(event,x,y,flags,param): if __name__ == '__main__': # print documentation - print __doc__ + print(__doc__) # Loading images if len(sys.argv) == 2: filename = sys.argv[1] # for drawing purposes else: - print "No input image given, so loading default image, ../data/lena.jpg \n" - print "Correct Usage: python grabcut.py \n" + print("No input image given, so loading default image, ../data/lena.jpg \n") + print("Correct Usage: python grabcut.py \n") filename = '../data/lena.jpg' img = cv2.imread(filename) @@ -119,8 +122,8 @@ if __name__ == '__main__': cv2.setMouseCallback('input',onmouse) cv2.moveWindow('input',img.shape[1]+10,90) - print " Instructions: \n" - print " Draw a rectangle around the object using right mouse button \n" + print(" Instructions: \n") + print(" Draw a rectangle around the object using right mouse button \n") while(1): @@ -132,10 +135,10 @@ if __name__ == '__main__': if k == 27: # esc to exit break elif k == ord('0'): # BG drawing - print " mark background regions with left mouse button \n" + print(" mark background regions with left mouse button \n") value = DRAW_BG elif k == ord('1'): # FG drawing - print " mark foreground regions with left mouse button \n" + print(" mark foreground regions with left mouse button \n") value = DRAW_FG elif k == ord('2'): # PR_BG drawing value = DRAW_PR_BG @@ -145,9 +148,9 @@ if __name__ == '__main__': bar = np.zeros((img.shape[0],5,3),np.uint8) res = np.hstack((img2,bar,img,bar,output)) cv2.imwrite('grabcut_output.png',res) - print " Result saved as image \n" + print(" Result saved as image \n") elif k == ord('r'): # reset everything - print "resetting \n" + print("resetting \n") rect = (0,0,1,1) drawing = False rectangle = False @@ -158,8 +161,8 @@ if __name__ == '__main__': mask = np.zeros(img.shape[:2],dtype = np.uint8) # mask initialized to PR_BG output = np.zeros(img.shape,np.uint8) # output image to be shown elif k == ord('n'): # segment the image - print """ For finer touchups, mark foreground and background after pressing keys 0-3 - and again press 'n' \n""" + print(""" For finer touchups, mark foreground and background after pressing keys 0-3 + and again press 'n' \n""") if (rect_or_mask == 0): # grabcut with rect bgdmodel = np.zeros((1,65),np.float64) fgdmodel = np.zeros((1,65),np.float64) diff --git a/samples/python2/houghcircles.py b/samples/python2/houghcircles.py index 9d68c2ce8..fe87d8f3e 100755 --- a/samples/python2/houghcircles.py +++ b/samples/python2/houghcircles.py @@ -6,13 +6,16 @@ Usage: ./houghcircles.py [] image argument defaults to ../data/board.jpg ''' +# Python 2/3 compatibility +from __future__ import print_function + import cv2 import numpy as np import sys if __name__ == '__main__': - print __doc__ + print(__doc__) try: fn = sys.argv[1] except: diff --git a/samples/python2/houghlines.py b/samples/python2/houghlines.py index cd25a56f8..674b26ec7 100755 --- a/samples/python2/houghlines.py +++ b/samples/python2/houghlines.py @@ -4,6 +4,9 @@ This example illustrates how to use Hough Transform to find lines Usage: ./houghlines.py [] image argument defaults to ../data/pic1.png ''' +# Python 2/3 compatibility +from __future__ import print_function + import cv2 import numpy as np import sys @@ -15,7 +18,7 @@ if __name__ == '__main__': fn = sys.argv[1] except: fn = "../data/pic1.png" - print __doc__ + print(__doc__) src = cv2.imread(fn) dst = cv2.Canny(src, 50, 200) cdst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR) diff --git a/samples/python2/inpaint.py b/samples/python2/inpaint.py index 4ff1ddb6e..0ca72f1a2 100755 --- a/samples/python2/inpaint.py +++ b/samples/python2/inpaint.py @@ -15,6 +15,9 @@ Keys: ESC - exit ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 from common import Sketcher @@ -26,11 +29,11 @@ if __name__ == '__main__': except: fn = '../data/fruits.jpg' - print __doc__ + print(__doc__) img = cv2.imread(fn) if img is None: - print 'Failed to load image file:', fn + print('Failed to load image file:', fn) sys.exit(1) img_mark = img.copy() diff --git a/samples/python2/kalman.py b/samples/python2/kalman.py index 101f1ea56..8e3748b4d 100755 --- a/samples/python2/kalman.py +++ b/samples/python2/kalman.py @@ -11,6 +11,13 @@ Pressing any key (except ESC) will reset the tracking with a different speed. Pressing ESC will stop the program. """ +# Python 2/3 compatibility +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + long = int + import cv2 from math import cos, sin import numpy as np @@ -21,7 +28,7 @@ if __name__ == "__main__": img_width = 500 kalman = cv2.KalmanFilter(2, 1, 0) - code = -1L + code = long(-1) cv2.namedWindow("Kalman") diff --git a/samples/python2/lappyr.py b/samples/python2/lappyr.py index 3cf2679b0..19f5bd918 100755 --- a/samples/python2/lappyr.py +++ b/samples/python2/lappyr.py @@ -12,6 +12,14 @@ References: Alexander Mordvintsev 6/10/12 ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 import video @@ -38,7 +46,7 @@ def merge_lappyr(levels): if __name__ == '__main__': import sys - print __doc__ + print(__doc__) try: fn = sys.argv[1] diff --git a/samples/python2/lk_homography.py b/samples/python2/lk_homography.py index ae8b2d49b..a9e92546c 100755 --- a/samples/python2/lk_homography.py +++ b/samples/python2/lk_homography.py @@ -20,6 +20,9 @@ SPACE - start tracking r - toggle RANSAC ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 import video @@ -108,7 +111,7 @@ def main(): except: video_src = 0 - print __doc__ + print(__doc__) App(video_src).run() cv2.destroyAllWindows() diff --git a/samples/python2/lk_track.py b/samples/python2/lk_track.py index 1ff90ff7e..8aa94fe64 100755 --- a/samples/python2/lk_track.py +++ b/samples/python2/lk_track.py @@ -18,6 +18,9 @@ Keys ESC - exit ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 import video @@ -93,7 +96,7 @@ def main(): except: video_src = 0 - print __doc__ + print(__doc__) App(video_src).run() cv2.destroyAllWindows() diff --git a/samples/python2/logpolar.py b/samples/python2/logpolar.py index 783c7b81a..60695bfd8 100644 --- a/samples/python2/logpolar.py +++ b/samples/python2/logpolar.py @@ -1,4 +1,8 @@ #!/usr/bin/env python + +# Python 2/3 compatibility +from __future__ import print_function + import cv2 if __name__ == '__main__': @@ -10,7 +14,7 @@ if __name__ == '__main__': img = cv2.imread(fn) if img is None: - print 'Failed to load image file:', fn + print('Failed to load image file:', fn) sys.exit(1) img2 = cv2.logPolar(img, (img.shape[0]/2, img.shape[1]/2), 40, cv2.WARP_FILL_OUTLIERS) diff --git a/samples/python2/morphology.py b/samples/python2/morphology.py index 76fa76c69..be287d33d 100755 --- a/samples/python2/morphology.py +++ b/samples/python2/morphology.py @@ -12,12 +12,17 @@ Keys: ESC - exit ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + import numpy as np import cv2 if __name__ == '__main__': - print __doc__ + print(__doc__) import sys from itertools import cycle @@ -31,15 +36,20 @@ if __name__ == '__main__': img = cv2.imread(fn) if img is None: - print 'Failed to load image file:', fn + print('Failed to load image file:', fn) sys.exit(1) cv2.imshow('original', img) modes = cycle(['erode/dilate', 'open/close', 'blackhat/tophat', 'gradient']) str_modes = cycle(['ellipse', 'rect', 'cross']) - cur_mode = modes.next() - cur_str_mode = str_modes.next() + + if PY3: + cur_mode = next(modes) + cur_str_mode = next(str_modes) + else: + cur_mode = modes.next() + cur_str_mode = str_modes.next() def update(dummy=None): sz = cv2.getTrackbarPos('op/size', 'morphology') @@ -73,8 +83,14 @@ if __name__ == '__main__': if ch == 27: break if ch == ord('1'): - cur_mode = modes.next() + if PY3: + cur_mode = next(modes) + else: + cur_mode = modes.next() if ch == ord('2'): - cur_str_mode = str_modes.next() + if PY3: + cur_str_mode = next(str_modes) + else: + cur_str_mode = str_modes.next() update() cv2.destroyAllWindows() diff --git a/samples/python2/mosse.py b/samples/python2/mosse.py index 81196dcc3..29a3a697f 100755 --- a/samples/python2/mosse.py +++ b/samples/python2/mosse.py @@ -21,6 +21,14 @@ Keys: http://www.cs.colostate.edu/~bolme/publications/Bolme2010Tracking.pdf ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 from common import draw_str, RectSelector @@ -178,7 +186,7 @@ class App: if __name__ == '__main__': - print __doc__ + print (__doc__) import sys, getopt opts, args = getopt.getopt(sys.argv[1:], '', ['pause']) opts = dict(opts) diff --git a/samples/python2/mouse_and_match.py b/samples/python2/mouse_and_match.py index 7937140e3..c0b03d77e 100755 --- a/samples/python2/mouse_and_match.py +++ b/samples/python2/mouse_and_match.py @@ -8,6 +8,10 @@ Demonstrate using a mouse to interact with an image: When they let go of the mouse, it correlates (using matchTemplate) that patch with the image. ESC to exit ''' + +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -46,7 +50,7 @@ def onmouse(event, x, y, flags, param): cv2.rectangle(img, (sel[0], sel[1]), (sel[2], sel[3]), (0,255,255), 1) cv2.imshow("gray", img) else: - print "selection is complete" + print("selection is complete") drag_start = None if __name__ == '__main__': @@ -61,7 +65,7 @@ if __name__ == '__main__': for infile in glob.glob( os.path.join(path, '*.*') ): ext = os.path.splitext(infile)[1][1:] #get the filename extenstion if ext == "png" or ext == "jpg" or ext == "bmp" or ext == "tiff" or ext == "pbm": - print infile + print(infile) img=cv2.imread(infile,1) if img == None: diff --git a/samples/python2/opencv_version.py b/samples/python2/opencv_version.py index 8c966f18e..44f197736 100644 --- a/samples/python2/opencv_version.py +++ b/samples/python2/opencv_version.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Python 2/3 compatibility +from __future__ import print_function + import cv2 if __name__ == '__main__': @@ -10,9 +13,9 @@ if __name__ == '__main__': param = "" if ("--build" == param): - print cv2.getBuildInformation() + print(cv2.getBuildInformation()) elif ("--help" == param): - print "\t--build\n\t\tprint complete build info" - print "\t--help\n\t\tprint this help" + print("\t--build\n\t\tprint complete build info") + print("\t--help\n\t\tprint this help") else: - print "Welcome to OpenCV" + print("Welcome to OpenCV") diff --git a/samples/python2/peopledetect.py b/samples/python2/peopledetect.py index 9d945dbcc..c8843e05e 100755 --- a/samples/python2/peopledetect.py +++ b/samples/python2/peopledetect.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np import cv2 @@ -27,20 +30,20 @@ if __name__ == '__main__': from glob import glob import itertools as it - print help_message + print(help_message) hog = cv2.HOGDescriptor() hog.setSVMDetector( cv2.HOGDescriptor_getDefaultPeopleDetector() ) for fn in it.chain(*map(glob, sys.argv[1:])): - print fn, ' - ', + print(fn, ' - ',) try: img = cv2.imread(fn) if img is None: - print 'Failed to load image file:', fn + print('Failed to load image file:', fn) continue except: - print 'loading error' + print('loading error') continue found, w = hog.detectMultiScale(img, winStride=(8,8), padding=(32,32), scale=1.05) @@ -53,7 +56,7 @@ if __name__ == '__main__': found_filtered.append(r) draw_detections(img, found) draw_detections(img, found_filtered, 3) - print '%d (%d) found' % (len(found_filtered), len(found)) + print('%d (%d) found' % (len(found_filtered), len(found))) cv2.imshow('img', img) ch = 0xFF & cv2.waitKey() if ch == 27: diff --git a/samples/python2/squares.py b/samples/python2/squares.py index 84160a291..cc33144de 100755 --- a/samples/python2/squares.py +++ b/samples/python2/squares.py @@ -6,6 +6,13 @@ Simple "Square Detector" program. Loads several images sequentially and tries to find squares in each image. ''' +# Python 2/3 compatibility +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 diff --git a/samples/python2/turing.py b/samples/python2/turing.py index 94816e6c3..f9926ba90 100755 --- a/samples/python2/turing.py +++ b/samples/python2/turing.py @@ -7,6 +7,14 @@ Multiscale Turing Patterns generator Inspired by http://www.jonathanmccabe.com/Cyclic_Symmetric_Multi-Scale_Turing_Patterns.pdf ''' +# Python 2/3 compatibility +from __future__ import print_function +import sys +PY3 = sys.version_info[0] == 3 + +if PY3: + xrange = range + import numpy as np import cv2 from common import draw_str @@ -20,7 +28,7 @@ Press ESC to stop. ''' if __name__ == '__main__': - print help_message + print(help_message) w, h = 512, 512 @@ -30,7 +38,7 @@ if __name__ == '__main__': if '-o' in args: fn = args['-o'] out = cv2.VideoWriter(args['-o'], cv2.VideoWriter_fourcc(*'DIB '), 30.0, (w, h), False) - print 'writing %s ...' % fn + print('writing %s ...' % fn) a = np.zeros((h, w), np.float32) cv2.randu(a, np.array([0]), np.array([1])) diff --git a/samples/python2/video.py b/samples/python2/video.py index 227b13f37..8bdec7440 100755 --- a/samples/python2/video.py +++ b/samples/python2/video.py @@ -29,6 +29,9 @@ Keys: ''' +# Python 2/3 compatibility +from __future__ import print_function + import numpy as np from numpy import pi, sin, cos @@ -162,7 +165,7 @@ def create_capture(source = 0, fallback = presets['chess']): cap.set(cv2.CAP_PROP_FRAME_WIDTH, w) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, h) if cap is None or not cap.isOpened(): - print 'Warning: unable to open video source: ', source + print('Warning: unable to open video source: ', source) if fallback is not None: return create_capture(fallback, None) return cap @@ -171,7 +174,7 @@ if __name__ == '__main__': import sys import getopt - print __doc__ + print(__doc__) args, sources = getopt.getopt(sys.argv[1:], '', 'shotdir=') args = dict(args) @@ -194,6 +197,6 @@ if __name__ == '__main__': for i, img in enumerate(imgs): fn = '%s/shot_%d_%03d.bmp' % (shotdir, i, shot_idx) cv2.imwrite(fn, img) - print fn, 'saved' + print(fn, 'saved') shot_idx += 1 cv2.destroyAllWindows() diff --git a/samples/python2/video_threaded.py b/samples/python2/video_threaded.py index a638791c8..76d764b62 100755 --- a/samples/python2/video_threaded.py +++ b/samples/python2/video_threaded.py @@ -15,6 +15,8 @@ Keyboard shortcuts: space - switch between multi and single threaded processing ''' +# Python 2/3 compatibility +from __future__ import print_function import numpy as np import cv2 @@ -37,7 +39,7 @@ class DummyTask: if __name__ == '__main__': import sys - print __doc__ + print(__doc__) try: fn = sys.argv[1] diff --git a/samples/python2/video_v4l2.py b/samples/python2/video_v4l2.py new file mode 100644 index 000000000..0f03e6bf0 --- /dev/null +++ b/samples/python2/video_v4l2.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +''' +VideoCapture sample showcasing some features of the Video4Linux2 backend + +Sample shows how VideoCapture class can be used to control parameters +of a webcam such as focus or framerate. +Also the sample provides an example how to access raw images delivered +by the hardware to get a grayscale image in a very efficient fashion. + +Keys: + ESC - exit + g - toggle optimized grayscale conversion + +''' + +import cv2 + +def decode_fourcc(v): + v = int(v) + return "".join([chr((v >> 8 * i) & 0xFF) for i in range(4)]) + +font = cv2.FONT_HERSHEY_SIMPLEX +color = (0, 255, 0) + +cap = cv2.VideoCapture(0) +cap.set(cv2.CAP_PROP_AUTOFOCUS, False) + +cv2.namedWindow("Video") + +convert_rgb = True +fps = int(cap.get(cv2.CAP_PROP_FPS)) +focus = int(cap.get(cv2.CAP_PROP_FOCUS)) * 100 + +cv2.createTrackbar("FPS", "Video", fps, 30, lambda v: cap.set(cv2.CAP_PROP_FPS, v)) +cv2.createTrackbar("Focus", "Video", focus, 100, lambda v: cap.set(cv2.CAP_PROP_FOCUS, v / 100)) + +while True: + status, img = cap.read() + + fourcc = decode_fourcc(cap.get(cv2.CAP_PROP_FOURCC)) + + fps = cap.get(cv2.CAP_PROP_FPS) + + if not bool(cap.get(cv2.CAP_PROP_CONVERT_RGB)): + if fourcc == "MJPG": + img = cv2.imdecode(img, cv2.IMREAD_GRAYSCALE) + elif fourcc == "YUYV": + img = cv2.cvtColor(img, cv2.COLOR_YUV2GRAY_YUYV) + else: + print("unsupported format") + break + + cv2.putText(img, "Mode: {}".format(fourcc), (15, 40), font, 1.0, color) + cv2.putText(img, "FPS: {}".format(fps), (15, 80), font, 1.0, color) + cv2.imshow("Video", img) + + k = cv2.waitKey(1) + + if k == 27: + break + elif k == ord("g"): + convert_rgb = not convert_rgb + cap.set(cv2.CAP_PROP_CONVERT_RGB, convert_rgb) diff --git a/samples/cpp/ufacedetect.cpp b/samples/tapi/ufacedetect.cpp similarity index 80% rename from samples/cpp/ufacedetect.cpp rename to samples/tapi/ufacedetect.cpp index 1e08b3e71..e3c82a2c6 100644 --- a/samples/cpp/ufacedetect.cpp +++ b/samples/tapi/ufacedetect.cpp @@ -1,15 +1,8 @@ #include "opencv2/objdetect.hpp" -#include "opencv2/imgcodecs.hpp" -#include "opencv2/videoio.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/core/utility.hpp" #include "opencv2/core/ocl.hpp" - -#include #include -#include -#include using namespace std; using namespace cv; @@ -20,13 +13,13 @@ static void help() "This classifier can recognize many kinds of rigid objects, once the appropriate classifier is trained.\n" "It's most known use is for faces.\n" "Usage:\n" - "./facedetect [--cascade= this is the primary trained classifier such as frontal face]\n" + "./ufacedetect [--cascade= this is the primary trained classifier such as frontal face]\n" " [--nested-cascade[=nested_cascade_path this an optional secondary classifier such as eyes]]\n" " [--scale=]\n" " [--try-flip]\n" " [filename|camera_index]\n\n" "see facedetect.cmd for one call:\n" - "./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye.xml\" --scale=1.3\n\n" + "./ufacedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --nested-cascade=\"../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml\" --scale=1.3\n\n" "During execution:\n\tHit any key to quit.\n" "\tUsing OpenCV version " << CV_VERSION << "\n" << endl; } @@ -76,7 +69,7 @@ int main( int argc, const char** argv ) } else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 ) { - if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale > 1 ) + if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) ) scale = 1; cout << " from which we read scale = " << scale << endl; } @@ -87,7 +80,7 @@ int main( int argc, const char** argv ) } else if( argv[i][0] == '-' ) { - cerr << "WARNING: Unknown option %s" << argv[i] << endl; + cerr << "WARNING: Unknown option " << argv[i] << endl; } else inputName = argv[i]; @@ -120,8 +113,6 @@ int main( int argc, const char** argv ) } } - namedWindow( "result", 1 ); - if( capture.isOpened() ) { cout << "Video capturing has been started ..." << endl; @@ -133,7 +124,8 @@ int main( int argc, const char** argv ) detectAndDraw( frame, canvas, cascade, nestedCascade, scale, tryflip ); - if( waitKey( 10 ) >= 0 ) + int c = waitKey(10); + if( c == 27 || c == 'q' || c == 'Q' ) break; } } @@ -183,46 +175,44 @@ int main( int argc, const char** argv ) void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade, CascadeClassifier& nestedCascade, - double scale0, bool tryflip ) + double scale, bool tryflip ) { - int i = 0; - double t = 0, scale=1; + double t = 0; vector faces, faces2; const static Scalar colors[] = { - Scalar(0,0,255), - Scalar(0,128,255), - Scalar(0,255,255), - Scalar(0,255,0), + Scalar(255,0,0), Scalar(255,128,0), Scalar(255,255,0), - Scalar(255,0,0), + Scalar(0,255,0), + Scalar(0,128,255), + Scalar(0,255,255), + Scalar(0,0,255), Scalar(255,0,255) }; static UMat gray, smallImg; t = (double)getTickCount(); - resize( img, smallImg, Size(), scale0, scale0, INTER_LINEAR ); - cvtColor( smallImg, gray, COLOR_BGR2GRAY ); - equalizeHist( gray, gray ); + cvtColor( img, gray, COLOR_BGR2GRAY ); + double fx = 1 / scale; + resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR ); + equalizeHist( smallImg, smallImg ); - cascade.detectMultiScale( gray, faces, + cascade.detectMultiScale( smallImg, faces, 1.1, 3, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); if( tryflip ) { - flip(gray, gray, 1); - cascade.detectMultiScale( gray, faces2, + flip(smallImg, smallImg, 1); + cascade.detectMultiScale( smallImg, faces2, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); for( vector::const_iterator r = faces2.begin(); r != faces2.end(); r++ ) { @@ -230,7 +220,7 @@ void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade, } } t = (double)getTickCount() - t; - smallImg.copyTo(canvas); + img.copyTo(canvas); double fps = getTickFrequency()/t; static double avgfps = 0; @@ -242,41 +232,43 @@ void detectAndDraw( UMat& img, Mat& canvas, CascadeClassifier& cascade, putText(canvas, format("OpenCL: %s, fps: %.1f", ocl::useOpenCL() ? "ON" : "OFF", avgfps), Point(50, 30), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0,255,0), 2); - for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) + for ( size_t i = 0; i < faces.size(); i++ ) { + Rect r = faces[i]; vector nestedObjects; Point center; Scalar color = colors[i%8]; int radius; - double aspect_ratio = (double)r->width/r->height; + double aspect_ratio = (double)r.width/r.height; if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ) { - center.x = cvRound((r->x + r->width*0.5)*scale); - center.y = cvRound((r->y + r->height*0.5)*scale); - radius = cvRound((r->width + r->height)*0.25*scale); + center.x = cvRound((r.x + r.width*0.5)*scale); + center.y = cvRound((r.y + r.height*0.5)*scale); + radius = cvRound((r.width + r.height)*0.25*scale); circle( canvas, center, radius, color, 3, 8, 0 ); } else - rectangle( canvas, Point(cvRound(r->x*scale), cvRound(r->y*scale)), - Point(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)), + rectangle( canvas, Point(cvRound(r.x*scale), cvRound(r.y*scale)), + Point(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)), color, 3, 8, 0); if( nestedCascade.empty() ) continue; - UMat smallImgROI = gray(*r); + UMat smallImgROI = smallImg(r); nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 1.1, 2, 0 //|CASCADE_FIND_BIGGEST_OBJECT //|CASCADE_DO_ROUGH_SEARCH //|CASCADE_DO_CANNY_PRUNING - |CASCADE_SCALE_IMAGE - , + |CASCADE_SCALE_IMAGE, Size(30, 30) ); - for( vector::const_iterator nr = nestedObjects.begin(); nr != nestedObjects.end(); nr++ ) + + for ( size_t j = 0; j < nestedObjects.size(); j++ ) { - center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale); - center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale); - radius = cvRound((nr->width + nr->height)*0.25*scale); + Rect nr = nestedObjects[j]; + center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale); + center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale); + radius = cvRound((nr.width + nr.height)*0.25*scale); circle( canvas, center, radius, color, 3, 8, 0 ); } } diff --git a/samples/vaapi/CMakeLists.txt b/samples/va_intel/CMakeLists.txt similarity index 67% rename from samples/vaapi/CMakeLists.txt rename to samples/va_intel/CMakeLists.txt index 4c03a316a..ddf63edb4 100644 --- a/samples/vaapi/CMakeLists.txt +++ b/samples/va_intel/CMakeLists.txt @@ -1,23 +1,23 @@ -SET(OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui) +SET(OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS opencv_core opencv_imgproc opencv_imgcodecs opencv_videoio opencv_highgui) -ocv_check_dependencies(${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS}) +ocv_check_dependencies(${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS}) if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) - set(project "vaapi") + set(project "va_intel") string(TOUPPER "${project}" project_upper) project("${project}_samples") - ocv_include_modules_recurse(${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS}) + ocv_include_modules_recurse(${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS}) # --------------------------------------------- # Define executable targets # --------------------------------------------- - MACRO(OPENCV_DEFINE_VAAPI_EXAMPLE name srcs) + MACRO(OPENCV_DEFINE_VA_INTEL_EXAMPLE name srcs) set(the_target "example_${project}_${name}") add_executable(${the_target} ${srcs}) - ocv_target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_VAAPI_SAMPLES_REQUIRED_DEPS} ${VAAPI_EXTRA_LIBS}) + ocv_target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${OPENCV_VA_INTEL_SAMPLES_REQUIRED_DEPS} ${VA_LIBRARIES} ${VA_INTEL_LIBRARIES}) set_target_properties(${the_target} PROPERTIES OUTPUT_NAME "${project}-example-${name}" @@ -33,6 +33,6 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND) foreach(sample_filename ${all_samples}) get_filename_component(sample ${sample_filename} NAME_WE) file(GLOB sample_srcs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${sample}.*) - OPENCV_DEFINE_VAAPI_EXAMPLE(${sample} ${sample_srcs}) + OPENCV_DEFINE_VA_INTEL_EXAMPLE(${sample} ${sample_srcs}) endforeach() endif() diff --git a/samples/vaapi/display.cpp.inc b/samples/va_intel/display.cpp.inc similarity index 63% rename from samples/vaapi/display.cpp.inc rename to samples/va_intel/display.cpp.inc index f192f0dd5..56e71d26e 100644 --- a/samples/vaapi/display.cpp.inc +++ b/samples/va_intel/display.cpp.inc @@ -7,25 +7,28 @@ #include #include -#include -#include +#include "cvconfig.h" -#define VAAPI_PCI_DIR "/sys/bus/pci/devices" -#define VAAPI_DRI_DIR "/dev/dri/" -#define VAAPI_PCI_DISPLAY_CONTROLLER_CLASS 0x03 +#include +# include namespace va { -static unsigned readId(const char* devName, const char* idName); -static int findAdapter(unsigned desiredVendorId); - bool openDisplay(); void closeDisplay(); -int drmfd = -1; VADisplay display = NULL; bool initialized = false; +#define VA_INTEL_PCI_DIR "/sys/bus/pci/devices" +#define VA_INTEL_DRI_DIR "/dev/dri/" +#define VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS 0x03 + +static unsigned readId(const char* devName, const char* idName); +static int findAdapter(unsigned desiredVendorId); + +int drmfd = -1; + class Directory { typedef int (*fsort)(const struct dirent**, const struct dirent**); @@ -70,7 +73,7 @@ static unsigned readId(const char* devName, const char* idName) long int id = 0; char fileName[256]; - snprintf(fileName, sizeof(fileName), "%s/%s/%s", VAAPI_PCI_DIR, devName, idName); + snprintf(fileName, sizeof(fileName), "%s/%s/%s", VA_INTEL_PCI_DIR, devName, idName); FILE* file = fopen(fileName, "r"); if (file) @@ -88,14 +91,14 @@ static int findAdapter(unsigned desiredVendorId) int adapterIndex = -1; int numAdapters = 0; - Directory dir(VAAPI_PCI_DIR); + Directory dir(VA_INTEL_PCI_DIR); for (int i = 0; i < dir.count(); ++i) { const char* name = dir[i]->d_name; unsigned classId = readId(name, "class"); - if ((classId >> 16) == VAAPI_PCI_DISPLAY_CONTROLLER_CLASS) + if ((classId >> 16) == VA_INTEL_PCI_DISPLAY_CONTROLLER_CLASS) { unsigned vendorId = readId(name, "vendor"); if (vendorId == desiredVendorId) @@ -122,9 +125,9 @@ public: numbers[1] = adapterIndex; for (int i = 0; i < NUM_NODES; ++i) { - int sz = sizeof(VAAPI_DRI_DIR) + strlen(names[i]) + 3; + int sz = sizeof(VA_INTEL_DRI_DIR) + strlen(names[i]) + 3; paths[i] = new char [sz]; - snprintf(paths[i], sz, "%s%s%d", VAAPI_DRI_DIR, names[i], numbers[i]); + snprintf(paths[i], sz, "%s%s%d", VA_INTEL_DRI_DIR, names[i], numbers[i]); } } ~NodeInfo() @@ -147,46 +150,74 @@ private: char* paths[NUM_NODES]; }; +static bool openDeviceIntel(); +static bool openDeviceGeneric(); + +static bool openDeviceIntel() +{ + const unsigned IntelVendorID = 0x8086; + + int adapterIndex = findAdapter(IntelVendorID); + if (adapterIndex >= 0) + { + NodeInfo nodes(adapterIndex); + + for (int i = 0; i < nodes.count(); ++i) + { + drmfd = open(nodes.path(i), O_RDWR); + if (drmfd >= 0) + { + display = vaGetDisplayDRM(drmfd); + if (display) + return true; + close(drmfd); + drmfd = -1; + } + } + } + return false; +} + +static bool openDeviceGeneric() +{ + static const char* device_paths[] = { "/dev/dri/renderD128", "/dev/dri/card0" }; + static const int num_devices = sizeof(device_paths) / sizeof(device_paths[0]); + + for (int i = 0; i < num_devices; ++i) + { + drmfd = open(device_paths[i], O_RDWR); + if (drmfd >= 0) + { + display = vaGetDisplayDRM(drmfd); + if (display) + return true; + close(drmfd); + drmfd = -1; + } + } + return false; +} + bool openDisplay() { if (!initialized) { - const unsigned IntelVendorID = 0x8086; - drmfd = -1; display = 0; - int adapterIndex = findAdapter(IntelVendorID); - if (adapterIndex >= 0) + if (openDeviceIntel() || openDeviceGeneric()) { - NodeInfo nodes(adapterIndex); - - for (int i = 0; i < nodes.count(); ++i) + int majorVersion = 0, minorVersion = 0; + if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS) { - drmfd = open(nodes.path(i), O_RDWR); - if (drmfd >= 0) - { - display = vaGetDisplayDRM(drmfd); - if (display) - { - int majorVersion = 0, minorVersion = 0; - if (vaInitialize(display, &majorVersion, &minorVersion) == VA_STATUS_SUCCESS) - { - initialized = true; - return true; - } - display = 0; - } - close(drmfd); - drmfd = -1; - } + initialized = true; + return true; } + close(drmfd); + display = 0; + drmfd = -1; } - - if (adapterIndex < 0) - return false; // Can't find Intel display adapter - if ((drmfd < 0) || !display) - return false; // Can't load VA display + return false; // Can't open VA display } return true; } diff --git a/samples/va_intel/va_intel_interop.cpp b/samples/va_intel/va_intel_interop.cpp new file mode 100644 index 000000000..8fa2c54f6 --- /dev/null +++ b/samples/va_intel/va_intel_interop.cpp @@ -0,0 +1,279 @@ +/* origin: libva-1.3.1/test/decode/mpeg2vldemo.cpp */ + +/* + * Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "display.cpp.inc" + +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core/va_intel.hpp" +#include "cvconfig.h" + +#define CHECK_VASTATUS(_status,_func) \ + if (_status != VA_STATUS_SUCCESS) \ + { \ + char str[256]; \ + snprintf(str, sizeof(str)-1, "%s:%s (%d) failed(status=0x%08x),exit\n", __func__, _func, __LINE__, _status); \ + throw std::runtime_error(str); \ + } + +class CmdlineParser +{ +public: + enum { fnInput=0, fnOutput1, fnOutput2, _fnNumFiles }; // file name indices + CmdlineParser(int argc, char** argv): + m_argc(argc), m_argv(argv) + {} + void usage() + { + fprintf(stderr, +#if defined(HAVE_VA_INTEL) + "Usage: va_intel_interop [-f] infile outfile1 outfile2\n\n" + "Interop ON/OFF version\n\n" + "where: -f option indicates interop is off (fallback mode); interop is on by default\n" +#elif defined(HAVE_VA) + "Usage: va_intel_interop infile outfile1 outfile2\n\n" + "Interop OFF only version\n\n" + "where:\n" +#endif //HAVE_VA_INTEL / HAVE_VA + " infile is to be existing, contains input image data (bmp, jpg, png, tiff, etc)\n" + " outfile1 is to be created, contains original surface data (NV12)\n" + " outfile2 is to be created, contains processed surface data (NV12)\n"); + } + // true => go, false => usage/exit; extra args/unknown options are ignored for simplicity + bool run() + { + int n = 0; + for (int i = 0; i < _fnNumFiles; ++i) + m_files[i] = 0; +#if defined(HAVE_VA_INTEL) + m_interop = true; +#elif defined(HAVE_VA) + m_interop = false; +#endif //HAVE_VA_INTEL / HAVE_VA + for (int i = 1; i < m_argc; ++i) + { + const char *arg = m_argv[i]; + if (arg[0] == '-') // option + { +#if defined(HAVE_VA_INTEL) + if (!strcmp(arg, "-f")) + m_interop = false; +#endif //HAVE_VA_INTEL + } + else // parameter + { + if (n < _fnNumFiles) + m_files[n++] = arg; + } + } + return bool(n >= _fnNumFiles); + } + bool isInterop() const + { + return m_interop; + } + const char* getFile(int n) const + { + return ((n >= 0) && (n < _fnNumFiles)) ? m_files[n] : 0; + } +private: + int m_argc; + char** m_argv; + const char* m_files[_fnNumFiles]; + bool m_interop; +}; + +class Timer +{ +public: + enum UNITS + { + USEC = 0, + MSEC, + SEC + }; + + Timer() : m_t0(0), m_diff(0) + { + m_tick_frequency = (float)cv::getTickFrequency(); + + m_unit_mul[USEC] = 1000000; + m_unit_mul[MSEC] = 1000; + m_unit_mul[SEC] = 1; + } + + void clear() + { + m_t0 = m_diff = 0; + } + + void start() + { + m_t0 = cv::getTickCount(); + } + + void stop() + { + m_diff = cv::getTickCount() - m_t0; + } + + float time(UNITS u = MSEC) + { + float sec = m_diff / m_tick_frequency; + + return sec * m_unit_mul[u]; + } + +public: + float m_tick_frequency; + int64 m_t0; + int64 m_diff; + int m_unit_mul[3]; +}; + +static void checkIfAvailableYUV420() +{ + VAEntrypoint entrypoints[5]; + int num_entrypoints,vld_entrypoint; + VAConfigAttrib attrib; + VAStatus status; + + status = vaQueryConfigEntrypoints(va::display, VAProfileMPEG2Main, entrypoints, &num_entrypoints); + CHECK_VASTATUS(status, "vaQueryConfigEntrypoints"); + + for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; ++vld_entrypoint) + { + if (entrypoints[vld_entrypoint] == VAEntrypointVLD) + break; + } + if (vld_entrypoint == num_entrypoints) + throw std::runtime_error("Failed to find VLD entry point"); + + attrib.type = VAConfigAttribRTFormat; + vaGetConfigAttributes(va::display, VAProfileMPEG2Main, VAEntrypointVLD, &attrib, 1); + if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) + throw std::runtime_error("Desired YUV420 RT format not found"); +} + +static cv::UMat readImage(const char* fileName) +{ + cv::Mat m = cv::imread(fileName); + if (m.empty()) + throw std::runtime_error("Failed to load image: " + std::string(fileName)); + return m.getUMat(cv::ACCESS_RW); +} + +static void writeImage(const cv::UMat& u, const char* fileName, bool doInterop) +{ + std::string fn = std::string(fileName) + std::string(doInterop ? ".on" : ".off") + std::string(".jpg"); + cv::imwrite(fn, u); +} + +static float run(const char* infile, const char* outfile1, const char* outfile2, bool doInterop) +{ + VASurfaceID surface; + VAStatus status; + Timer t; + + // initialize CL context for CL/VA interop + cv::va_intel::ocl::initializeContextFromVA(va::display, doInterop); + + // load input image + cv::UMat u1 = readImage(infile); + cv::Size size2 = u1.size(); + status = vaCreateSurfaces(va::display, VA_RT_FORMAT_YUV420, size2.width, size2.height, &surface, 1, NULL, 0); + CHECK_VASTATUS(status, "vaCreateSurfaces"); + + // transfer image into VA surface, make sure all CL initialization is done (kernels etc) + cv::va_intel::convertToVASurface(va::display, u1, surface, size2); + cv::va_intel::convertFromVASurface(va::display, surface, size2, u1); + cv::UMat u2; + cv::blur(u1, u2, cv::Size(7, 7), cv::Point(-3, -3)); + + // measure performance on some image processing + writeImage(u1, outfile1, doInterop); + t.start(); + cv::va_intel::convertFromVASurface(va::display, surface, size2, u1); + cv::blur(u1, u2, cv::Size(7, 7), cv::Point(-3, -3)); + cv::va_intel::convertToVASurface(va::display, u2, surface, size2); + t.stop(); + writeImage(u2, outfile2, doInterop); + + vaDestroySurfaces(va::display, &surface,1); + + return t.time(Timer::MSEC); +} + +int main(int argc, char** argv) +{ + try + { + CmdlineParser cmd(argc, argv); + if (!cmd.run()) + { + cmd.usage(); + return 0; + } + + if (!va::openDisplay()) + throw std::runtime_error("Failed to open VA display for CL-VA interoperability"); + std::cout << "VA display opened successfully" << std::endl; + + checkIfAvailableYUV420(); + + const char* infile = cmd.getFile(CmdlineParser::fnInput); + const char* outfile1 = cmd.getFile(CmdlineParser::fnOutput1); + const char* outfile2 = cmd.getFile(CmdlineParser::fnOutput2); + bool doInterop = cmd.isInterop(); + + float time = run(infile, outfile1, outfile2, doInterop); + + std::cout << "Interop " << (doInterop ? "ON " : "OFF") << ": processing time, msec: " << time << std::endl; + } + catch (std::exception& ex) + { + std::cerr << "ERROR: " << ex.what() << std::endl; + } + + va::closeDisplay(); + return 0; +} diff --git a/samples/vaapi/vaapi_interop.cpp b/samples/vaapi/vaapi_interop.cpp deleted file mode 100644 index a0d3ece96..000000000 --- a/samples/vaapi/vaapi_interop.cpp +++ /dev/null @@ -1,315 +0,0 @@ -/* origin: libva-1.3.1/test/decode/mpeg2vldemo.cpp */ - -/* - * Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "display.cpp.inc" - -#include "opencv2/core.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/core/vaapi.hpp" - -#define CHECK_VASTATUS(va_status,func) \ -if (va_status != VA_STATUS_SUCCESS) { \ - fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \ - exit(1); \ -} - -/* Data dump of a 16x16 MPEG2 video clip,it has one I frame - */ -static unsigned char mpeg2_clip[]={ - 0x00,0x00,0x01,0xb3,0x01,0x00,0x10,0x13,0xff,0xff,0xe0,0x18,0x00,0x00,0x01,0xb5, - 0x14,0x8a,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0xb8,0x00,0x08,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x0f,0xff,0xf8,0x00,0x00,0x01,0xb5,0x8f,0xff,0xf3,0x41,0x80,0x00, - 0x00,0x01,0x01,0x13,0xe1,0x00,0x15,0x81,0x54,0xe0,0x2a,0x05,0x43,0x00,0x2d,0x60, - 0x18,0x01,0x4e,0x82,0xb9,0x58,0xb1,0x83,0x49,0xa4,0xa0,0x2e,0x05,0x80,0x4b,0x7a, - 0x00,0x01,0x38,0x20,0x80,0xe8,0x05,0xff,0x60,0x18,0xe0,0x1d,0x80,0x98,0x01,0xf8, - 0x06,0x00,0x54,0x02,0xc0,0x18,0x14,0x03,0xb2,0x92,0x80,0xc0,0x18,0x94,0x42,0x2c, - 0xb2,0x11,0x64,0xa0,0x12,0x5e,0x78,0x03,0x3c,0x01,0x80,0x0e,0x80,0x18,0x80,0x6b, - 0xca,0x4e,0x01,0x0f,0xe4,0x32,0xc9,0xbf,0x01,0x42,0x69,0x43,0x50,0x4b,0x01,0xc9, - 0x45,0x80,0x50,0x01,0x38,0x65,0xe8,0x01,0x03,0xf3,0xc0,0x76,0x00,0xe0,0x03,0x20, - 0x28,0x18,0x01,0xa9,0x34,0x04,0xc5,0xe0,0x0b,0x0b,0x04,0x20,0x06,0xc0,0x89,0xff, - 0x60,0x12,0x12,0x8a,0x2c,0x34,0x11,0xff,0xf6,0xe2,0x40,0xc0,0x30,0x1b,0x7a,0x01, - 0xa9,0x0d,0x00,0xac,0x64 -}; - -/* hardcoded here without a bitstream parser helper - * please see picture mpeg2-I.jpg for bitstream details - */ -static VAPictureParameterBufferMPEG2 pic_param={ - horizontal_size:16, - vertical_size:16, - forward_reference_picture:0xffffffff, - backward_reference_picture:0xffffffff, - picture_coding_type:1, - f_code:0xffff, - { - { - intra_dc_precision:0, - picture_structure:3, - top_field_first:0, - frame_pred_frame_dct:1, - concealment_motion_vectors:0, - q_scale_type:0, - intra_vlc_format:0, - alternate_scan:0, - repeat_first_field:0, - progressive_frame:1 , - is_first_field:1 - }, - } -}; - -/* see MPEG2 spec65 for the defines of matrix */ -static VAIQMatrixBufferMPEG2 iq_matrix = { - load_intra_quantiser_matrix:1, - load_non_intra_quantiser_matrix:1, - load_chroma_intra_quantiser_matrix:0, - load_chroma_non_intra_quantiser_matrix:0, - intra_quantiser_matrix:{ - 8, 16, 16, 19, 16, 19, 22, 22, - 22, 22, 22, 22, 26, 24, 26, 27, - 27, 27, 26, 26, 26, 26, 27, 27, - 27, 29, 29, 29, 34, 34, 34, 29, - 29, 29, 27, 27, 29, 29, 32, 32, - 34, 34, 37, 38, 37, 35, 35, 34, - 35, 38, 38, 40, 40, 40, 48, 48, - 46, 46, 56, 56, 58, 69, 69, 83 - }, - non_intra_quantiser_matrix:{16}, - chroma_intra_quantiser_matrix:{0}, - chroma_non_intra_quantiser_matrix:{0} -}; - -#if 1 -static VASliceParameterBufferMPEG2 slice_param={ - slice_data_size:150, - slice_data_offset:0, - slice_data_flag:0, - macroblock_offset:38, /* 4byte + 6bits=38bits */ - slice_horizontal_position:0, - slice_vertical_position:0, - quantiser_scale_code:2, - intra_slice_flag:0 -}; -#endif - -#define CLIP_WIDTH 16 -#define CLIP_HEIGHT 16 - -static void dumpSurface(VADisplay display, VASurfaceID surface_id, const char* fileName) -{ - VAStatus va_status; - - va_status = vaSyncSurface(display, surface_id); - CHECK_VASTATUS(va_status, "vaSyncSurface"); - - VAImage image; - va_status = vaDeriveImage(display, surface_id, &image); - CHECK_VASTATUS(va_status, "vaDeriveImage"); - - unsigned char* buffer = 0; - va_status = vaMapBuffer(display, image.buf, (void **)&buffer); - CHECK_VASTATUS(va_status, "vaMapBuffer"); - - CV_Assert(image.format.fourcc == VA_FOURCC_NV12); -/* - printf("image.format.fourcc = 0x%08x\n", image.format.fourcc); - printf("image.[width x height] = %d x %d\n", image.width, image.height); - printf("image.data_size = %d\n", image.data_size); - printf("image.num_planes = %d\n", image.num_planes); - printf("image.pitches[0..2] = 0x%08x 0x%08x 0x%08x\n", image.pitches[0], image.pitches[1], image.pitches[2]); - printf("image.offsets[0..2] = 0x%08x 0x%08x 0x%08x\n", image.offsets[0], image.offsets[1], image.offsets[2]); -*/ - FILE* out = fopen(fileName, "wb"); - if (!out) - { - perror(fileName); - exit(1); - } - fwrite(buffer, 1, image.data_size, out); - fclose(out); - - vaUnmapBuffer(display, image.buf); - CHECK_VASTATUS(va_status, "vaUnmapBuffer"); - - vaDestroyImage(display, image.image_id); - CHECK_VASTATUS(va_status, "vaDestroyImage"); -} - -int main(int argc,char **argv) -{ - (void)argc; (void)argv; - - VAEntrypoint entrypoints[5]; - int num_entrypoints,vld_entrypoint; - VAConfigAttrib attrib; - VAConfigID config_id; - VASurfaceID surface_id; - VAContextID context_id; - VABufferID pic_param_buf,iqmatrix_buf,slice_param_buf,slice_data_buf; - VAStatus va_status; - - if (argc < 3) - { - fprintf(stderr, - "Usage: vaapi_interop file1 file2\n\n" - "where: file1 is to be created, contains original surface data (NV12)\n" - " file2 is to be created, contains processed surface data (NV12)\n"); - exit(0); - } - - if (!va::openDisplay()) - { - fprintf(stderr, "Failed to open VA display for CL-VA interoperability\n"); - exit(1); - } - fprintf(stderr, "VA display opened successfully\n"); - - cv::vaapi::ocl::initializeContextFromVA(va::display); - - va_status = vaQueryConfigEntrypoints(va::display, VAProfileMPEG2Main, entrypoints, - &num_entrypoints); - CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints"); - - for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; vld_entrypoint++) { - if (entrypoints[vld_entrypoint] == VAEntrypointVLD) - break; - } - if (vld_entrypoint == num_entrypoints) { - /* not find VLD entry point */ - assert(0); - } - - /* Assuming finding VLD, find out the format for the render target */ - attrib.type = VAConfigAttribRTFormat; - vaGetConfigAttributes(va::display, VAProfileMPEG2Main, VAEntrypointVLD, - &attrib, 1); - if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) { - /* not find desired YUV420 RT format */ - assert(0); - } - - va_status = vaCreateConfig(va::display, VAProfileMPEG2Main, VAEntrypointVLD, - &attrib, 1,&config_id); - CHECK_VASTATUS(va_status, "vaCreateConfig"); - - va_status = vaCreateSurfaces( - va::display, - VA_RT_FORMAT_YUV420, CLIP_WIDTH, CLIP_HEIGHT, - &surface_id, 1, - NULL, 0 - ); - CHECK_VASTATUS(va_status, "vaCreateSurfaces"); - - /* Create a context for this decode pipe */ - va_status = vaCreateContext(va::display, config_id, - CLIP_WIDTH, - ((CLIP_HEIGHT+15)/16)*16, - VA_PROGRESSIVE, - &surface_id, - 1, - &context_id); - CHECK_VASTATUS(va_status, "vaCreateContext"); - - va_status = vaCreateBuffer(va::display, context_id, - VAPictureParameterBufferType, - sizeof(VAPictureParameterBufferMPEG2), - 1, &pic_param, - &pic_param_buf); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); - - va_status = vaCreateBuffer(va::display, context_id, - VAIQMatrixBufferType, - sizeof(VAIQMatrixBufferMPEG2), - 1, &iq_matrix, - &iqmatrix_buf ); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); - - va_status = vaCreateBuffer(va::display, context_id, - VASliceParameterBufferType, - sizeof(VASliceParameterBufferMPEG2), - 1, - &slice_param, &slice_param_buf); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); - - va_status = vaCreateBuffer(va::display, context_id, - VASliceDataBufferType, - 0xc4-0x2f+1, - 1, - mpeg2_clip+0x2f, - &slice_data_buf); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); - - va_status = vaBeginPicture(va::display, context_id, surface_id); - CHECK_VASTATUS(va_status, "vaBeginPicture"); - - va_status = vaRenderPicture(va::display,context_id, &pic_param_buf, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va::display,context_id, &iqmatrix_buf, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va::display,context_id, &slice_param_buf, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va::display,context_id, &slice_data_buf, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaEndPicture(va::display,context_id); - CHECK_VASTATUS(va_status, "vaEndPicture"); - - va_status = vaSyncSurface(va::display, surface_id); - CHECK_VASTATUS(va_status, "vaSyncSurface"); - - dumpSurface(va::display, surface_id, argv[1]); - - cv::Size size(CLIP_WIDTH,CLIP_HEIGHT); - cv::UMat u; - - cv::vaapi::convertFromVASurface(surface_id, size, u); - cv::blur(u, u, cv::Size(7, 7), cv::Point(-3, -3)); - cv::vaapi::convertToVASurface(u, surface_id, size); - - dumpSurface(va::display, surface_id, argv[2]); - - vaDestroySurfaces(va::display,&surface_id,1); - vaDestroyConfig(va::display,config_id); - vaDestroyContext(va::display,context_id); - - vaTerminate(va::display); - va::closeDisplay(); - return 0; -}