From 35c7216846ac1982e19e594e2144c11e16787c26 Mon Sep 17 00:00:00 2001 From: Pavel Vlasov Date: Thu, 13 Apr 2017 15:50:23 +0300 Subject: [PATCH] IPP for OpenCV 2017u2 initial enabling patch; --- 3rdparty/ippicv/CMakeLists.txt | 42 + 3rdparty/ippicv/ippicv.cmake | 31 +- CMakeLists.txt | 21 +- cmake/OpenCVFindIPP.cmake | 45 +- cmake/OpenCVFindIPPIW.cmake | 154 ++++ cmake/OpenCVFindLibsPerf.cmake | 5 + cmake/templates/cvconfig.h.in | 1 + modules/calib3d/src/stereosgbm.cpp | 48 +- modules/core/include/opencv2/core/base.hpp | 4 + modules/core/include/opencv2/core/private.hpp | 253 +++++- modules/core/perf/opencl/perf_matop.cpp | 2 +- modules/core/src/convert.cpp | 2 +- modules/core/src/copy.cpp | 8 +- modules/core/src/dxt.cpp | 36 +- modules/core/src/matrix.cpp | 367 ++++---- modules/core/src/system.cpp | 39 +- modules/imgproc/src/color.cpp | 796 ++++++++---------- modules/imgproc/src/deriv.cpp | 485 +++-------- modules/imgproc/src/distransform.cpp | 8 +- modules/imgproc/src/filter.cpp | 9 +- modules/imgproc/src/histogram.cpp | 275 +++--- modules/imgproc/src/imgwarp.cpp | 465 +++++----- modules/imgproc/src/morph.cpp | 406 +++++---- modules/imgproc/src/precomp.hpp | 13 + modules/imgproc/src/smooth.cpp | 221 ++--- modules/imgproc/src/templmatch.cpp | 197 +++-- modules/imgproc/test/test_filter.cpp | 2 +- 27 files changed, 2087 insertions(+), 1848 deletions(-) create mode 100644 3rdparty/ippicv/CMakeLists.txt create mode 100644 cmake/OpenCVFindIPPIW.cmake diff --git a/3rdparty/ippicv/CMakeLists.txt b/3rdparty/ippicv/CMakeLists.txt new file mode 100644 index 0000000000..b9fb79f10d --- /dev/null +++ b/3rdparty/ippicv/CMakeLists.txt @@ -0,0 +1,42 @@ +# ---------------------------------------------------------------------------- +# CMake file for IPP IW. See root CMakeLists.txt +# +# ---------------------------------------------------------------------------- +project(${IPP_IW_LIBRARY}) + +ocv_include_directories(${IPP_INCLUDE_DIRS} ${IPP_IW_PATH}/include) +add_definitions(-DIW_BUILD) +if(HAVE_IPP_ICV_ONLY) + add_definitions(-DICV_BASE) +endif() + +file(GLOB lib_srcs ${IPP_IW_PATH}/src/*.c) +file(GLOB lib_hdrs ${IPP_IW_PATH}/include/*.h ${IPP_IW_PATH}/include/iw/*.h ${IPP_IW_PATH}/include/iw++/*.hpp) + +# ---------------------------------------------------------------------------------- +# Define the library target: +# ---------------------------------------------------------------------------------- + +add_library(${IPP_IW_LIBRARY} STATIC ${lib_srcs} ${lib_hdrs}) + +if(UNIX) + if(CMAKE_COMPILER_IS_GNUCXX OR CV_ICC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -Wno-unused-function") + endif() +endif() + +set_target_properties(${IPP_IW_LIBRARY} + PROPERTIES OUTPUT_NAME ${IPP_IW_LIBRARY} + DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" + COMPILE_PDB_NAME ${IPP_IW_LIBRARY} + COMPILE_PDB_NAME_DEBUG "${IPP_IW_LIBRARY}${OPENCV_DEBUG_POSTFIX}" + ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH} + ) + +if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(${IPP_IW_LIBRARY} PROPERTIES FOLDER "3rdparty") +endif() + +if(NOT BUILD_SHARED_LIBS) + ocv_install_target(${IPP_IW_LIBRARY} EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) +endif() diff --git a/3rdparty/ippicv/ippicv.cmake b/3rdparty/ippicv/ippicv.cmake index a477d60b8a..7cec77c4ee 100644 --- a/3rdparty/ippicv/ippicv.cmake +++ b/3rdparty/ippicv/ippicv.cmake @@ -2,23 +2,38 @@ function(download_ippicv root_var) set(${root_var} "" PARENT_SCOPE) # Commit SHA in the opencv_3rdparty repo - set(IPPICV_COMMIT "81a676001ca8075ada498583e4166079e5744668") + set(IPPICV_COMMIT "a62e20676a60ee0ad6581e217fe7e4bada3b95db") # Define actual ICV versions if(APPLE) - set(OPENCV_ICV_NAME "ippicv_macosx_20151201.tgz") - set(OPENCV_ICV_HASH "4ff1fde9a7cfdfe7250bfcd8334e0f2f") set(OPENCV_ICV_PLATFORM "macosx") - set(OPENCV_ICV_PACKAGE_SUBDIR "ippicv_osx") + set(OPENCV_ICV_PACKAGE_SUBDIR "ippicv_mac") + if(X86_64) + set(OPENCV_ICV_NAME "ippicv_2017u2_mac_intel64_20170418.tgz") + set(OPENCV_ICV_HASH "0c25953c99dbb499ff502485a9356d8d") + else() + set(OPENCV_ICV_NAME "ippicv_2017u2_mac_ia32_20170418.tgz") + set(OPENCV_ICV_HASH "5f225948f3f64067c681293c098d50d8") + endif() elseif((UNIX AND NOT ANDROID) OR (UNIX AND ANDROID_ABI MATCHES "x86")) - set(OPENCV_ICV_NAME "ippicv_linux_20151201.tgz") - set(OPENCV_ICV_HASH "808b791a6eac9ed78d32a7666804320e") set(OPENCV_ICV_PLATFORM "linux") set(OPENCV_ICV_PACKAGE_SUBDIR "ippicv_lnx") + if(X86_64) + set(OPENCV_ICV_NAME "ippicv_2017u2_lnx_intel64_20170418.tgz") + set(OPENCV_ICV_HASH "87cbdeb627415d8e4bc811156289fa3a") + else() + set(OPENCV_ICV_NAME "ippicv_2017u2_lnx_ia32_20170406.tgz") + set(OPENCV_ICV_HASH "f2cece00d802d4dea86df52ed095257e") + endif() elseif(WIN32 AND NOT ARM) - set(OPENCV_ICV_NAME "ippicv_windows_20151201.zip") - set(OPENCV_ICV_HASH "04e81ce5d0e329c3fbc606ae32cad44d") set(OPENCV_ICV_PLATFORM "windows") set(OPENCV_ICV_PACKAGE_SUBDIR "ippicv_win") + if(X86_64) + set(OPENCV_ICV_NAME "ippicv_2017u2_win_intel64_20170418.zip") + set(OPENCV_ICV_HASH "75060a0c662c0800f48995b7e9b085f6") + else() + set(OPENCV_ICV_NAME "ippicv_2017u2_win_ia32_20170418.zip") + set(OPENCV_ICV_HASH "60fcf3ccd9a2ebc9e432ffb5cb91638b") + endif() else() return() endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c913e0230..a340289a84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -270,6 +270,7 @@ OCV_OPTION(BUILD_JPEG "Build libjpeg from source" WIN32 O OCV_OPTION(BUILD_PNG "Build libpng from source" WIN32 OR ANDROID OR APPLE ) OCV_OPTION(BUILD_OPENEXR "Build openexr from source" (WIN32 OR ANDROID OR APPLE) AND NOT WINRT) OCV_OPTION(BUILD_TBB "Download and build TBB from source" ANDROID ) +OCV_OPTION(BUILD_IPP_IW "Build IPP IW from source" NOT MINGW IF (X86_64 OR X86) AND NOT WINRT ) # OpenCV installation options # =================================================== @@ -1238,17 +1239,27 @@ status("") status(" Other third-party libraries:") if(WITH_IPP AND HAVE_IPP) - status(" Use IPP:" "${IPP_VERSION_STR} [${IPP_VERSION_MAJOR}.${IPP_VERSION_MINOR}.${IPP_VERSION_BUILD}]") - status(" at:" "${IPP_ROOT_DIR}") + status(" Use Intel IPP:" "${IPP_VERSION_STR} [${IPP_VERSION_MAJOR}.${IPP_VERSION_MINOR}.${IPP_VERSION_BUILD}]") + status(" at:" "${IPP_ROOT_DIR}") if(NOT HAVE_IPP_ICV_ONLY) - status(" linked:" BUILD_WITH_DYNAMIC_IPP THEN "dynamic" ELSE "static") + status(" linked:" BUILD_WITH_DYNAMIC_IPP THEN "dynamic" ELSE "static") + endif() + if(HAVE_IPP_IW) + if(BUILD_IPP_IW) + status(" Use Intel IPP IW:" "build (${IW_VERSION_MAJOR}.${IW_VERSION_MINOR}.${IW_VERSION_UPDATE})") + else() + status(" Use Intel IPP IW:" "prebuilt binaries (${IW_VERSION_MAJOR}.${IW_VERSION_MINOR}.${IW_VERSION_UPDATE})") + endif() + else() + status(" Use Intel IPP IW:" NO) endif() else() - status(" Use IPP:" WITH_IPP AND NOT HAVE_IPP THEN "IPP not found or implicitly disabled" ELSE NO) + status(" Use Intel IPP:" WITH_IPP AND NOT HAVE_IPP THEN "IPP not found or implicitly disabled" ELSE NO) + status(" Use Intel IPP IW:" WITH_IPP AND NOT HAVE_IPP AND HAVE_IPP_IW THEN "IPP not found or implicitly disabled" ELSE NO) endif() if(DEFINED WITH_IPP_A) -status(" Use IPP Async:" HAVE_IPP_A THEN "YES" ELSE NO) +status(" Use Intel IPP Async:" HAVE_IPP_A THEN "YES" ELSE NO) endif(DEFINED WITH_IPP_A) if(DEFINED WITH_VA) diff --git a/cmake/OpenCVFindIPP.cmake b/cmake/OpenCVFindIPP.cmake index fd6b568baf..04b17f712e 100644 --- a/cmake/OpenCVFindIPP.cmake +++ b/cmake/OpenCVFindIPP.cmake @@ -35,7 +35,7 @@ unset(IPP_VERSION_MINOR) unset(IPP_VERSION_BUILD) if (X86 AND UNIX AND NOT APPLE AND NOT ANDROID AND BUILD_SHARED_LIBS) - message(STATUS "On 32-bit Linux IPP can not currently be used with dynamic libs because of linker errors. Set BUILD_SHARED_LIBS=OFF") + message(STATUS "On 32-bit Linux Intel IPP can not currently be used with dynamic libs because of linker errors. Set BUILD_SHARED_LIBS=OFF") return() endif() @@ -47,14 +47,14 @@ if(CMAKE_CL_64) set(IPP_X64 1) endif() -# This function detects IPP version by analyzing .h file +# This function detects Intel IPP version by analyzing .h file macro(ipp_get_version VERSION_FILE) unset(_VERSION_STR) unset(_MAJOR) unset(_MINOR) unset(_BUILD) - # read IPP version info from file + # read Intel IPP version info from file file(STRINGS ${VERSION_FILE} STR1 REGEX "IPP_VERSION_MAJOR") file(STRINGS ${VERSION_FILE} STR2 REGEX "IPP_VERSION_MINOR") file(STRINGS ${VERSION_FILE} STR3 REGEX "IPP_VERSION_BUILD") @@ -96,29 +96,29 @@ macro(ipp_detect_version) elseif(EXISTS ${IPP_ROOT_DIR}/include/ipp.h) # nothing else() - _ipp_not_supported("Can't resolve IPP directory: ${IPP_ROOT_DIR}") + _ipp_not_supported("Can't resolve Intel IPP directory: ${IPP_ROOT_DIR}") endif() ipp_get_version(${IPP_INCLUDE_DIRS}/ippversion.h) ocv_assert(IPP_VERSION_STR VERSION_GREATER "1.0") - message(STATUS "found IPP${__msg}: ${_MAJOR}.${_MINOR}.${_BUILD} [${IPP_VERSION_STR}]") + message(STATUS "found Intel IPP${__msg}: ${_MAJOR}.${_MINOR}.${_BUILD} [${IPP_VERSION_STR}]") message(STATUS "at: ${IPP_ROOT_DIR}") if(${IPP_VERSION_STR} VERSION_LESS "7.0") - _ipp_not_supported("IPP ${IPP_VERSION_STR} is not supported") + _ipp_not_supported("Intel IPP ${IPP_VERSION_STR} is not supported") endif() set(HAVE_IPP 1) macro(_ipp_set_library_dir DIR) if(NOT EXISTS ${DIR}) - _ipp_not_supported("IPP library directory not found") + _ipp_not_supported("Intel IPP library directory not found") endif() set(IPP_LIBRARY_DIR ${DIR}) endmacro() - if(APPLE) + if(APPLE AND NOT HAVE_IPP_ICV_ONLY) _ipp_set_library_dir(${IPP_ROOT_DIR}/lib) elseif(IPP_X64) _ipp_set_library_dir(${IPP_ROOT_DIR}/lib/intel64) @@ -127,7 +127,7 @@ macro(ipp_detect_version) endif() macro(_ipp_add_library name) - # dynamic linking is only supported for standalone version of IPP + # dynamic linking is only supported for standalone version of Intel IPP if (BUILD_WITH_DYNAMIC_IPP AND NOT HAVE_IPP_ICV_ONLY) if (WIN32) set(IPP_LIB_PREFIX ${CMAKE_IMPORT_LIBRARY_PREFIX}) @@ -142,7 +142,7 @@ macro(ipp_detect_version) endif () if (EXISTS ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX}) if (BUILD_WITH_DYNAMIC_IPP AND NOT HAVE_IPP_ICV_ONLY) - # When using dynamic libraries from standalone IPP it is your responsibility to install those on the target system + # When using dynamic libraries from standalone Intel IPP it is your responsibility to install those on the target system list(APPEND IPP_LIBRARIES ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX}) else () add_library(ipp${name} STATIC IMPORTED) @@ -161,33 +161,32 @@ macro(ipp_detect_version) endif() endif() else() - message(STATUS "Can't find IPP library: ${name} at ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX}") + message(STATUS "Can't find Intel IPP library: ${name} at ${IPP_LIBRARY_DIR}/${IPP_LIB_PREFIX}${IPP_PREFIX}${name}${IPP_SUFFIX}${IPP_LIB_SUFFIX}") endif() endmacro() set(IPP_PREFIX "ipp") if(${IPP_VERSION_STR} VERSION_LESS "8.0") if (BUILD_WITH_DYNAMIC_IPP AND NOT HAVE_IPP_ICV_ONLY) - set(IPP_SUFFIX "") # dynamic not threaded libs suffix IPP 7.x + set(IPP_SUFFIX "") # dynamic not threaded libs suffix Intel IPP 7.x else () - set(IPP_SUFFIX "_l") # static not threaded libs suffix IPP 7.x + set(IPP_SUFFIX "_l") # static not threaded libs suffix Intel IPP 7.x endif () else () if(WIN32) if (BUILD_WITH_DYNAMIC_IPP AND NOT HAVE_IPP_ICV_ONLY) - set(IPP_SUFFIX "") # dynamic not threaded libs suffix IPP 8.x for Windows + set(IPP_SUFFIX "") # dynamic not threaded libs suffix Intel IPP 8.x for Windows else () - set(IPP_SUFFIX "mt") # static not threaded libs suffix IPP 8.x for Windows + set(IPP_SUFFIX "mt") # static not threaded libs suffix Intel IPP 8.x for Windows endif () else() - set(IPP_SUFFIX "") # static not threaded libs suffix IPP 8.x for Linux/OS X + set(IPP_SUFFIX "") # static not threaded libs suffix Intel IPP 8.x for Linux/OS X endif() endif() if(HAVE_IPP_ICV_ONLY) _ipp_add_library(icv) else() - _ipp_add_library(m) _ipp_add_library(cv) _ipp_add_library(i) _ipp_add_library(cc) @@ -201,7 +200,7 @@ macro(ipp_detect_version) get_filename_component(INTEL_COMPILER_LIBRARY_DIR ${IPP_ROOT_DIR}/../compiler/lib REALPATH) endif() if(NOT EXISTS ${INTEL_COMPILER_LIBRARY_DIR}) - _ipp_not_supported("IPP configuration error: can't find Intel compiler library dir ${INTEL_COMPILER_LIBRARY_DIR}") + _ipp_not_supported("Intel IPP configuration error: can't find Intel compiler library dir ${INTEL_COMPILER_LIBRARY_DIR}") endif() if(NOT APPLE) if(IPP_X64) @@ -231,7 +230,7 @@ macro(ipp_detect_version) endif() endif() - #message(STATUS "IPP libs: ${IPP_LIBRARIES}") + #message(STATUS "Intel IPP libs: ${IPP_LIBRARIES}") endmacro() # OPENCV_IPP_PATH is an environment variable for internal usage only, do not use it @@ -240,12 +239,6 @@ if(DEFINED ENV{OPENCV_IPP_PATH} AND NOT DEFINED IPPROOT) endif() if(NOT DEFINED IPPROOT) - if(IOS AND NOT x86_64) - # 2016/10: There is an issue with MacOS binary .a file. - # It is fat multiarch library, and can't be "merged" multiple times. - # So try to ignore i386 version - return() - endif() include("${OpenCV_SOURCE_DIR}/3rdparty/ippicv/ippicv.cmake") download_ippicv(IPPROOT) if(NOT IPPROOT) @@ -261,7 +254,7 @@ endif() if(WIN32 AND MINGW AND NOT IPP_VERSION_MAJOR LESS 7) - # Since IPP built with Microsoft compiler and /GS option + # Since Intel IPP built with Microsoft compiler and /GS option # ====================================================== # From Windows SDK 7.1 # (usually in "C:\Program Files\Microsoft Visual Studio 10.0\VC\lib"), diff --git a/cmake/OpenCVFindIPPIW.cmake b/cmake/OpenCVFindIPPIW.cmake new file mode 100644 index 0000000000..e74c2fb324 --- /dev/null +++ b/cmake/OpenCVFindIPPIW.cmake @@ -0,0 +1,154 @@ +# +# The script to detect Intel(R) Integrated Performance Primitives Integration Wrappers (IPP IW) +# installation/package +# +# +# On return this will define: +# +# HAVE_IPP_IW - True if Intel IPP found +# IPP_IW_PATH - Root of Intel IPP IW directory +# IPP_IW_LIBRARIES - Intel IPP IW libraries +# IPP_IW_INCLUDES - Intel IPP IW include folder +# + +unset(HAVE_IPP_IW CACHE) +unset(IPP_IW_PATH) +unset(IPP_IW_LIBRARIES) +unset(IPP_IW_INCLUDES) +unset(IW_CONFIG_DEBUG) +#set(IW_CONFIG_DEBUG 1) + +if(NOT HAVE_IPP) + return() +endif() + +macro(ippiw_debugmsg MESSAGE) + if(DEFINED IW_CONFIG_DEBUG) + message(STATUS "${MESSAGE}") + endif() +endmacro() + +# This function detects Intel IPP IW version by analyzing .h file +macro(ippiw_setup PATH BUILD) + set(FILE "${PATH}/include/iw/iw_version.h") + ippiw_debugmsg("Checking path: ${PATH}") + if(EXISTS "${FILE}") + ippiw_debugmsg("vfile\tok") + file(STRINGS "${FILE}" IW_VERSION_MAJOR REGEX "IW_VERSION_MAJOR") + file(STRINGS "${FILE}" IW_VERSION_MINOR REGEX "IW_VERSION_MINOR") + file(STRINGS "${FILE}" IW_VERSION_UPDATE REGEX "IW_VERSION_UPDATE") + + file(STRINGS "${FILE}" IW_MIN_COMPATIBLE_IPP_MAJOR REGEX "IW_MIN_COMPATIBLE_IPP_MAJOR") + file(STRINGS "${FILE}" IW_MIN_COMPATIBLE_IPP_MINOR REGEX "IW_MIN_COMPATIBLE_IPP_MINOR") + file(STRINGS "${FILE}" IW_MIN_COMPATIBLE_IPP_UPDATE REGEX "IW_MIN_COMPATIBLE_IPP_UPDATE") + + string(REGEX MATCH "[0-9]+" IW_MIN_COMPATIBLE_IPP_MAJOR ${IW_MIN_COMPATIBLE_IPP_MAJOR}) + string(REGEX MATCH "[0-9]+" IW_MIN_COMPATIBLE_IPP_MINOR ${IW_MIN_COMPATIBLE_IPP_MINOR}) + string(REGEX MATCH "[0-9]+" IW_MIN_COMPATIBLE_IPP_UPDATE ${IW_MIN_COMPATIBLE_IPP_UPDATE}) + + string(REGEX MATCH "[0-9]+" IW_VERSION_MAJOR ${IW_VERSION_MAJOR}) + string(REGEX MATCH "[0-9]+" IW_VERSION_MINOR ${IW_VERSION_MINOR}) + string(REGEX MATCH "[0-9]+" IW_VERSION_UPDATE ${IW_VERSION_UPDATE}) + + math(EXPR IPP_VERSION_EXP "${IPP_VERSION_MAJOR}*10000 + ${IPP_VERSION_MINOR}*100 + ${IPP_VERSION_BUILD}") + math(EXPR IW_MIN_COMPATIBLE_IPP_EXP "${IW_MIN_COMPATIBLE_IPP_MAJOR}*10000 + ${IW_MIN_COMPATIBLE_IPP_MINOR}*100 + ${IW_MIN_COMPATIBLE_IPP_UPDATE}") + + if((IPP_VERSION_EXP GREATER IW_MIN_COMPATIBLE_IPP_EXP) OR (IPP_VERSION_EXP EQUAL IW_MIN_COMPATIBLE_IPP_EXP)) + ippiw_debugmsg("version\tok") + if(${BUILD}) + # check sources + if(EXISTS "${PATH}/src/iw_core.c") + ippiw_debugmsg("sources\tok") + set(IPP_IW_PATH "${PATH}") + message(STATUS "found Intel IPP IW sources: ${IW_VERSION_MAJOR}.${IW_VERSION_MINOR}.${IW_VERSION_UPDATE}") + message(STATUS "at: ${IPP_IW_PATH}") + + set(IPP_IW_LIBRARY ippiw) + set(IPP_IW_INCLUDES "${IPP_IW_PATH}/include") + set(IPP_IW_LIBRARIES ${IPP_IW_LIBRARY}) + execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OpenCV_SOURCE_DIR}/3rdparty/ippicv/CMakeLists.txt" "${IPP_IW_PATH}/") + add_subdirectory("${IPP_IW_PATH}/" ${OpenCV_BINARY_DIR}/3rdparty/ippiw) + set(HAVE_IPP_IW 1) + return() + endif() + else() + # check binaries + if(IPP_X64) + set(FILE "${PATH}/lib/intel64/${CMAKE_STATIC_LIBRARY_PREFIX}ipp_iw${CMAKE_STATIC_LIBRARY_SUFFIX}") + else() + set(FILE "${PATH}/lib/ia32/${CMAKE_STATIC_LIBRARY_PREFIX}ipp_iw${CMAKE_STATIC_LIBRARY_SUFFIX}") + endif() + if(EXISTS ${FILE}) + ippiw_debugmsg("binaries\tok (64=${IPP_X64})") + set(IPP_IW_PATH "${PATH}") + message(STATUS "found Intel IPP IW binaries: ${IW_VERSION_MAJOR}.${IW_VERSION_MINOR}.${IW_VERSION_UPDATE}") + message(STATUS "at: ${IPP_IW_PATH}") + + set(IPP_IW_INCLUDES "${IPP_IW_PATH}/include") + set(IPP_IW_LIBRARIES ${FILE}) + set(HAVE_IPP_IW 1) + set(BUILD_IPP_IW 0) + return() + endif() + endif() + endif() + endif() + set(HAVE_IPP_IW 0) +endmacro() + +# check os and architecture +if(APPLE) + set(IW_PACKAGE_SUBDIR "ippiw_mac") +elseif((UNIX AND NOT ANDROID) OR (UNIX AND ANDROID_ABI MATCHES "x86")) + set(IW_PACKAGE_SUBDIR "ippiw_lnx") +elseif(WIN32 AND NOT ARM) + set(IW_PACKAGE_SUBDIR "ippiw_win") +else() + message(SEND_ERROR "Improper system for Intel IPP Integrations Wrappers. This message shouldn't appera. Check Intel IPP configurations steps") + return() +endif() + +# check build options first +if(BUILD_IPP_IW) + # custom path + if(DEFINED IPPIWROOT) + ippiw_setup("${IPPIWROOT}/" 1) + message(STATUS "Can't find Intel IPP IW sources at: ${IPPIWROOT}") + endif() + + # local sources + ippiw_setup("${OpenCV_SOURCE_DIR}/3rdparty/ippiw" 1) + + # Package sources + ippiw_setup("${IPPROOT}/../${IW_PACKAGE_SUBDIR}/" 1) +endif() + + +# custom binaries +if(DEFINED IPPIWROOT) + ippiw_setup("${IPPIWROOT}/" 0) + message(STATUS "Can't find Intel IPP IW sources at: ${IPPIWROOT}") +endif() + +# check binaries in IPP folder +ippiw_setup("${IPPROOT}/" 0) + +# check binaries near IPP folder +ippiw_setup("${IPPROOT}/../${IW_PACKAGE_SUBDIR}/" 0) + + +# take Intel IPP IW from ICV package +if(NOT HAVE_IPP_ICV_ONLY AND BUILD_IPP_IW) + message(STATUS "Cannot find Intel IPP IW. Checking \"Intel IPP for OpenCV\" package") + set(TEMP_ROOT 0) + include("${OpenCV_SOURCE_DIR}/3rdparty/ippicv/ippicv.cmake") + download_ippicv(TEMP_ROOT) + + # Package sources. Only sources are compatible with regular Intel IPP + ippiw_setup("${TEMP_ROOT}/../${IW_PACKAGE_SUBDIR}/" 1) +endif() + + +set(HAVE_IPP_IW 0) +message(STATUS "Cannot find Intel IPP Integration Wrappers, optimizations will be limited. Use IPPIWROOT to set custom location") +return() diff --git a/cmake/OpenCVFindLibsPerf.cmake b/cmake/OpenCVFindLibsPerf.cmake index 70b6cf543e..d19fc947e9 100644 --- a/cmake/OpenCVFindLibsPerf.cmake +++ b/cmake/OpenCVFindLibsPerf.cmake @@ -36,6 +36,11 @@ endif(WITH_TBB) if(WITH_IPP) include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindIPP.cmake") if(HAVE_IPP) + include("${OpenCV_SOURCE_DIR}/cmake/OpenCVFindIPPIW.cmake") + if(HAVE_IPP_IW) + ocv_include_directories(${IPP_IW_INCLUDES}) + list(APPEND OPENCV_LINKER_LIBS ${IPP_IW_LIBRARIES}) + endif() ocv_include_directories(${IPP_INCLUDE_DIRS}) list(APPEND OPENCV_LINKER_LIBS ${IPP_LIBRARIES}) endif() diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index f20ff0c174..267aebf513 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -101,6 +101,7 @@ /* Intel Integrated Performance Primitives */ #cmakedefine HAVE_IPP #cmakedefine HAVE_IPP_ICV_ONLY +#cmakedefine HAVE_IPP_IW /* Intel IPP Async */ #cmakedefine HAVE_IPP_A diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index d5c160b0fc..eca3c06303 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -1705,43 +1705,37 @@ 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) +static bool ipp_filterSpeckles(Mat &img, int maxSpeckleSize, int newVal, int maxDiff, Mat &buffer) { +#if IPP_VERSION_X100 >= 810 CV_INSTRUMENT_REGION_IPP() -#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; + IppDataType dataType = ippiGetDataType(img.depth()); + IppiSize size = ippiSize(img.size()); + int bufferSize; - if(ippiMarkSpecklesGetBufferSize(roisize, datatype, CV_MAT_CN(type), &bufsize) < 0) + if(img.channels() != 1) return false; - pBuffer = (Ipp8u*)ippMalloc(bufsize); - if(!pBuffer && bufsize) + if(dataType != ipp8u && dataType != ipp16s) return false; - if (type == CV_8UC1) - { - status = CV_INSTRUMENT_FUN_IPP(ippiMarkSpeckles_8u_C1IR, img.ptr(), (int)img.step, roisize, - (Ipp8u)newVal, maxSpeckleSize, (Ipp8u)maxDiff, ippiNormL1, pBuffer); - } - else - { - status = CV_INSTRUMENT_FUN_IPP(ippiMarkSpeckles_16s_C1IR, img.ptr(), (int)img.step, roisize, - (Ipp16s)newVal, maxSpeckleSize, (Ipp16s)maxDiff, ippiNormL1, pBuffer); - } - if(pBuffer) ippFree(pBuffer); + if(ippiMarkSpecklesGetBufferSize(size, dataType, 1, &bufferSize) < 0) + return false; - if (status >= 0) - return true; + if(bufferSize && (buffer.empty() || (int)(buffer.step*buffer.rows) < bufferSize)) + buffer.create(1, (int)bufferSize, CV_8U); + + switch(dataType) + { + case ipp8u: return CV_INSTRUMENT_FUN_IPP(ippiMarkSpeckles_8u_C1IR, img.ptr(), (int)img.step, size, (Ipp8u)newVal, maxSpeckleSize, (Ipp8u)maxDiff, ippiNormL1, buffer.ptr()) >= 0; + case ipp16s: return CV_INSTRUMENT_FUN_IPP(ippiMarkSpeckles_16s_C1IR, img.ptr(), (int)img.step, size, (Ipp16s)newVal, maxSpeckleSize, (Ipp16s)maxDiff, ippiNormL1, buffer.ptr()) >= 0; + default: return false; + } #else - CV_UNUSED(img); CV_UNUSED(maxSpeckleSize); CV_UNUSED(newVal); CV_UNUSED(maxDiff); -#endif + CV_UNUSED(img); CV_UNUSED(maxSpeckleSize); CV_UNUSED(newVal); CV_UNUSED(maxDiff); CV_UNUSED(buffer); return false; +#endif } #endif @@ -1759,7 +1753,7 @@ void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSi int newVal = cvRound(_newval), maxDiff = cvRound(_maxDiff); - CV_IPP_RUN(IPP_VERSION_X100 >= 810 && !__buf.needed() && (type == CV_8UC1 || type == CV_16SC1), ipp_filterSpeckles(img, maxSpeckleSize, newVal, maxDiff)); + CV_IPP_RUN_FAST(ipp_filterSpeckles(img, maxSpeckleSize, newVal, maxDiff, _buf)); if (type == CV_8UC1) filterSpecklesImpl(img, newVal, maxSpeckleSize, maxDiff, _buf); diff --git a/modules/core/include/opencv2/core/base.hpp b/modules/core/include/opencv2/core/base.hpp index 07ca3a51a1..ec961f0575 100644 --- a/modules/core/include/opencv2/core/base.hpp +++ b/modules/core/include/opencv2/core/base.hpp @@ -671,7 +671,11 @@ namespace cudev namespace ipp { +#if OPENCV_ABI_COMPATIBILITY > 300 +CV_EXPORTS unsigned long long getIppFeatures(); +#else CV_EXPORTS int getIppFeatures(); +#endif 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/private.hpp b/modules/core/include/opencv2/core/private.hpp index c43bd727e7..50b5de2ac8 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -185,28 +185,78 @@ CV_EXPORTS void scalarToRawData(const cv::Scalar& s, void* buf, int type, int un * Structures and macros for integration with IPP * \****************************************************************************************/ -#ifdef HAVE_IPP -#include "ipp.h" +// Temporary disabled named IPP region. Accuracy +#define IPP_DISABLE_PYRAMIDS_UP 1 // Different results +#define IPP_DISABLE_PYRAMIDS_DOWN 1 // Different results +#define IPP_DISABLE_PYRAMIDS_BUILD 1 // Different results +#define IPP_DISABLE_WARPAFFINE 1 // Different results +#define IPP_DISABLE_WARPPERSPECTIVE 1 // Different results +#define IPP_DISABLE_REMAP 1 // Different results +#define IPP_DISABLE_MORPH_ADV 1 // mask flipping in IPP +#define IPP_DISABLE_SORT_IDX 0 // different order in index tables +#define IPP_DISABLE_YUV_RGB 1 // accuracy difference +#define IPP_DISABLE_RGB_YUV 1 // breaks OCL accuracy tests +#define IPP_DISABLE_RGB_HSV 1 // breaks OCL accuracy tests +#define IPP_DISABLE_RGB_LAB 1 // breaks OCL accuracy tests +#define IPP_DISABLE_LAB_RGB 1 // breaks OCL accuracy tests +#define IPP_DISABLE_RGB_XYZ 1 // big accuracy difference +#define IPP_DISABLE_XYZ_RGB 1 // big accuracy difference +#define IPP_DISABLE_HAAR 1 // improper integration/results +#define IPP_DISABLE_HOUGH 1 // improper integration/results +#define IPP_DISABLE_RESIZE_8U 1 // Incompatible accuracy +#define IPP_DISABLE_RESIZE_NEAREST 1 // Accuracy mismatch (max diff 1) +#define IPP_DISABLE_RESIZE_AREA 1 // Accuracy mismatch (max diff 1) +// Temporary disabled named IPP region. Performance +#define IPP_DISABLE_PERF_COPYMAKE 1 // performance variations +#define IPP_DISABLE_PERF_LUT 1 // there are no performance benefits (PR #2653) +#define IPP_DISABLE_PERF_TRUE_DIST_MT 1 // cv::distanceTransform OpenCV MT performance is better +#define IPP_DISABLE_PERF_CANNY_MT 1 // cv::Canny OpenCV MT performance is better +#define IPP_DISABLE_PERF_HISTU32F_SSE42 1 // cv::calcHist optimizations problem +#define IPP_DISABLE_PERF_MORPH_SSE42 1 // cv::erode, cv::dilate optimizations problem +#define IPP_DISABLE_PERF_MAG_SSE42 1 // cv::magnitude optimizations problem +#define IPP_DISABLE_PERF_BOX16S_SSE42 1 // cv::boxFilter optimizations problem + +#define IPP_DISABLE_BLOCK 0 // legacy switch + +#ifdef HAVE_IPP +#include "ippversion.h" #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 HAVE_IPP_ICV_ONLY +#define ICV_BASE +#if IPP_VERSION_X100 >= 201700 +#include "ippicv.h" +#else +#include "ipp.h" +#endif +#else +#include "ipp.h" +#endif +#ifdef HAVE_IPP_IW +#include "iw++/iw.hpp" +#endif #ifdef CV_MALLOC_ALIGN #undef CV_MALLOC_ALIGN #endif #define CV_MALLOC_ALIGN 32 // required for AVX optimization +#if IPP_VERSION_X100 >= 201700 +#define CV_IPP_MALLOC(SIZE) ippMalloc_L(SIZE) +#else +#define CV_IPP_MALLOC(SIZE) ippMalloc((int)SIZE) +#endif + #define setIppErrorStatus() cv::ipp::setIppStatus(-1, CV_Func, __FILE__, __LINE__) -static inline IppiSize ippiSize(int width, int height) +static inline IppiSize ippiSize(size_t width, size_t height) { - IppiSize size = { width, height }; + IppiSize size = { (int)width, (int)height }; return size; } @@ -216,6 +266,20 @@ static inline IppiSize ippiSize(const cv::Size & _size) return size; } +#if IPP_VERSION_X100 >= 201700 +static inline IppiSizeL ippiSizeL(size_t width, size_t height) +{ + IppiSizeL size = { (IppSizeL)width, (IppSizeL)height }; + return size; +} + +static inline IppiSizeL ippiSizeL(const cv::Size & _size) +{ + IppiSizeL size = { _size.width, _size.height }; + return size; +} +#endif + static inline IppiPoint ippiPoint(const cv::Point & _point) { IppiPoint point = { _point.x, _point.y }; @@ -230,34 +294,177 @@ static inline IppiPoint ippiPoint(int x, int y) static inline IppiBorderType ippiGetBorderType(int borderTypeNI) { - return borderTypeNI == cv::BORDER_CONSTANT ? ippBorderConst : - borderTypeNI == cv::BORDER_WRAP ? ippBorderWrap : - borderTypeNI == cv::BORDER_REPLICATE ? ippBorderRepl : - borderTypeNI == cv::BORDER_REFLECT_101 ? ippBorderMirror : - borderTypeNI == cv::BORDER_REFLECT ? ippBorderMirrorR : (IppiBorderType)-1; + return borderTypeNI == cv::BORDER_CONSTANT ? ippBorderConst : + borderTypeNI == cv::BORDER_TRANSPARENT ? ippBorderTransp : + borderTypeNI == cv::BORDER_REPLICATE ? ippBorderRepl : + borderTypeNI == cv::BORDER_REFLECT_101 ? ippBorderMirror : + (IppiBorderType)-1; +} + +static inline IppiMaskSize ippiGetMaskSize(int kx, int ky) +{ + return (kx == 1 && ky == 3) ? ippMskSize1x3 : + (kx == 1 && ky == 5) ? ippMskSize1x5 : + (kx == 3 && ky == 1) ? ippMskSize3x1 : + (kx == 3 && ky == 3) ? ippMskSize3x3 : + (kx == 5 && ky == 1) ? ippMskSize5x1 : + (kx == 5 && ky == 5) ? ippMskSize5x5 : + (IppiMaskSize)-1; } static inline IppDataType ippiGetDataType(int depth) { + depth = CV_MAT_DEPTH(depth); return depth == CV_8U ? ipp8u : depth == CV_8S ? ipp8s : depth == CV_16U ? ipp16u : depth == CV_16S ? ipp16s : depth == CV_32S ? ipp32s : depth == CV_32F ? ipp32f : - depth == CV_64F ? ipp64f : (IppDataType)-1; + depth == CV_64F ? ipp64f : + (IppDataType)-1; } -// IPP temporary buffer hepler +#ifdef HAVE_IPP_IW +static inline IwiDerivativeType ippiGetDerivType(int dx, int dy, bool nvert) +{ + return (dx == 1 && dy == 0) ? ((nvert)?iwiDerivNVerFirst:iwiDerivVerFirst) : + (dx == 0 && dy == 1) ? iwiDerivHorFirst : + (dx == 2 && dy == 0) ? iwiDerivVerSecond : + (dx == 0 && dy == 2) ? iwiDerivHorSecond : + (IwiDerivativeType)-1; +} + +static inline void ippiGetImage(const cv::Mat &src, ::ipp::IwiImage &dst) +{ + ::ipp::IwiBorderSize inMemBorder; + if(src.isSubmatrix()) // already have physical border + { + cv::Size origSize; + cv::Point offset; + src.locateROI(origSize, offset); + + inMemBorder.borderLeft = (Ipp32u)offset.x; + inMemBorder.borderTop = (Ipp32u)offset.y; + inMemBorder.borderRight = (Ipp32u)(origSize.width - src.cols - offset.x); + inMemBorder.borderBottom = (Ipp32u)(origSize.height - src.rows - offset.y); + } + + dst.Init(ippiSize(src.size()), ippiGetDataType(src.depth()), src.channels(), inMemBorder, (void*)src.ptr(), src.step); +} + +static inline ::ipp::IwiImage ippiGetImage(const cv::Mat &src) +{ + ::ipp::IwiImage image; + ippiGetImage(src, image); + return image; +} + +static inline IppiBorderType ippiGetBorder(::ipp::IwiImage &image, int ocvBorderType, IppiBorderSize &borderSize) +{ + int inMemFlags = 0; + IppiBorderType border = ippiGetBorderType(ocvBorderType & ~cv::BORDER_ISOLATED); + if((int)border == -1) + return (IppiBorderType)0; + + if(!(ocvBorderType & cv::BORDER_ISOLATED)) + { + if(image.m_inMemSize.borderLeft) + { + if(image.m_inMemSize.borderLeft >= borderSize.borderLeft) + inMemFlags |= ippBorderInMemLeft; + else + return (IppiBorderType)0; + } + else + borderSize.borderLeft = 0; + if(image.m_inMemSize.borderTop) + { + if(image.m_inMemSize.borderTop >= borderSize.borderTop) + inMemFlags |= ippBorderInMemTop; + else + return (IppiBorderType)0; + } + else + borderSize.borderTop = 0; + if(image.m_inMemSize.borderRight) + { + if(image.m_inMemSize.borderRight >= borderSize.borderRight) + inMemFlags |= ippBorderInMemRight; + else + return (IppiBorderType)0; + } + else + borderSize.borderRight = 0; + if(image.m_inMemSize.borderBottom) + { + if(image.m_inMemSize.borderBottom >= borderSize.borderBottom) + inMemFlags |= ippBorderInMemBottom; + else + return (IppiBorderType)0; + } + else + borderSize.borderBottom = 0; + } + else + borderSize.borderLeft = borderSize.borderRight = borderSize.borderTop = borderSize.borderBottom = 0; + + return (IppiBorderType)(border|inMemFlags); +} + +static inline ::ipp::IwValue ippiGetValue(const cv::Scalar &scalar) +{ + return ::ipp::IwValue(scalar[0], scalar[1], scalar[2], scalar[3]); +} + +static inline int ippiSuggestThreadsNum(const ::ipp::IwiImage &image, double multiplier) +{ + int threads = cv::getNumThreads(); + if(image.m_size.height > threads) + { + size_t opMemory = (int)(image.m_step*image.m_size.height*multiplier); + int l2cache = 0; +#if IPP_VERSION_X100 >= 201700 + ippGetL2CacheSize(&l2cache); +#endif + if(!l2cache) + l2cache = 1 << 18; + + return IPP_MAX(1, (IPP_MIN((int)(opMemory/l2cache), threads))); + } + return 1; +} +#endif + +static inline int ippiSuggestThreadsNum(const cv::Mat &image, double multiplier) +{ + int threads = cv::getNumThreads(); + if(image.rows > threads) + { + size_t opMemory = (int)(image.total()*multiplier); + int l2cache = 0; +#if IPP_VERSION_X100 >= 201700 + ippGetL2CacheSize(&l2cache); +#endif + if(!l2cache) + l2cache = 1 << 18; + + return IPP_MAX(1, (IPP_MIN((int)(opMemory/l2cache), threads))); + } + return 1; +} + +// IPP temporary buffer helper 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); } + IppAutoBuffer() { m_size = 0; m_pBuffer = NULL; } + IppAutoBuffer(size_t size) { m_size = 0; m_pBuffer = NULL; allocate(size); } + ~IppAutoBuffer() { deallocate(); } + T* allocate(size_t size) { if(m_size < size) { deallocate(); m_pBuffer = (T*)CV_IPP_MALLOC(size); m_size = size; } return m_pBuffer; } + void deallocate() { if(m_pBuffer) { ippFree(m_pBuffer); m_pBuffer = NULL; } m_size = 0; } + inline T* get() { return (T*)m_pBuffer;} inline operator T* () { return (T*)m_pBuffer;} inline operator const T* () const { return (const T*)m_pBuffer;} private: @@ -265,9 +472,17 @@ private: IppAutoBuffer(IppAutoBuffer &) {} IppAutoBuffer& operator =(const IppAutoBuffer &) {return *this;} - T* m_pBuffer; + size_t m_size; + T* m_pBuffer; }; +// Extracts border interpolation type without flags +#if IPP_VERSION_MAJOR >= 2017 +#define IPP_BORDER_INTER(BORDER) (IppiBorderType)((BORDER)&0xF|((((BORDER)&ippBorderInMem) == ippBorderInMem)?ippBorderInMem:0)); +#else +#define IPP_BORDER_INTER(BORDER) (IppiBorderType)((BORDER)&0xF); +#endif + #else #define IPP_VERSION_X100 0 #endif diff --git a/modules/core/perf/opencl/perf_matop.cpp b/modules/core/perf/opencl/perf_matop.cpp index 0fd5d437c4..8c39a91f0f 100644 --- a/modules/core/perf/opencl/perf_matop.cpp +++ b/modules/core/perf/opencl/perf_matop.cpp @@ -139,7 +139,7 @@ OCL_PERF_TEST_P(CopyToFixture, CopyToWithMaskUninit, dst.release(); startTimer(); src.copyTo(dst, mask); - cv::ocl::finish(); + cvtest::ocl::perf::safeFinish(); stopTimer(); } diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 6c060f9c9c..b1e9af36d9 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -5512,7 +5512,7 @@ public: size_t elemSize1 = dst.elemSize1(); CV_DbgAssert(elemSize1 == 1); - lutBuffer = (uchar*)ippMalloc(256 * (int)elemSize1 * 4); + lutBuffer = (uchar*)CV_IPP_MALLOC(256 * (int)elemSize1 * 4); lutTable[0] = lutBuffer + 0; lutTable[1] = lutBuffer + 1 * 256 * elemSize1; lutTable[2] = lutBuffer + 2 * 256 * elemSize1; diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 1dd56f3cfe..fb8da3bfac 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -298,13 +298,7 @@ void Mat::copyTo( OutputArray _dst ) const const uchar* sptr = data; uchar* dptr = dst.data; - CV_IPP_RUN( - (size_t)cols*elemSize() <= (size_t)INT_MAX && - (size_t)step <= (size_t)INT_MAX && - (size_t)dst.step <= (size_t)INT_MAX - , - CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R, sptr, (int)step, dptr, (int)dst.step, ippiSize((int)(cols*elemSize()), rows)) >= 0 - ) + CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R_L, sptr, (int)step, dptr, (int)dst.step, ippiSizeL((int)(cols*elemSize()), rows)) >= 0) Size sz = getContinuousSize(*this, dst); size_t len = sz.width*elemSize(); diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index e33b105ba6..e2a0222969 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -1580,13 +1580,13 @@ public: return; } - IppiDFTSpec_C_32fc* pDFTSpec = (IppiDFTSpec_C_32fc*)ippMalloc( sizeSpec ); + IppiDFTSpec_C_32fc* pDFTSpec = (IppiDFTSpec_C_32fc*)CV_IPP_MALLOC( sizeSpec ); if ( sizeInit > 0 ) - pMemInit = (Ipp8u*)ippMalloc( sizeInit ); + pMemInit = (Ipp8u*)CV_IPP_MALLOC( sizeInit ); if ( sizeBuffer > 0 ) - pBuffer = (Ipp8u*)ippMalloc( sizeBuffer ); + pBuffer = (Ipp8u*)CV_IPP_MALLOC( sizeBuffer ); status = ippiDFTInit_C_32fc( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit ); @@ -1661,13 +1661,13 @@ public: return; } - IppiDFTSpec_R_32f* pDFTSpec = (IppiDFTSpec_R_32f*)ippMalloc( sizeSpec ); + IppiDFTSpec_R_32f* pDFTSpec = (IppiDFTSpec_R_32f*)CV_IPP_MALLOC( sizeSpec ); if ( sizeInit > 0 ) - pMemInit = (Ipp8u*)ippMalloc( sizeInit ); + pMemInit = (Ipp8u*)CV_IPP_MALLOC( sizeInit ); if ( sizeBuffer > 0 ) - pBuffer = (Ipp8u*)ippMalloc( sizeBuffer ); + pBuffer = (Ipp8u*)CV_IPP_MALLOC( sizeBuffer ); status = ippiDFTInit_R_32f( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit ); @@ -1767,13 +1767,13 @@ static bool ippi_DFT_C_32F(const uchar * src, size_t src_step, uchar * dst, size if ( status < 0 ) return false; - IppiDFTSpec_C_32fc* pDFTSpec = (IppiDFTSpec_C_32fc*)ippMalloc( sizeSpec ); + IppiDFTSpec_C_32fc* pDFTSpec = (IppiDFTSpec_C_32fc*)CV_IPP_MALLOC( sizeSpec ); if ( sizeInit > 0 ) - pMemInit = (Ipp8u*)ippMalloc( sizeInit ); + pMemInit = (Ipp8u*)CV_IPP_MALLOC( sizeInit ); if ( sizeBuffer > 0 ) - pBuffer = (Ipp8u*)ippMalloc( sizeBuffer ); + pBuffer = (Ipp8u*)CV_IPP_MALLOC( sizeBuffer ); status = ippiDFTInit_C_32fc( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit ); @@ -1823,13 +1823,13 @@ static bool ippi_DFT_R_32F(const uchar * src, size_t src_step, uchar * dst, size if ( status < 0 ) return false; - IppiDFTSpec_R_32f* pDFTSpec = (IppiDFTSpec_R_32f*)ippMalloc( sizeSpec ); + IppiDFTSpec_R_32f* pDFTSpec = (IppiDFTSpec_R_32f*)CV_IPP_MALLOC( sizeSpec ); if ( sizeInit > 0 ) - pMemInit = (Ipp8u*)ippMalloc( sizeInit ); + pMemInit = (Ipp8u*)CV_IPP_MALLOC( sizeInit ); if ( sizeBuffer > 0 ) - pBuffer = (Ipp8u*)ippMalloc( sizeBuffer ); + pBuffer = (Ipp8u*)CV_IPP_MALLOC( sizeBuffer ); status = ippiDFTInit_R_32f( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit ); @@ -3852,20 +3852,20 @@ public: return; } - pDCTSpec = (Ipp8u*)ippMalloc(specSize); + pDCTSpec = (Ipp8u*)CV_IPP_MALLOC(specSize); if(!pDCTSpec && specSize) { *ok = false; return; } - pBuffer = (Ipp8u*)ippMalloc(bufferSize); + pBuffer = (Ipp8u*)CV_IPP_MALLOC(bufferSize); if(!pBuffer && bufferSize) { *ok = false; IPP_RETURN } - pInitBuf = (Ipp8u*)ippMalloc(initSize); + pInitBuf = (Ipp8u*)CV_IPP_MALLOC(initSize); if(!pInitBuf && initSize) { *ok = false; @@ -3981,17 +3981,17 @@ static bool ippi_DCT_32f(const uchar * src, size_t src_step, uchar * dst, size_t if(ippDctGetSize(srcRoiSize, &specSize, &initSize, &bufferSize) < 0) return false; - pDCTSpec = (Ipp8u*)ippMalloc(specSize); + pDCTSpec = (Ipp8u*)CV_IPP_MALLOC(specSize); if(!pDCTSpec && specSize) return false; - pBuffer = (Ipp8u*)ippMalloc(bufferSize); + pBuffer = (Ipp8u*)CV_IPP_MALLOC(bufferSize); if(!pBuffer && bufferSize) { IPP_RELEASE return false; } - pInitBuf = (Ipp8u*)ippMalloc(initSize); + pInitBuf = (Ipp8u*)CV_IPP_MALLOC(initSize); if(!pInitBuf && initSize) { IPP_RELEASE diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 2e479f7c56..142a0d21ae 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -3955,50 +3955,6 @@ void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype) namespace cv { -#ifdef HAVE_IPP -#define USE_IPP_SORT - -typedef IppStatus (CV_STDCALL * IppSortFunc)(void *, int); -typedef IppSortFunc IppFlipFunc; - -static IppSortFunc getSortFunc(int depth, bool sortDescending) -{ - if (!sortDescending) - return depth == CV_8U ? (IppSortFunc)ippsSortAscend_8u_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 : -#endif - 0; - else - return depth == CV_8U ? (IppSortFunc)ippsSortDescend_8u_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 : -#endif - 0; -} - -static IppFlipFunc getFlipFunc(int depth) -{ - CV_SUPPRESS_DEPRECATED_START - return - depth == CV_8U || depth == CV_8S ? (IppFlipFunc)ippsFlip_8u_I : - depth == CV_16U || depth == CV_16S ? (IppFlipFunc)ippsFlip_16u_I : - depth == CV_32S || depth == CV_32F ? (IppFlipFunc)ippsFlip_32f_I : - depth == CV_64F ? (IppFlipFunc)ippsFlip_64f_I : 0; - CV_SUPPRESS_DEPRECATED_END -} - - -#endif - template static void sort_( const Mat& src, Mat& dst, int flags ) { AutoBuffer buf; @@ -4017,17 +3973,6 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) } bptr = (T*)buf; -#ifdef USE_IPP_SORT - int depth = src.depth(); - IppSortFunc ippSortFunc = 0; - IppFlipFunc ippFlipFunc = 0; - CV_IPP_CHECK() - { - ippSortFunc = getSortFunc(depth, sortDescending); - ippFlipFunc = getFlipFunc(depth); - } -#endif - for( int i = 0; i < n; i++ ) { T* ptr = bptr; @@ -4047,41 +3992,12 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) ptr[j] = src.ptr(j)[i]; } -#ifdef USE_IPP_SORT - if (!ippSortFunc || CV_INSTRUMENT_FUN_IPP(ippSortFunc, ptr, len) < 0) -#endif + std::sort( ptr, ptr + len ); + if( sortDescending ) { -#ifdef USE_IPP_SORT - if (depth == CV_8U) - setIppErrorStatus(); -#endif - std::sort( ptr, ptr + len ); - if( sortDescending ) - { -#ifdef USE_IPP_SORT - if (!ippFlipFunc || CV_INSTRUMENT_FUN_IPP(ippFlipFunc, ptr, len) < 0) -#endif - { -#ifdef USE_IPP_SORT - setIppErrorStatus(); -#endif - for( int j = 0; j < len/2; j++ ) - std::swap(ptr[j], ptr[len-1-j]); - } -#ifdef USE_IPP_SORT - else - { - CV_IMPL_ADD(CV_IMPL_IPP); - } -#endif - } + for( int j = 0; j < len/2; j++ ) + std::swap(ptr[j], ptr[len-1-j]); } -#ifdef USE_IPP_SORT - else - { - CV_IMPL_ADD(CV_IMPL_IPP); - } -#endif if( !sortRows ) for( int j = 0; j < len; j++ ) @@ -4089,6 +4005,94 @@ template static void sort_( const Mat& src, Mat& dst, int flags ) } } +#ifdef HAVE_IPP +typedef IppStatus (CV_STDCALL *IppSortFunc)(void *pSrcDst, int len, Ipp8u *pBuffer); + +static IppSortFunc getSortFunc(int depth, bool sortDescending) +{ + if (!sortDescending) + return depth == CV_8U ? (IppSortFunc)ippsSortRadixAscend_8u_I : + depth == CV_16U ? (IppSortFunc)ippsSortRadixAscend_16u_I : + depth == CV_16S ? (IppSortFunc)ippsSortRadixAscend_16s_I : + depth == CV_32S ? (IppSortFunc)ippsSortRadixAscend_32s_I : + depth == CV_32F ? (IppSortFunc)ippsSortRadixAscend_32f_I : + depth == CV_64F ? (IppSortFunc)ippsSortRadixAscend_64f_I : + 0; + else + return depth == CV_8U ? (IppSortFunc)ippsSortRadixDescend_8u_I : + depth == CV_16U ? (IppSortFunc)ippsSortRadixDescend_16u_I : + depth == CV_16S ? (IppSortFunc)ippsSortRadixDescend_16s_I : + depth == CV_32S ? (IppSortFunc)ippsSortRadixDescend_32s_I : + depth == CV_32F ? (IppSortFunc)ippsSortRadixDescend_32f_I : + depth == CV_64F ? (IppSortFunc)ippsSortRadixDescend_64f_I : + 0; +} + +static bool ipp_sort(const Mat& src, Mat& dst, int flags) +{ + CV_INSTRUMENT_REGION_IPP() + + bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW; + bool sortDescending = (flags & CV_SORT_DESCENDING) != 0; + bool inplace = (src.data == dst.data); + int depth = src.depth(); + IppDataType type = ippiGetDataType(depth); + + IppSortFunc ippsSortRadix_I = getSortFunc(depth, sortDescending); + if(!ippsSortRadix_I) + return false; + + if(sortRows) + { + AutoBuffer buffer; + int bufferSize; + if(ippsSortRadixGetBufferSize(src.cols, type, &bufferSize) < 0) + return false; + + buffer.allocate(bufferSize); + + if(!inplace) + src.copyTo(dst); + + for(int i = 0; i < dst.rows; i++) + { + if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)dst.ptr(i), dst.cols, buffer) < 0) + return false; + } + } + else + { + AutoBuffer buffer; + int bufferSize; + if(ippsSortRadixGetBufferSize(src.rows, type, &bufferSize) < 0) + return false; + + buffer.allocate(bufferSize); + + Mat row(1, src.rows, src.type()); + Mat srcSub; + Mat dstSub; + Rect subRect(0,0,1,src.rows); + + for(int i = 0; i < src.cols; i++) + { + subRect.x = i; + srcSub = Mat(src, subRect); + dstSub = Mat(dst, subRect); + srcSub.copyTo(row); + + if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)row.ptr(), dst.rows, buffer) < 0) + return false; + + row = row.reshape(1, dstSub.rows); + row.copyTo(dstSub); + } + } + + return true; +} +#endif + template class LessThanIdx { public: @@ -4097,30 +4101,6 @@ public: const _Tp* arr; }; -#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK - -typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(void *, int *, int); - -static IppSortIndexFunc getSortIndexFunc(int depth, bool sortDescending) -{ - if (!sortDescending) - return depth == CV_8U ? (IppSortIndexFunc)ippsSortIndexAscend_8u_I : - depth == CV_16U ? (IppSortIndexFunc)ippsSortIndexAscend_16u_I : - depth == CV_16S ? (IppSortIndexFunc)ippsSortIndexAscend_16s_I : - depth == CV_32S ? (IppSortIndexFunc)ippsSortIndexAscend_32s_I : - depth == CV_32F ? (IppSortIndexFunc)ippsSortIndexAscend_32f_I : - depth == CV_64F ? (IppSortIndexFunc)ippsSortIndexAscend_64f_I : 0; - else - return depth == CV_8U ? (IppSortIndexFunc)ippsSortIndexDescend_8u_I : - depth == CV_16U ? (IppSortIndexFunc)ippsSortIndexDescend_16u_I : - depth == CV_16S ? (IppSortIndexFunc)ippsSortIndexDescend_16s_I : - depth == CV_32S ? (IppSortIndexFunc)ippsSortIndexDescend_32s_I : - depth == CV_32F ? (IppSortIndexFunc)ippsSortIndexDescend_32f_I : - depth == CV_64F ? (IppSortIndexFunc)ippsSortIndexDescend_64f_I : 0; -} - -#endif - template static void sortIdx_( const Mat& src, Mat& dst, int flags ) { AutoBuffer buf; @@ -4142,17 +4122,6 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) T* bptr = (T*)buf; int* _iptr = (int*)ibuf; -#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK - int depth = src.depth(); - IppSortIndexFunc ippFunc = 0; - IppFlipFunc ippFlipFunc = 0; - CV_IPP_CHECK() - { - ippFunc = getSortIndexFunc(depth, sortDescending); - ippFlipFunc = getFlipFunc(depth); - } -#endif - for( int i = 0; i < n; i++ ) { T* ptr = bptr; @@ -4171,40 +4140,12 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) for( int j = 0; j < len; j++ ) iptr[j] = j; -#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK - if (sortRows || !ippFunc || ippFunc(ptr, iptr, len) < 0) -#endif + std::sort( iptr, iptr + len, LessThanIdx(ptr) ); + if( sortDescending ) { -#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK - setIppErrorStatus(); -#endif - std::sort( iptr, iptr + len, LessThanIdx(ptr) ); - if( sortDescending ) - { -#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK - if (!ippFlipFunc || ippFlipFunc(iptr, len) < 0) -#endif - { -#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK - setIppErrorStatus(); -#endif - for( int j = 0; j < len/2; j++ ) - std::swap(iptr[j], iptr[len-1-j]); - } -#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK - else - { - CV_IMPL_ADD(CV_IMPL_IPP); - } -#endif - } + for( int j = 0; j < len/2; j++ ) + std::swap(iptr[j], iptr[len-1-j]); } -#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK - else - { - CV_IMPL_ADD(CV_IMPL_IPP); - } -#endif if( !sortRows ) for( int j = 0; j < len; j++ ) @@ -4212,24 +4153,110 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) } } -typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags); +#ifdef HAVE_IPP +#if !IPP_DISABLE_SORT_IDX +typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(const void* pSrc, Ipp32s srcStrideBytes, Ipp32s *pDstIndx, int len, Ipp8u *pBuffer); +static IppSortIndexFunc getSortIndexFunc(int depth, bool sortDescending) +{ + if (!sortDescending) + return depth == CV_8U ? (IppSortIndexFunc)ippsSortRadixIndexAscend_8u : + depth == CV_16U ? (IppSortIndexFunc)ippsSortRadixIndexAscend_16u : + depth == CV_16S ? (IppSortIndexFunc)ippsSortRadixIndexAscend_16s : + depth == CV_32S ? (IppSortIndexFunc)ippsSortRadixIndexAscend_32s : + depth == CV_32F ? (IppSortIndexFunc)ippsSortRadixIndexAscend_32f : + 0; + else + return depth == CV_8U ? (IppSortIndexFunc)ippsSortRadixIndexDescend_8u : + depth == CV_16U ? (IppSortIndexFunc)ippsSortRadixIndexDescend_16u : + depth == CV_16S ? (IppSortIndexFunc)ippsSortRadixIndexDescend_16s : + depth == CV_32S ? (IppSortIndexFunc)ippsSortRadixIndexDescend_32s : + depth == CV_32F ? (IppSortIndexFunc)ippsSortRadixIndexDescend_32f : + 0; +} + +static bool ipp_sortIdx( const Mat& src, Mat& dst, int flags ) +{ + CV_INSTRUMENT_REGION_IPP() + + bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW; + bool sortDescending = (flags & CV_SORT_DESCENDING) != 0; + int depth = src.depth(); + IppDataType type = ippiGetDataType(depth); + Ipp32s elemSize = (Ipp32s)src.elemSize1(); + + IppSortIndexFunc ippsSortRadixIndex = getSortIndexFunc(depth, sortDescending); + if(!ippsSortRadixIndex) + return false; + + if(sortRows) + { + AutoBuffer buffer; + int bufferSize; + if(ippsSortRadixIndexGetBufferSize(src.cols, type, &bufferSize) < 0) + return false; + + buffer.allocate(bufferSize); + + for(int i = 0; i < src.rows; i++) + { + if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (void*)src.ptr(i), elemSize, (Ipp32s*)dst.ptr(i), src.cols, buffer) < 0) + return false; + } + } + else + { + Mat dstRow(1, dst.rows, dst.type()); + Mat dstSub; + Rect subRect(0,0,1,src.rows); + + AutoBuffer buffer; + int bufferSize; + if(ippsSortRadixIndexGetBufferSize(src.rows, type, &bufferSize) < 0) + return false; + + buffer.allocate(bufferSize); + + Ipp32s pixStride = elemSize*dst.cols; + for(int i = 0; i < src.cols; i++) + { + subRect.x = i; + dstSub = Mat(dst, subRect); + + if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (void*)src.ptr(0, i), pixStride, (Ipp32s*)dstRow.ptr(), src.rows, buffer) < 0) + return false; + + dstRow = dstRow.reshape(1, dstSub.rows); + dstRow.copyTo(dstSub); + } + } + + return true; +} +#endif +#endif + +typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags); } void cv::sort( InputArray _src, OutputArray _dst, int flags ) { CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); + CV_Assert( src.dims <= 2 && src.channels() == 1 ); + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); + CV_IPP_RUN_FAST(ipp_sort(src, dst, flags)); + static SortFunc tab[] = { sort_, sort_, sort_, sort_, sort_, sort_, sort_, 0 }; - Mat src = _src.getMat(); SortFunc func = tab[src.depth()]; - CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 ); - _dst.create( src.size(), src.type() ); - Mat dst = _dst.getMat(); + CV_Assert( func != 0 ); + func( src, dst, flags ); } @@ -4237,20 +4264,24 @@ void cv::sortIdx( InputArray _src, OutputArray _dst, int flags ) { CV_INSTRUMENT_REGION() - static SortFunc tab[] = - { - sortIdx_, sortIdx_, sortIdx_, sortIdx_, - sortIdx_, sortIdx_, sortIdx_, 0 - }; Mat src = _src.getMat(); - SortFunc func = tab[src.depth()]; - CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 ); - + CV_Assert( src.dims <= 2 && src.channels() == 1 ); Mat dst = _dst.getMat(); if( dst.data == src.data ) _dst.release(); _dst.create( src.size(), CV_32S ); dst = _dst.getMat(); +#if !IPP_DISABLE_SORT_IDX + CV_IPP_RUN_FAST(ipp_sortIdx(src, dst, flags)); +#endif + + static SortFunc tab[] = + { + sortIdx_, sortIdx_, sortIdx_, sortIdx_, + sortIdx_, sortIdx_, sortIdx_, 0 + }; + SortFunc func = tab[src.depth()]; + CV_Assert( func != 0 ); func( src, dst, flags ); } diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index e5402614eb..526b474c0b 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -1738,19 +1738,19 @@ IntrumentationRegion::~IntrumentationRegion() namespace ipp { +#ifdef HAVE_IPP struct IPPInitSingleton { public: IPPInitSingleton() { - useIPP = true; - ippStatus = 0; - funcname = NULL; - filename = NULL; - linen = 0; - ippFeatures = 0; + 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()) @@ -1783,7 +1783,7 @@ public: } IPP_INITIALIZER(ippFeatures) -#endif + ippFeatures = ippGetEnabledCpuFeatures(); } bool useIPP; @@ -1792,18 +1792,27 @@ public: const char *funcname; const char *filename; int linen; - int ippFeatures; + Ipp64u ippFeatures; }; static IPPInitSingleton& getIPPSingleton() { CV_SINGLETON_LAZY_INIT_REF(IPPInitSingleton, new IPPInitSingleton()) } +#endif +#if OPENCV_ABI_COMPATIBILITY > 300 +unsigned long long getIppFeatures() +#else int getIppFeatures() +#endif { #ifdef HAVE_IPP +#if OPENCV_ABI_COMPATIBILITY > 300 return getIPPSingleton().ippFeatures; +#else + return (int)getIPPSingleton().ippFeatures; +#endif #else return 0; #endif @@ -1811,20 +1820,32 @@ int getIppFeatures() void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line) { +#ifdef HAVE_IPP getIPPSingleton().ippStatus = status; getIPPSingleton().funcname = _funcname; getIPPSingleton().filename = _filename; getIPPSingleton().linen = _line; +#else + CV_UNUSED(status); CV_UNUSED(_funcname); CV_UNUSED(_filename); CV_UNUSED(_line); +#endif } int getIppStatus() { +#ifdef HAVE_IPP return getIPPSingleton().ippStatus; +#else + return 0; +#endif } String getIppErrorLocation() { +#ifdef HAVE_IPP return format("%s:%d %s", getIPPSingleton().filename ? getIPPSingleton().filename : "", getIPPSingleton().linen, getIPPSingleton().funcname ? getIPPSingleton().funcname : ""); +#else + return String(); +#endif } bool useIPP() diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 8aefa4ce72..f07b1f65e0 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -446,19 +446,23 @@ static ippiGeneralFunc ippiCopyP3C3RTab[] = 0, (ippiGeneralFunc)ippiCopy_32f_P3C3R, 0, 0 }; +#if !IPP_DISABLE_RGB_XYZ static ippiGeneralFunc ippiRGB2XYZTab[] = { (ippiGeneralFunc)ippiRGBToXYZ_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToXYZ_16u_C3R, 0, 0, (ippiGeneralFunc)ippiRGBToXYZ_32f_C3R, 0, 0 }; +#endif +#if !IPP_DISABLE_XYZ_RGB static ippiGeneralFunc ippiXYZ2RGBTab[] = { (ippiGeneralFunc)ippiXYZToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiXYZToRGB_16u_C3R, 0, 0, (ippiGeneralFunc)ippiXYZToRGB_32f_C3R, 0, 0 }; +#endif -#if IPP_DISABLE_BLOCK +#if !IPP_DISABLE_RGB_HSV static ippiGeneralFunc ippiRGB2HSVTab[] = { (ippiGeneralFunc)ippiRGBToHSV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToHSV_16u_C3R, 0, @@ -484,13 +488,15 @@ static ippiGeneralFunc ippiHLS2RGBTab[] = 0, (ippiGeneralFunc)ippiHLSToRGB_32f_C3R, 0, 0 }; -#if IPP_DISABLE_BLOCK +#if !IPP_DISABLE_RGB_LAB static ippiGeneralFunc ippiRGBToLUVTab[] = { (ippiGeneralFunc)ippiRGBToLUV_8u_C3R, 0, (ippiGeneralFunc)ippiRGBToLUV_16u_C3R, 0, 0, (ippiGeneralFunc)ippiRGBToLUV_32f_C3R, 0, 0 }; +#endif +#if !IPP_DISABLE_LAB_RGB static ippiGeneralFunc ippiLUVToRGBTab[] = { (ippiGeneralFunc)ippiLUVToRGB_8u_C3R, 0, (ippiGeneralFunc)ippiLUVToRGB_16u_C3R, 0, @@ -8714,41 +8720,6 @@ void cvtBGRtoBGR5x5(const uchar * src_data, size_t src_step, CALL_HAL(cvtBGRtoBGR5x5, cv_hal_cvtBGRtoBGR5x5, src_data, src_step, dst_data, dst_step, width, height, scn, swapBlue, greenBits); -#if defined(HAVE_IPP) && IPP_DISABLE_BLOCK // breaks OCL accuracy tests - CV_IPP_CHECK() - { - CV_SUPPRESS_DEPRECATED_START; - if (scn == 3 && greenBits == 6 && !swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R))) - return; - } - else if (scn == 4 && greenBits == 6 && !swapBlue) - { - if (CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(CV_8U, scn), dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[CV_8U], - (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 0, 1, 2, CV_8U))) - return; - } - else if (scn == 3 && greenBits == 6 && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(CV_8U, scn), dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[CV_8U], - (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 2, 1, 0, CV_8U)) ) - return; - } - else if (scn == 4 && greenBits == 6 && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(CV_8U, scn), dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[CV_8U], - (ippiGeneralFunc)ippiBGRToBGR565_8u16u_C3R, 2, 1, 0, CV_8U)) ) - return; - } - CV_SUPPRESS_DEPRECATED_END; - } -#endif - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB2RGB5x5(scn, swapBlue ? 2 : 0, greenBits)); } @@ -8762,41 +8733,6 @@ void cvtBGR5x5toBGR(const uchar * src_data, size_t src_step, CALL_HAL(cvtBGR5x5toBGR, cv_hal_cvtBGR5x5toBGR, src_data, src_step, dst_data, dst_step, width, height, dcn, swapBlue, greenBits); -#if defined(HAVE_IPP) && IPP_VERSION_X100 < 900 - CV_IPP_CHECK() - { - CV_SUPPRESS_DEPRECATED_START; - if (dcn == 3 && greenBits == 6 && !swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R))) - return; - } - else if (dcn == 3 && greenBits == 6 && swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R, - ippiSwapChannelsC3RTab[CV_8U], 2, 1, 0, CV_8U))) - return; - } - else if (dcn == 4 && greenBits == 6 && !swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R, - ippiSwapChannelsC3C4RTab[CV_8U], 0, 1, 2, CV_8U))) - return; - } - else if (dcn == 4 && greenBits == 6 && swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiBGR565ToBGR_16u8u_C3R, - ippiSwapChannelsC3C4RTab[CV_8U], 2, 1, 0, CV_8U))) - return; - } - CV_SUPPRESS_DEPRECATED_END; - } -#endif - CvtColorLoop(src_data, src_step, dst_data, dst_step, width, height, RGB5x52RGB(dcn, swapBlue ? 2 : 0, greenBits)); } @@ -8813,30 +8749,30 @@ void cvtBGRtoGray(const uchar * src_data, size_t src_step, #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 CV_IPP_CHECK() { - if(depth == CV_32F && scn == 3 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) ) - return; - } - else if(depth == CV_32F && scn == 3 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) ) - return; - } - else if(depth == CV_32F && scn == 4 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) ) - return; - } - else if(depth == CV_32F && scn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) ) - return; - } + if(depth == CV_32F && scn == 3 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPColor2GrayFunctor(ippiColor2GrayC3Tab[depth])) ) + return; + } + else if(depth == CV_32F && scn == 3 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGB2GrayC3Tab[depth])) ) + return; + } + else if(depth == CV_32F && scn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPColor2GrayFunctor(ippiColor2GrayC4Tab[depth])) ) + return; + } + else if(depth == CV_32F && scn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGB2GrayC4Tab[depth])) ) + return; + } } #endif @@ -8862,18 +8798,18 @@ void cvtGraytoBGR(const uchar * src_data, size_t src_step, #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 CV_IPP_CHECK() { - if(dcn == 3) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + if(dcn == 3) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRFunctor(ippiCopyP3C3RTab[depth])) ) - return; - } - else if(dcn == 4) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + return; + } + else if(dcn == 4) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, IPPGray2BGRAFunctor(ippiCopyP3C3RTab[depth], ippiSwapChannelsC3C4RTab[depth], depth)) ) - return; - } + return; + } } #endif @@ -8919,37 +8855,39 @@ void cvtBGRtoYUV(const uchar * src_data, size_t src_step, CALL_HAL(cvtBGRtoYUV, cv_hal_cvtBGRtoYUV, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isCbCr); -#if defined(HAVE_IPP) && IPP_DISABLE_BLOCK +#if defined(HAVE_IPP) +#if !IPP_DISABLE_RGB_YUV CV_IPP_CHECK() { - if (scn == 3 && depth == CV_8U && swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiRGBToYUV_8u_C3R))) - return; - } - else if (scn == 3 && depth == CV_8U && !swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], - (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth))) - return; - } - else if (scn == 4 && depth == CV_8U && swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 0, 1, 2, depth))) - return; - } - else if (scn == 4 && depth == CV_8U && !swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth))) - return; - } + if (scn == 3 && depth == CV_8U && swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor((ippiGeneralFunc)ippiRGBToYUV_8u_C3R))) + return; + } + else if (scn == 3 && depth == CV_8U && !swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], + (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth))) + return; + } + else if (scn == 4 && depth == CV_8U && swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 0, 1, 2, depth))) + return; + } + else if (scn == 4 && depth == CV_8U && !swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + (ippiGeneralFunc)ippiRGBToYUV_8u_C3R, 2, 1, 0, depth))) + return; + } } +#endif #endif int blueIdx = swapBlue ? 2 : 0; @@ -8971,37 +8909,39 @@ void cvtYUVtoBGR(const uchar * src_data, size_t src_step, CALL_HAL(cvtYUVtoBGR, cv_hal_cvtYUVtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isCbCr); -#if defined(HAVE_IPP) && IPP_DISABLE_BLOCK +#if defined(HAVE_IPP) +#if !IPP_DISABLE_YUV_RGB CV_IPP_CHECK() { - if (dcn == 3 && depth == CV_8U && swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R))) - return; - } - else if (dcn == 3 && depth == CV_8U && !swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, - ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth))) - return; - } - else if (dcn == 4 && depth == CV_8U && swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, - ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth))) - return; - } - else if (dcn == 4 && depth == CV_8U && !swapBlue && !isCbCr) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, - ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth))) - return; - } + if (dcn == 3 && depth == CV_8U && swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R))) + return; + } + else if (dcn == 3 && depth == CV_8U && !swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, + ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth))) + return; + } + else if (dcn == 4 && depth == CV_8U && swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, + ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth))) + return; + } + else if (dcn == 4 && depth == CV_8U && !swapBlue && !isCbCr) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiYUVToRGB_8u_C3R, + ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth))) + return; + } } +#endif #endif int blueIdx = swapBlue ? 2 : 0; @@ -9023,33 +8963,35 @@ void cvtBGRtoXYZ(const uchar * src_data, size_t src_step, CALL_HAL(cvtBGRtoXYZ, cv_hal_cvtBGRtoXYZ, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue); #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 +#if !IPP_DISABLE_RGB_XYZ CV_IPP_CHECK() { - if(scn == 3 && depth != CV_32F && !swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 4 && depth != CV_32F && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 3 && depth != CV_32F && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiRGB2XYZTab[depth])) ) - return; - } - else if(scn == 4 && depth != CV_32F && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 0, 1, 2, depth)) ) - return; - } + if(scn == 3 && depth != CV_32F && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(scn == 4 && depth != CV_32F && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(scn == 3 && depth != CV_32F && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, scn), dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGB2XYZTab[depth])) ) + return; + } + else if(scn == 4 && depth != CV_32F && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2XYZTab[depth], 0, 1, 2, depth)) ) + return; + } } +#endif #endif int blueIdx = swapBlue ? 2 : 0; @@ -9071,33 +9013,35 @@ void cvtXYZtoBGR(const uchar * src_data, size_t src_step, CALL_HAL(cvtXYZtoBGR, cv_hal_cvtXYZtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue); #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 +#if !IPP_DISABLE_XYZ_RGB CV_IPP_CHECK() { - if(dcn == 3 && depth != CV_32F && !swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(dcn == 4 && depth != CV_32F && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) - return; - } - if(dcn == 3 && depth != CV_32F && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiXYZ2RGBTab[depth])) ) - return; - } - else if(dcn == 4 && depth != CV_32F && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) - return; - } + if(dcn == 3 && depth != CV_32F && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(dcn == 4 && depth != CV_32F && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) + return; + } + if(dcn == 3 && depth != CV_32F && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiXYZ2RGBTab[depth])) ) + return; + } + else if(dcn == 4 && depth != CV_32F && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiXYZ2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) + return; + } } +#endif #endif int blueIdx = swapBlue ? 2 : 0; @@ -9122,60 +9066,60 @@ void cvtBGRtoHSV(const uchar * src_data, size_t src_step, #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 CV_IPP_CHECK() { - if (depth == CV_8U && isFullRange) - { - if (isHSV) + if(depth == CV_8U && isFullRange) { -#if IPP_DISABLE_BLOCK // breaks OCL accuracy tests - if(scn == 3 && !swapBlue) + if (isHSV) { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 4 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 0, 1, 2, depth)) ) - return; - } +#if !IPP_DISABLE_RGB_HSV // breaks OCL accuracy tests + if(scn == 3 && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(scn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(scn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HSVTab[depth], 0, 1, 2, depth)) ) + return; + } #endif - } - else - { - if(scn == 3 && !swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) ) - return; } - else if(scn == 4 && !swapBlue) + else { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(scn == 3 && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiRGB2HLSTab[depth])) ) - return; - } - else if(scn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 0, 1, 2, depth)) ) - return; + if(scn == 3 && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(scn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(scn == 3 && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKE_TYPE(depth, scn), dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiRGB2HLSTab[depth])) ) + return; + } + else if(scn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], ippiRGB2HLSTab[depth], 0, 1, 2, depth)) ) + return; + } } } } - } #endif int hrange = depth == CV_32F ? 360 : isFullRange ? 256 : 180; @@ -9209,63 +9153,63 @@ void cvtHSVtoBGR(const uchar * src_data, size_t src_step, #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 700 CV_IPP_CHECK() { - if (depth == CV_8U && isFullRange) - { - if (isHSV) + if (depth == CV_8U && isFullRange) { - if(dcn == 3 && !swapBlue) + if (isHSV) { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) - return; + if(dcn == 3 && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(dcn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(dcn == 3 && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiHSV2RGBTab[depth])) ) + return; + } + else if(dcn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) + return; + } } - else if(dcn == 4 && !swapBlue) + else { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(dcn == 3 && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiHSV2RGBTab[depth])) ) - return; - } - else if(dcn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHSV2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) - return; + if(dcn == 3 && !swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(dcn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if(dcn == 3 && swapBlue) + { + if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, + IPPGeneralFunctor(ippiHLS2RGBTab[depth])) ) + return; + } + else if(dcn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, + IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) + return; + } } } - else - { - if(dcn == 3 && !swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(dcn == 4 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if(dcn == 3 && swapBlue) - { - if( CvtColorIPPLoopCopy(src_data, src_step, CV_MAKETYPE(depth, 3), dst_data, dst_step, width, height, - IPPGeneralFunctor(ippiHLS2RGBTab[depth])) ) - return; - } - else if(dcn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data, dst_step, width, height, - IPPGeneralReorderFunctor(ippiHLS2RGBTab[depth], ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) - return; - } - } - } } #endif @@ -9297,72 +9241,72 @@ void cvtBGRtoLab(const uchar * src_data, size_t src_step, CALL_HAL(cvtBGRtoLab, cv_hal_cvtBGRtoLab, src_data, src_step, dst_data, dst_step, width, height, depth, scn, swapBlue, isLab, srgb); -#if defined(HAVE_IPP) && IPP_DISABLE_BLOCK +#if defined(HAVE_IPP) && !IPP_DISABLE_RGB_LAB CV_IPP_CHECK() { - if (!srgb) - { - if (isLab) + if (!srgb) { - if (scn == 3 && depth == CV_8U && !swapBlue) + if (isLab) { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToLab_8u_C3R))) - return; + if (scn == 3 && depth == CV_8U && !swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPGeneralFunctor((ippiGeneralFunc)ippiBGRToLab_8u_C3R))) + return; + } + else if (scn == 4 && depth == CV_8U && !swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 0, 1, 2, depth))) + return; + } + else if (scn == 3 && depth == CV_8U && swapBlue) // slower than OpenCV + { + if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], + (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth))) + return; + } + else if (scn == 4 && depth == CV_8U && swapBlue) // slower than OpenCV + { + if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth))) + return; + } } - else if (scn == 4 && depth == CV_8U && !swapBlue) + else { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 0, 1, 2, depth))) - return; - } - else if (scn == 3 && depth == CV_8U && swapBlue) // slower than OpenCV - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], - (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth))) - return; - } - else if (scn == 4 && depth == CV_8U && swapBlue) // slower than OpenCV - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - (ippiGeneralFunc)ippiBGRToLab_8u_C3R, 2, 1, 0, depth))) - return; + if (scn == 3 && swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPGeneralFunctor(ippiRGBToLUVTab[depth]))) + return; + } + else if (scn == 4 && swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + ippiRGBToLUVTab[depth], 0, 1, 2, depth))) + return; + } + else if (scn == 3 && !swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], + ippiRGBToLUVTab[depth], 2, 1, 0, depth))) + return; + } + else if (scn == 4 && !swapBlue) + { + if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], + ippiRGBToLUVTab[depth], 2, 1, 0, depth))) + return; + } } } - else - { - if (scn == 3 && swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralFunctor(ippiRGBToLUVTab[depth]))) - return; - } - else if (scn == 4 && swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - ippiRGBToLUVTab[depth], 0, 1, 2, depth))) - return; - } - else if (scn == 3 && !swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC3RTab[depth], - ippiRGBToLUVTab[depth], 2, 1, 0, depth))) - return; - } - else if (scn == 4 && !swapBlue) - { - if (CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPReorderGeneralFunctor(ippiSwapChannelsC4C3RTab[depth], - ippiRGBToLUVTab[depth], 2, 1, 0, depth))) - return; - } - } - } } #endif @@ -9394,72 +9338,72 @@ void cvtLabtoBGR(const uchar * src_data, size_t src_step, CALL_HAL(cvtLabtoBGR, cv_hal_cvtLabtoBGR, src_data, src_step, dst_data, dst_step, width, height, depth, dcn, swapBlue, isLab, srgb); -#if defined(HAVE_IPP) && IPP_DISABLE_BLOCK +#if defined(HAVE_IPP) && !IPP_DISABLE_LAB_RGB CV_IPP_CHECK() { - if (!srgb) - { - if (isLab) + if (!srgb) { - if( dcn == 3 && depth == CV_8U && !swapBlue) + if (isLab) { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R)) ) - return; + if( dcn == 3 && depth == CV_8U && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPGeneralFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R)) ) + return; + } + else if( dcn == 4 && depth == CV_8U && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, + ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) + return; + } + if( dcn == 3 && depth == CV_8U && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, + ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if( dcn == 4 && depth == CV_8U && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, + ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) + return; + } } - else if( dcn == 4 && depth == CV_8U && !swapBlue) + else { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, - ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) - return; - } - if( dcn == 3 && depth == CV_8U && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, - ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if( dcn == 4 && depth == CV_8U && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor((ippiGeneralFunc)ippiLabToBGR_8u_C3R, - ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) - return; + if( dcn == 3 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPGeneralFunctor(ippiLUVToRGBTab[depth])) ) + return; + } + else if( dcn == 4 && swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth], + ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) + return; + } + if( dcn == 3 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth], + ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) + return; + } + else if( dcn == 4 && !swapBlue) + { + if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, + IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth], + ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) + return; + } } } - else - { - if( dcn == 3 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralFunctor(ippiLUVToRGBTab[depth])) ) - return; - } - else if( dcn == 4 && swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth], - ippiSwapChannelsC3C4RTab[depth], 0, 1, 2, depth)) ) - return; - } - if( dcn == 3 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth], - ippiSwapChannelsC3RTab[depth], 2, 1, 0, depth)) ) - return; - } - else if( dcn == 4 && !swapBlue) - { - if( CvtColorIPPLoop(src_data, src_step, dst_data,dst_step, width, height, - IPPGeneralReorderFunctor(ippiLUVToRGBTab[depth], - ippiSwapChannelsC3C4RTab[depth], 2, 1, 0, depth)) ) - return; - } - } - } } #endif @@ -9894,9 +9838,11 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) _dst.create(dstSz, CV_MAKETYPE(depth, dcn)); dst = _dst.getMat(); #ifdef HAVE_IPP - if (CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R, src.data, (int)src.step, dst.data, (int)dst.step, - ippiSize(dstSz.width, dstSz.height)) >= 0) +#if IPP_VERSION_X100 >= 201700 + if (CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R_L, src.data, (IppSizeL)src.step, dst.data, (IppSizeL)dst.step, + ippiSizeL(dstSz.width, dstSz.height)) >= 0) break; +#endif #endif src(Range(0, dstSz.height), Range::all()).copyTo(dst); } diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index 8486ec899b..327eaf6165 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -302,338 +302,91 @@ namespace cv #ifdef HAVE_IPP namespace cv { -static bool IPPDerivScharr(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) + +static bool ipp_Deriv(InputArray _src, OutputArray _dst, int dx, int dy, int ksize, double scale, double delta, int borderType) { +#ifdef HAVE_IPP_IW CV_INSTRUMENT_REGION_IPP() -#if IPP_VERSION_X100 >= 810 - if ((0 > dx) || (0 > dy) || (1 != dx + dy)) - return false; - if (fabs(delta) > FLT_EPSILON) + ::ipp::IwiSize size(_src.size().width, _src.size().height); + IppDataType srcType = ippiGetDataType(_src.depth()); + IppDataType dstType = ippiGetDataType(_dst.depth()); + int channels = _src.channels(); + bool useScale = false; + bool useScharr = false; + + if(channels != _dst.channels() || channels > 1) return false; - IppiBorderType ippiBorderType = ippiGetBorderType(borderType & (~BORDER_ISOLATED)); - if ((int)ippiBorderType < 0) + if(fabs(delta) > FLT_EPSILON || fabs(scale-1) > FLT_EPSILON) + useScale = true; + + if(ksize <= 0) + { + ksize = 3; + useScharr = true; + } + + IppiMaskSize maskSize = ippiGetMaskSize(ksize, ksize); + if(maskSize < 0) return false; - int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); - if (ddepth < 0) - ddepth = sdepth; - int dtype = CV_MAKETYPE(ddepth, cn); +#if IPP_VERSION_X100 <= 201703 + // Bug with mirror wrap + if(borderType == BORDER_REFLECT_101 && (ksize/2+1 > size.width || ksize/2+1 > size.height)) + return false; +#endif - Mat src = _src.getMat(); - if (0 == (BORDER_ISOLATED & borderType)) + IwiDerivativeType derivType = ippiGetDerivType(dx, dy, (useScharr)?false:true); + if(derivType < 0) + return false; + + // Acquire data and begin processing + try { - Size size; Point offset; - src.locateROI(size, offset); - if (0 < offset.x) - ippiBorderType = (IppiBorderType)(ippiBorderType | ippBorderInMemLeft); - if (0 < offset.y) - ippiBorderType = (IppiBorderType)(ippiBorderType | ippBorderInMemTop); - if (offset.x + src.cols < size.width) - ippiBorderType = (IppiBorderType)(ippiBorderType | ippBorderInMemRight); - if (offset.y + src.rows < size.height) - ippiBorderType = (IppiBorderType)(ippiBorderType | ippBorderInMemBottom); - } + Mat src = _src.getMat(); + Mat dst = _dst.getMat(); + ::ipp::IwiImage iwSrc = ippiGetImage(src); + ::ipp::IwiImage iwDst = ippiGetImage(dst); + ::ipp::IwiImage iwSrcProc = iwSrc; + ::ipp::IwiImage iwDstProc = iwDst; + ::ipp::IwiBorderSize borderSize(maskSize); + ::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize)); + if(!ippBorder.m_borderType) + return false; - bool horz = (0 == dx) && (1 == dy); - IppiSize roiSize = {src.cols, src.rows}; - - _dst.create( _src.size(), dtype); - Mat dst = _dst.getMat(); - IppStatus sts = ippStsErr; - if ((CV_8U == stype) && (CV_16S == dtype)) - { - int bufferSize = 0; Ipp8u *pBuffer; - if (horz) + if(srcType == ipp8u && dstType == ipp8u) { - if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp8u, ipp16s, 1, &bufferSize)) - return false; - pBuffer = ippsMalloc_8u(bufferSize); - if (NULL == pBuffer) - return false; - sts = CV_INSTRUMENT_FUN_IPP(ippiFilterScharrHorizMaskBorder_8u16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); + iwDstProc.Alloc(iwDst.m_size, ipp16s, channels); + useScale = true; } + else if(srcType == ipp8u && dstType == ipp32f) + { + iwSrc -= borderSize; + iwSrcProc.Alloc(iwSrc.m_size, ipp32f, channels); + CV_INSTRUMENT_FUN_IPP(::ipp::iwiScale, &iwSrc, &iwSrcProc, 1, 0, ippAlgHintFast); + iwSrcProc += borderSize; + } + + if(useScharr) + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterScharr, &iwSrcProc, &iwDstProc, derivType, maskSize, ippBorder); else - { - if (0 > ippiFilterScharrVertMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp8u, ipp16s, 1, &bufferSize)) - return false; - pBuffer = ippsMalloc_8u(bufferSize); - if (NULL == pBuffer) - return false; - sts = CV_INSTRUMENT_FUN_IPP(ippiFilterScharrVertMaskBorder_8u16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); - } - ippsFree(pBuffer); - } - else if ((CV_16S == stype) && (CV_16S == dtype)) - { - int bufferSize = 0; Ipp8u *pBuffer; - if (horz) - { - if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp16s, ipp16s, 1, &bufferSize)) - return false; - pBuffer = ippsMalloc_8u(bufferSize); - if (NULL == pBuffer) - return false; - sts = CV_INSTRUMENT_FUN_IPP(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)) - return false; - pBuffer = ippsMalloc_8u(bufferSize); - if (NULL == pBuffer) - return false; - sts = CV_INSTRUMENT_FUN_IPP(ippiFilterScharrVertMaskBorder_16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); - } - ippsFree(pBuffer); - } - else if ((CV_32F == stype) && (CV_32F == dtype)) - { - int bufferSize = 0; Ipp8u *pBuffer; - if (horz) - { - if (0 > ippiFilterScharrHorizMaskBorderGetBufferSize(roiSize, ippMskSize3x3, ipp32f, ipp32f, 1, &bufferSize)) - return false; - pBuffer = ippsMalloc_8u(bufferSize); - if (NULL == pBuffer) - return false; - sts = CV_INSTRUMENT_FUN_IPP(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)) - return false; - pBuffer = ippsMalloc_8u(bufferSize); - if (NULL == pBuffer) - return false; - sts = CV_INSTRUMENT_FUN_IPP(ippiFilterScharrVertMaskBorder_32f_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize, ippMskSize3x3, ippiBorderType, 0, pBuffer); - } - ippsFree(pBuffer); - if (sts < 0) - return false;; + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterSobel, &iwSrcProc, &iwDstProc, derivType, maskSize, ippBorder); - if (FLT_EPSILON < fabs(scale - 1.0)) - sts = CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1R, dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, roiSize); + if(useScale) + CV_INSTRUMENT_FUN_IPP(::ipp::iwiScale, &iwDstProc, &iwDst, scale, delta, ippAlgHintFast); } - return (0 <= sts); + catch (::ipp::IwException) + { + return false; + } + + return true; #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); + CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(dx); CV_UNUSED(dy); CV_UNUSED(ksize); 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) -{ - CV_INSTRUMENT_REGION_IPP() - - if (((borderType & ~BORDER_ISOLATED) != BORDER_REPLICATE) || ((3 != ksize) && (5 != ksize))) - return false; - if (fabs(delta) > FLT_EPSILON) - return false; - if (1 != _src.channels()) - return false; - - int bufSize = 0; - cv::AutoBuffer buffer; - Mat src = _src.getMat(), dst = _dst.getMat(); - - if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix()) - return false; - - 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 ((dx == 1) && (dy == 0)) - { -#if IPP_VERSION_X100 >= 900 - if (0 > ippiFilterSobelNegVertBorderGetBufferSize(roi, kernel, ipp8u, ipp16s, 1,&bufSize)) - return false; - buffer.allocate(bufSize); -#else - if (0 > ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) - return false; - buffer.allocate(bufSize); -#endif - - if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelNegVertBorder_8u16s_C1R, src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, roi, kernel, - ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - return false; - return true; - } - - if ((dx == 0) && (dy == 1)) - { -#if IPP_VERSION_X100 >= 900 - if (0 > ippiFilterSobelHorizBorderGetBufferSize(roi, kernel, ipp8u, ipp16s, 1,&bufSize)) - return false; - buffer.allocate(bufSize); -#else - if (0 > ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) - return false; - buffer.allocate(bufSize); -#endif - - if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelHorizBorder_8u16s_C1R, src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, roi, kernel, - ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - return false; - return true; - } - - if ((dx == 2) && (dy == 0)) - { -#if IPP_VERSION_X100 >= 900 - if (0 > ippiFilterSobelVertSecondBorderGetBufferSize(roi, kernel, ipp8u, ipp16s, 1,&bufSize)) - return false; - buffer.allocate(bufSize); -#else - if (0 > ippiFilterSobelVertSecondGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) - return false; - buffer.allocate(bufSize); -#endif - - if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelVertSecondBorder_8u16s_C1R, src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, roi, kernel, - ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - return false; - return true; - } - - if ((dx == 0) && (dy == 2)) - { -#if IPP_VERSION_X100 >= 900 - if (0 > ippiFilterSobelHorizSecondBorderGetBufferSize(roi, kernel, ipp8u, ipp16s, 1,&bufSize)) - return false; - buffer.allocate(bufSize); -#else - if (0 > ippiFilterSobelHorizSecondGetBufferSize_8u16s_C1R(roi, kernel,&bufSize)) - return false; - buffer.allocate(bufSize); -#endif - - if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelHorizSecondBorder_8u16s_C1R, src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, roi, kernel, - ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - return false; - return true; - } - } - - if (src.type() == CV_32F && dst.type() == CV_32F) - { -#if IPP_DISABLE_BLOCK - if ((dx == 1) && (dy == 0)) - { -#if IPP_VERSION_X100 >= 900 - if (0 > ippiFilterSobelNegVertBorderGetBufferSize(roi, kernel, ipp32f, ipp32f, 1,&bufSize)) - return false; - buffer.allocate(bufSize); -#else - 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, roi, kernel, - 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; - } - - if ((dx == 0) && (dy == 1)) - { -#if IPP_VERSION_X100 >= 900 - if (0 > ippiFilterSobelHorizBorderGetBufferSize(roi, kernel, ipp32f, ipp32f, 1,&bufSize)) - return false; - buffer.allocate(bufSize); -#else - 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, roi, kernel, - 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; - } -#endif - - if((dx == 2) && (dy == 0)) - { -#if IPP_VERSION_X100 >= 900 - if (0 > ippiFilterSobelVertSecondBorderGetBufferSize(roi, kernel, ipp32f, ipp32f, 1,&bufSize)) - return false; - buffer.allocate(bufSize); -#else - if (0 > ippiFilterSobelVertSecondGetBufferSize_32f_C1R(roi, kernel,&bufSize)) - return false; - buffer.allocate(bufSize); -#endif - - if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelVertSecondBorder_32f_C1R, src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, roi, kernel, - ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - return false; - if(scale != 1) - CV_INSTRUMENT_FUN_IPP(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 == 2)) - { -#if IPP_VERSION_X100 >= 900 - if (0 > ippiFilterSobelHorizSecondBorderGetBufferSize(roi, kernel, ipp32f, ipp32f, 1,&bufSize)) - return false; - buffer.allocate(bufSize); -#else - if (0 > ippiFilterSobelHorizSecondGetBufferSize_32f_C1R(roi, kernel,&bufSize)) - return false; - buffer.allocate(bufSize); -#endif - - if (0 > CV_INSTRUMENT_FUN_IPP(ippiFilterSobelHorizSecondBorder_32f_C1R, src.ptr(), (int)src.step, - dst.ptr(), (int)dst.step, roi, kernel, - ippBorderRepl, 0, (Ipp8u*)(char*)buffer)) - return false; - - if(scale != 1) - CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1R, dst.ptr(), (int)dst.step, (Ipp32f)scale, dst.ptr(), (int)dst.step, ippiSize(dst.cols*dst.channels(), dst.rows)); - return true; - } - } - return false; -} - -static bool ipp_sobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) -{ - CV_INSTRUMENT_REGION_IPP() - - if (ksize < 0) - { - if (IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)) - return true; - } - else if (0 < ksize) - { - if (IPPDerivSobel(_src, _dst, ddepth, dx, dy, ksize, scale, delta, borderType)) - return true; - } - return false; -} } #endif @@ -722,7 +475,7 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, CV_OVX_RUN(true, openvx_sobel(_src, _dst, dx, dy, ksize, scale, delta, borderType)) - CV_IPP_RUN(!(ocl::useOpenCL() && _dst.isUMat()), ipp_sobel(_src, _dst, ddepth, dx, dy, ksize, scale, delta, borderType)); + CV_IPP_RUN(!(ocl::useOpenCL() && _dst.isUMat()), ipp_Deriv(_src, _dst, dx, dy, ksize, scale, delta, borderType)); int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); @@ -766,7 +519,7 @@ void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, } #endif - CV_IPP_RUN(!(ocl::useOpenCL() && _dst.isUMat()), IPPDerivScharr(_src, _dst, ddepth, dx, dy, scale, delta, borderType)); + CV_IPP_RUN(!(ocl::useOpenCL() && _dst.isUMat()), ipp_Deriv(_src, _dst, dx, dy, 0, scale, delta, borderType)); int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); @@ -986,69 +739,71 @@ static bool ocl_Laplacian3_8UC1(InputArray _src, OutputArray _dst, int ddepth, #if defined(HAVE_IPP) namespace cv { -static bool ipp_Laplacian(InputArray _src, OutputArray _dst, int ddepth, int ksize, - double scale, double delta, int borderType) + +static bool ipp_Laplacian(InputArray _src, OutputArray _dst, int ksize, double scale, double delta, int borderType) { +#ifdef HAVE_IPP_IW CV_INSTRUMENT_REGION_IPP() - int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); - if (ddepth < 0) - ddepth = sdepth; - _dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) ); + ::ipp::IwiSize size(_src.size().width, _src.size().height); + IppDataType srcType = ippiGetDataType(_src.depth()); + IppDataType dstType = ippiGetDataType(_dst.depth()); + int channels = _src.channels(); + bool useScale = false; - int iscale = saturate_cast(scale), idelta = saturate_cast(delta); - bool floatScale = std::fabs(scale - iscale) > DBL_EPSILON, needScale = iscale != 1; - bool floatDelta = std::fabs(delta - idelta) > DBL_EPSILON, needDelta = delta != 0; - int borderTypeNI = borderType & ~BORDER_ISOLATED; - Mat src = _src.getMat(), dst = _dst.getMat(); + if(channels != _dst.channels() || channels > 1) + return false; - if (src.data != dst.data) + if(fabs(delta) > FLT_EPSILON || fabs(scale-1) > FLT_EPSILON) + useScale = true; + + IppiMaskSize maskSize = ippiGetMaskSize(ksize, ksize); + if(maskSize < 0) + return false; + + // Acquire data and begin processing + try { - Ipp32s bufsize; - IppStatus status = (IppStatus)-1; - IppiSize roisize = { src.cols, src.rows }; - IppiMaskSize masksize = ksize == 3 ? ippMskSize3x3 : ippMskSize5x5; - IppiBorderType borderTypeIpp = ippiGetBorderType(borderTypeNI); + Mat src = _src.getMat(); + Mat dst = _dst.getMat(); + ::ipp::IwiImage iwSrc = ippiGetImage(src); + ::ipp::IwiImage iwDst = ippiGetImage(dst); + ::ipp::IwiImage iwSrcProc = iwSrc; + ::ipp::IwiImage iwDstProc = iwDst; + ::ipp::IwiBorderSize borderSize(maskSize); + ::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize)); + if(!ippBorder.m_borderType) + return false; -#define IPP_FILTER_LAPLACIAN(ippsrctype, ippdsttype, ippfavor) \ - do \ - { \ - if (borderTypeIpp >= 0 && ippiFilterLaplacianGetBufferSize_##ippfavor##_C1R(roisize, masksize, &bufsize) >= 0) \ - { \ - Ipp8u * buffer = ippsMalloc_8u(bufsize); \ - status = CV_INSTRUMENT_FUN_IPP(ippiFilterLaplacianBorder_##ippfavor##_C1R, src.ptr(), (int)src.step, dst.ptr(), \ - (int)dst.step, roisize, masksize, borderTypeIpp, 0, buffer); \ - ippsFree(buffer); \ - } \ - } while ((void)0, 0) - - CV_SUPPRESS_DEPRECATED_START - if (sdepth == CV_8U && ddepth == CV_16S && !floatScale && !floatDelta) + if(srcType == ipp8u && dstType == ipp8u) { - IPP_FILTER_LAPLACIAN(Ipp8u, Ipp16s, 8u16s); - - if (needScale && status >= 0) - status = CV_INSTRUMENT_FUN_IPP(ippiMulC_16s_C1IRSfs, (Ipp16s)iscale, dst.ptr(), (int)dst.step, roisize, 0); - if (needDelta && status >= 0) - status = CV_INSTRUMENT_FUN_IPP(ippiAddC_16s_C1IRSfs, (Ipp16s)idelta, dst.ptr(), (int)dst.step, roisize, 0); + iwDstProc.Alloc(iwDst.m_size, ipp16s, channels); + useScale = true; } - else if (sdepth == CV_32F && ddepth == CV_32F) + else if(srcType == ipp8u && dstType == ipp32f) { - IPP_FILTER_LAPLACIAN(Ipp32f, Ipp32f, 32f); - - if (needScale && status >= 0) - status = CV_INSTRUMENT_FUN_IPP(ippiMulC_32f_C1IR, (Ipp32f)scale, dst.ptr(), (int)dst.step, roisize); - if (needDelta && status >= 0) - status = CV_INSTRUMENT_FUN_IPP(ippiAddC_32f_C1IR, (Ipp32f)delta, dst.ptr(), (int)dst.step, roisize); + iwSrc -= borderSize; + iwSrcProc.Alloc(iwSrc.m_size, ipp32f, channels); + CV_INSTRUMENT_FUN_IPP(::ipp::iwiScale, &iwSrc, &iwSrcProc, 1, 0); + iwSrcProc += borderSize; } - CV_SUPPRESS_DEPRECATED_END - if (status >= 0) - return true; + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterLaplacian, &iwSrcProc, &iwDstProc, maskSize, ippBorder); + + if(useScale) + CV_INSTRUMENT_FUN_IPP(::ipp::iwiScale, &iwDstProc, &iwDst, scale, delta); + + } + catch (::ipp::IwException ex) + { + return false; } -#undef IPP_FILTER_LAPLACIAN + return true; +#else + CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ksize); CV_UNUSED(scale); CV_UNUSED(delta); CV_UNUSED(borderType); return false; +#endif } } #endif @@ -1080,9 +835,7 @@ void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize, ocl_Laplacian3_8UC1(_src, _dst, ddepth, kernel, delta, borderType)); } - CV_IPP_RUN((ksize == 3 || ksize == 5) && ((borderType & BORDER_ISOLATED) != 0 || !_src.isSubmatrix()) && - ((stype == CV_8UC1 && ddepth == CV_16S) || (ddepth == CV_32F && stype == CV_32FC1)) && (!cv::ocl::useOpenCL()), - ipp_Laplacian(_src, _dst, ddepth, ksize, scale, delta, borderType)); + CV_IPP_RUN(!(cv::ocl::useOpenCL() && _dst.isUMat()), ipp_Laplacian(_src, _dst, ksize, scale, delta, borderType)); #ifdef HAVE_TEGRA_OPTIMIZATION diff --git a/modules/imgproc/src/distransform.cpp b/modules/imgproc/src/distransform.cpp index 36914d89d8..aba0a774c1 100644 --- a/modules/imgproc/src/distransform.cpp +++ b/modules/imgproc/src/distransform.cpp @@ -681,6 +681,8 @@ namespace cv { static void distanceTransform_L1_8U(InputArray _src, OutputArray _dst) { + CV_INSTRUMENT_REGION() + Mat src = _src.getMat(); CV_Assert( src.type() == CV_8UC1); @@ -745,7 +747,9 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe #ifdef HAVE_IPP CV_IPP_CHECK() { - if ((currentParallelFramework()==NULL) || (src.total()<(int)(1<<14))) +#if IPP_DISABLE_PERF_TRUE_DIST_MT + if(cv::getNumThreads()<=1 || (src.total()<(int)(1<<14))) +#endif { IppStatus status; IppiSize roi = { src.cols, src.rows }; @@ -755,7 +759,7 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe status = ippiTrueDistanceTransformGetBufferSize_8u32f_C1R(roi, &bufSize); if (status>=0) { - pBuffer = (Ipp8u *)ippMalloc( bufSize ); + pBuffer = (Ipp8u *)CV_IPP_MALLOC( bufSize ); status = CV_INSTRUMENT_FUN_IPP(ippiTrueDistanceTransform_8u32f_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roi, pBuffer); ippFree( pBuffer ); if (status>=0) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 641f960ab3..51d0bc4f51 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4635,7 +4635,7 @@ static bool ippFilter2D(int stype, int dtype, int ddepth = CV_MAT_DEPTH(dtype); int sdepth = CV_MAT_DEPTH(stype); -#if IPP_VERSION_X100 >= 201700 && IPP_VERSION_X100 < 201702 // IPP bug with 1x1 kernel +#if IPP_VERSION_X100 >= 201700 && IPP_VERSION_X100 <= 201702 // IPP bug with 1x1 kernel if(kernel_width == 1 && kernel_height == 1) return false; #endif @@ -4662,6 +4662,7 @@ static bool ippFilter2D(int stype, int dtype, Ipp32s bufsize = 0; IppiSize dstRoiSize = { width, height }; IppStatus status; + status = ippiFilterBorderGetSize(kernelSize, dstRoiSize, dataType, kernelType, cn, &specSize, &bufsize); if (status < 0) return false; @@ -4670,7 +4671,7 @@ static bool ippFilter2D(int stype, int dtype, size_t good_kernel_step = sizeof(kernel_type) * static_cast(kernelSize.width); #if IPP_VERSION_X100 >= 900 if (kernel_step != good_kernel_step) { - kernelBuffer.Alloc((int)good_kernel_step * kernelSize.height); + kernelBuffer.allocate((int)good_kernel_step * kernelSize.height); status = trait::get_copy_fun()((kernel_type*)kernel_data, (int)kernel_step, kernelBuffer, (int)good_kernel_step, kernelSize); if (status < 0) return false; @@ -4683,8 +4684,8 @@ static bool ippFilter2D(int stype, int dtype, flip(kernel, kerFlip, -1); pKerBuffer = kernelBuffer; #endif - spec.Alloc(specSize); - buffer.Alloc(bufsize); + spec.allocate(specSize); + buffer.allocate(bufsize); status = trait::runInit(pKerBuffer, kernelSize, 0, dataType, cn, ippRndFinancial, spec); if (status < 0) { return false; diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index a0a2909511..aa229a92bc 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -1178,86 +1178,150 @@ calcHist_8u( std::vector& _ptrs, const std::vector& _deltas, } #ifdef HAVE_IPP -class IPPCalcHistInvoker : - public ParallelLoopBody + +typedef IppStatus(CV_STDCALL * IppiHistogram_C1)(const void* pSrc, int srcStep, + IppiSize roiSize, Ipp32u* pHist, const IppiHistogramSpec* pSpec, Ipp8u* pBuffer); + +static IppiHistogram_C1 getIppiHistogramFunction_C1(int type) +{ + IppiHistogram_C1 ippFunction = + (type == CV_8UC1) ? (IppiHistogram_C1)ippiHistogram_8u_C1R : +#if IPP_VERSION_X100 >= 201700 || !(defined HAVE_IPP_ICV_ONLY) + (type == CV_16UC1) ? (IppiHistogram_C1)ippiHistogram_16u_C1R : + (type == CV_32FC1) ? (IppiHistogram_C1)ippiHistogram_32f_C1R : +#endif + NULL; + + return ippFunction; +} + +class ipp_calcHistParallelTLS { public: - 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) + ipp_calcHistParallelTLS() {} + + IppAutoBuffer spec; + IppAutoBuffer buffer; + IppAutoBuffer thist; +}; + +class ipp_calcHistParallel: public ParallelLoopBody +{ +public: + ipp_calcHistParallel(const Mat &src, Mat &hist, Ipp32s histSize, const float *ranges, bool uniform, bool &ok): + ParallelLoopBody(), m_src(src), m_hist(hist), m_ok(ok) { - *ok = true; + ok = true; + + m_uniform = uniform; + m_ranges = ranges; + m_histSize = histSize; + m_type = ippiGetDataType(src.type()); + m_levelsNum = histSize+1; + ippiHistogram_C1 = getIppiHistogramFunction_C1(src.type()); + if(!ippiHistogram_C1) + { + ok = false; + return; + } + + m_fullRoi = ippiSize(src.size()); + m_bufferSize = 0; + m_specSize = 0; + + if(ippiHistogramGetBufferSize(m_type, m_fullRoi, &m_levelsNum, 1, 1, &m_specSize, &m_bufferSize) < 0) + { + ok = false; + return; + } + + hist.setTo(0); } virtual void operator() (const Range & range) const { - Ipp32s levelNum = histSize + 1; - 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; + CV_INSTRUMENT_REGION_IPP() - if(ippiHistogramGetBufferSize(ipp8u, roi, &levelNum, 1, 1, &specSize, &bufferSize) < 0) + if(!m_ok) + return; + + ipp_calcHistParallelTLS *pTls = m_tls.get(); + + IppiSize roi = {m_src.cols, range.end - range.start }; + bool mtLoop = false; + if(m_fullRoi.height != roi.height) + mtLoop = true; + + if(!pTls->spec) { - *ok = false; + pTls->spec.allocate(m_specSize); + if(!pTls->spec.get()) + { + m_ok = false; + return; + } + + pTls->buffer.allocate(m_bufferSize); + if(!pTls->buffer.get() && m_bufferSize) + { + m_ok = false; + return; + } + + if(m_uniform) + { + if(ippiHistogramUniformInit(m_type, (Ipp32f*)&m_ranges[0], (Ipp32f*)&m_ranges[1], (Ipp32s*)&m_levelsNum, 1, pTls->spec) < 0) + { + m_ok = false; + return; + } + } + else + { + if(ippiHistogramInit(m_type, (const Ipp32f**)&m_ranges, (Ipp32s*)&m_levelsNum, 1, pTls->spec) < 0) + { + m_ok = false; + return; + } + } + + pTls->thist.allocate(m_histSize*sizeof(Ipp32u)); + } + + if(CV_INSTRUMENT_FUN_IPP(ippiHistogram_C1, m_src.ptr(range.start), (int)m_src.step, roi, pTls->thist, pTls->spec, pTls->buffer) < 0) + { + m_ok = false; return; } - pBuffer = (Ipp8u*)ippMalloc(bufferSize); - if(!pBuffer && bufferSize) + if(mtLoop) { - *ok = false; - return; + for(int i = 0; i < m_histSize; i++) + CV_XADD((int*)(m_hist.ptr(i)), *(int*)((Ipp32u*)pTls->thist + i)); } - - pSpec = (IppiHistogramSpec*)ippMalloc(specSize); - if(!pSpec && specSize) - { - if(pBuffer) ippFree(pBuffer); - *ok = false; - return; - } - - if(ippiHistogramUniformInit(ipp8u, (Ipp32f*)&low, (Ipp32f*)&high, (Ipp32s*)&levelNum, 1, pSpec) < 0) - { - if(pSpec) ippFree(pSpec); - if(pBuffer) ippFree(pBuffer); - *ok = false; - return; - } - - IppStatus status = CV_INSTRUMENT_FUN_IPP(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, levelNum, (Ipp32s)low, (Ipp32s)high); - CV_SUPPRESS_DEPRECATED_END -#endif - if(status < 0) - { - *ok = false; - return; - } - - for (int i = 0; i < histSize; ++i) - CV_XADD((int *)(hist->data + i * hist->step), *(int *)(phist.data + i * phist.step)); + else + ippiCopy_32s_C1R((Ipp32s*)pTls->thist.get(), sizeof(Ipp32u), (Ipp32s*)m_hist.ptr(), (int)m_hist.step, ippiSize(1, m_histSize)); } private: - const Mat * src; - Mat * hist; - AutoBuffer * levels; - Ipp32s histSize; - Ipp32f low, high; - bool * ok; + const Mat &m_src; + Mat &m_hist; + Ipp32s m_histSize; + const float *m_ranges; + bool m_uniform; - const IPPCalcHistInvoker & operator = (const IPPCalcHistInvoker & ); + IppiHistogram_C1 ippiHistogram_C1; + IppiSize m_fullRoi; + IppDataType m_type; + Ipp32s m_levelsNum; + int m_bufferSize; + int m_specSize; + + mutable Mutex m_syncMutex; + TLSData m_tls; + + volatile bool &m_ok; + const ipp_calcHistParallel & operator = (const ipp_calcHistParallel & ); }; #endif @@ -1319,49 +1383,49 @@ namespace cv } #endif -#if defined(HAVE_IPP) +#ifdef HAVE_IPP +#define IPP_HISTOGRAM_PARALLEL 1 namespace cv { -static bool ipp_calchist(const Mat* images, int nimages, const int* channels, - InputArray _mask, OutputArray _hist, int dims, const int* histSize, - const float** ranges, bool uniform, bool accumulate ) +static bool ipp_calchist(const Mat &image, Mat &hist, int histSize, const float** ranges, bool uniform, bool accumulate) { CV_INSTRUMENT_REGION_IPP() - Mat mask = _mask.getMat(); - - CV_Assert(dims > 0 && histSize); - - _hist.create(dims, histSize, CV_32F); - Mat hist = _hist.getMat(), ihist = hist; - ihist.flags = (ihist.flags & ~CV_MAT_TYPE_MASK)|CV_32S; - - { - if (nimages == 1 && images[0].type() == CV_8UC1 && dims == 1 && channels && - channels[0] == 0 && mask.empty() && images[0].dims <= 2 && - !accumulate && uniform) - { - ihist.setTo(Scalar::all(0)); - AutoBuffer levels(histSize[0]); - - bool ok = true; - const Mat & src = images[0]; - int nstripes = std::min(8, static_cast(src.total() / (1 << 16))); -#ifdef HAVE_CONCURRENCY - nstripes = 1; + // No SSE42 optimization for uniform 32f +#if IPP_DISABLE_PERF_HISTU32F_SSE42 + if(uniform && image.depth() == CV_32F && !(ipp::getIppFeatures()&ippCPUID_AVX)) + return false; #endif - IPPCalcHistInvoker invoker(src, ihist, levels, histSize[0], ranges[0][0], ranges[0][1], &ok); - Range range(0, src.rows); - parallel_for_(range, invoker, nstripes); - if (ok) - { - ihist.convertTo(hist, CV_32F); - return true; - } + Mat ihist = hist; + if(accumulate) + ihist.create(1, &histSize, CV_32S); + + bool ok = true; + int threads = ippiSuggestThreadsNum(image, (1+((double)ihist.total()/image.total()))*2); + Range range(0, image.rows); + ipp_calcHistParallel invoker(image, ihist, histSize, ranges[0], uniform, ok); + if(!ok) + return false; + + if(IPP_HISTOGRAM_PARALLEL && threads > 1) + parallel_for_(range, invoker, threads*2); + else + invoker(range); + + if(ok) + { + if(accumulate) + { + IppiSize histRoi = ippiSize(1, histSize); + IppAutoBuffer fhist(histSize*sizeof(Ipp32f)); + CV_INSTRUMENT_FUN_IPP(ippiConvert_32s32f_C1R, (Ipp32s*)ihist.ptr(), (int)ihist.step, (Ipp32f*)fhist, sizeof(Ipp32f), histRoi); + CV_INSTRUMENT_FUN_IPP(ippiAdd_32f_C1IR, (Ipp32f*)fhist, sizeof(Ipp32f), (Ipp32f*)hist.ptr(), (int)hist.step, histRoi); } + else + CV_INSTRUMENT_FUN_IPP(ippiConvert_32s32f_C1R, (Ipp32s*)ihist.ptr(), (int)ihist.step, (Ipp32f*)hist.ptr(), (int)hist.step, ippiSize(1, histSize)); } - return false; + return ok; } } #endif @@ -1379,23 +1443,24 @@ void cv::calcHist( const Mat* images, int nimages, const int* channels, ranges && ranges[0], openvx_calchist(images[0], _hist, histSize[0], ranges[0])) - CV_IPP_RUN(nimages == 1 && images[0].type() == CV_8UC1 && dims == 1 && channels && - channels[0] == 0 && _mask.getMat().empty() && images[0].dims <= 2 && - !accumulate && uniform, - ipp_calchist(images, nimages, channels, - _mask, _hist, dims, histSize, - ranges, uniform, accumulate)); - Mat mask = _mask.getMat(); CV_Assert(dims > 0 && histSize); const uchar* const histdata = _hist.getMat().ptr(); _hist.create(dims, histSize, CV_32F); - Mat hist = _hist.getMat(), ihist = hist; + Mat hist = _hist.getMat(); + + if(histdata != hist.data) + accumulate = false; + + CV_IPP_RUN(nimages == 1 && dims == 1 && channels && channels[0] == 0 && _mask.empty() && images[0].dims <= 2, + ipp_calchist(images[0], hist, histSize[0], ranges, uniform, accumulate)); + + Mat ihist = hist; ihist.flags = (ihist.flags & ~CV_MAT_TYPE_MASK)|CV_32S; - if( !accumulate || histdata != hist.data ) + if(!accumulate) hist = Scalar(0.); else hist.convertTo(ihist, CV_32S); diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 84a7e5218a..21dddcbbdb 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -57,73 +57,66 @@ using namespace cv; namespace cv { -#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_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); +#if defined (HAVE_IPP) && (!IPP_DISABLE_WARPAFFINE || !IPP_DISABLE_WARPPERSPECTIVE || !IPP_DISABLE_REMAP) +typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize); - template - bool IPPSetSimple(cv::Scalar value, void *dataPointer, int step, IppiSize &size, ippiSetFunc func) +template +bool IPPSetSimple(cv::Scalar value, void *dataPointer, int step, IppiSize &size, ippiSetFunc func) +{ + CV_INSTRUMENT_REGION_IPP() + + Type values[channels]; + for( int i = 0; i < channels; i++ ) + values[i] = saturate_cast(value[i]); + return func(values, dataPointer, step, size) >= 0; +} + +static bool IPPSet(const cv::Scalar &value, void *dataPointer, int step, IppiSize &size, int channels, int depth) +{ + CV_INSTRUMENT_REGION_IPP() + + if( channels == 1 ) { - CV_INSTRUMENT_REGION_IPP() - - Type values[channels]; - for( int i = 0; i < channels; i++ ) - values[i] = saturate_cast(value[i]); - return func(values, dataPointer, step, size) >= 0; + switch( depth ) + { + case CV_8U: + return CV_INSTRUMENT_FUN_IPP(ippiSet_8u_C1R, saturate_cast(value[0]), (Ipp8u *)dataPointer, step, size) >= 0; + case CV_16U: + return CV_INSTRUMENT_FUN_IPP(ippiSet_16u_C1R, saturate_cast(value[0]), (Ipp16u *)dataPointer, step, size) >= 0; + case CV_32F: + return CV_INSTRUMENT_FUN_IPP(ippiSet_32f_C1R, saturate_cast(value[0]), (Ipp32f *)dataPointer, step, size) >= 0; + } } - - static bool IPPSet(const cv::Scalar &value, void *dataPointer, int step, IppiSize &size, int channels, int depth) + else { - CV_INSTRUMENT_REGION_IPP() - - if( channels == 1 ) + if( channels == 3 ) { switch( depth ) { case CV_8U: - return CV_INSTRUMENT_FUN_IPP(ippiSet_8u_C1R,(saturate_cast(value[0]), (Ipp8u *)dataPointer, step, size)) >= 0; + return IPPSetSimple<3, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C3R); case CV_16U: - return CV_INSTRUMENT_FUN_IPP(ippiSet_16u_C1R,(saturate_cast(value[0]), (Ipp16u *)dataPointer, step, size)) >= 0; + return IPPSetSimple<3, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C3R); case CV_32F: - return CV_INSTRUMENT_FUN_IPP(ippiSet_32f_C1R,(saturate_cast(value[0]), (Ipp32f *)dataPointer, step, size)) >= 0; + return IPPSetSimple<3, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C3R); } } - else + else if( channels == 4 ) { - if( channels == 3 ) + switch( depth ) { - switch( depth ) - { - case CV_8U: - return IPPSetSimple<3, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C3R); - case CV_16U: - return IPPSetSimple<3, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C3R); - case CV_32F: - return IPPSetSimple<3, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C3R); - } - } - else if( channels == 4 ) - { - switch( depth ) - { - case CV_8U: - return IPPSetSimple<4, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C4R); - case CV_16U: - return IPPSetSimple<4, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C4R); - case CV_32F: - return IPPSetSimple<4, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C4R); - } + case CV_8U: + return IPPSetSimple<4, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C4R); + case CV_16U: + return IPPSetSimple<4, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C4R); + case CV_32F: + return IPPSetSimple<4, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C4R); } } - return false; } + return false; +} #endif /************** interpolation formulas and tables ***************/ @@ -2708,135 +2701,7 @@ static int computeResizeAreaTab( int ssize, int dsize, int cn, double scale, Dec return k; } -#define CHECK_IPP_STATUS(STATUS) if (STATUS < 0) { *ok = false; return; } - -#define SET_IPP_RESIZE_LINEAR_FUNC_PTR(TYPE, CN) \ - ippiResize = (ippiResizeFunc)ippiResizeLinear_##TYPE##_##CN##R; \ - CHECK_IPP_STATUS(ippiResizeGetSize_##TYPE(srcSize, dstSize, (IppiInterpolationType)mode, 0, &specSize, &initSize));\ - specBuf.allocate(specSize);\ - pSpec = (uchar*)specBuf;\ - CHECK_IPP_STATUS(ippiResizeLinearInit_##TYPE(srcSize, dstSize, (IppiResizeSpec_32f*)pSpec)); - -#define SET_IPP_RESIZE_LINEAR_FUNC_64_PTR(TYPE, CN) \ - if (mode == (int)ippCubic) { *ok = false; return; } \ - ippiResize = (ippiResizeFunc)ippiResizeLinear_##TYPE##_##CN##R; \ - CHECK_IPP_STATUS(ippiResizeGetSize_##TYPE(srcSize, dstSize, (IppiInterpolationType)mode, 0, &specSize, &initSize));\ - specBuf.allocate(specSize);\ - pSpec = (uchar*)specBuf;\ - CHECK_IPP_STATUS(ippiResizeLinearInit_##TYPE(srcSize, dstSize, (IppiResizeSpec_64f*)pSpec));\ - getBufferSizeFunc = (ippiResizeGetBufferSize)ippiResizeGetBufferSize_##TYPE;\ - getSrcOffsetFunc = (ippiResizeGetSrcOffset) ippiResizeGetSrcOffset_##TYPE; - -#define SET_IPP_RESIZE_CUBIC_FUNC_PTR(TYPE, CN) \ - ippiResize = (ippiResizeFunc)ippiResizeCubic_##TYPE##_##CN##R; \ - CHECK_IPP_STATUS(ippiResizeGetSize_##TYPE(srcSize, dstSize, (IppiInterpolationType)mode, 0, &specSize, &initSize));\ - specBuf.allocate(specSize);\ - pSpec = (uchar*)specBuf;\ - AutoBuffer buf(initSize);\ - uchar* pInit = (uchar*)buf;\ - CHECK_IPP_STATUS(ippiResizeCubicInit_##TYPE(srcSize, dstSize, 0.f, 0.75f, (IppiResizeSpec_32f*)pSpec, pInit)); - -#define SET_IPP_RESIZE_PTR(TYPE, CN) \ - if (mode == (int)ippLinear) { SET_IPP_RESIZE_LINEAR_FUNC_PTR(TYPE, CN);} \ - else if (mode == (int)ippCubic) { SET_IPP_RESIZE_CUBIC_FUNC_PTR(TYPE, CN);} \ - else { *ok = false; return; } \ - getBufferSizeFunc = (ippiResizeGetBufferSize)ippiResizeGetBufferSize_##TYPE; \ - getSrcOffsetFunc = (ippiResizeGetSrcOffset)ippiResizeGetSrcOffset_##TYPE; - -#if IPP_VERSION_X100 >= 710 -class IPPresizeInvoker : - public ParallelLoopBody -{ -public: - IPPresizeInvoker(const Mat & _src, Mat & _dst, double _inv_scale_x, double _inv_scale_y, int _mode, bool *_ok) : - ParallelLoopBody(), src(_src), dst(_dst), inv_scale_x(_inv_scale_x), - inv_scale_y(_inv_scale_y), pSpec(NULL), mode(_mode), - ippiResize(NULL), getBufferSizeFunc(NULL), getSrcOffsetFunc(NULL), ok(_ok) - { - *ok = true; - IppiSize srcSize, dstSize; - int type = src.type(), specSize = 0, initSize = 0; - srcSize.width = src.cols; - srcSize.height = src.rows; - dstSize.width = dst.cols; - dstSize.height = dst.rows; - - switch (type) - { -#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; -#endif - case CV_16UC1: SET_IPP_RESIZE_PTR(16u,C1); break; - case CV_16UC3: SET_IPP_RESIZE_PTR(16u,C3); break; - case CV_16UC4: SET_IPP_RESIZE_PTR(16u,C4); break; - case CV_16SC1: SET_IPP_RESIZE_PTR(16s,C1); break; - case CV_16SC3: SET_IPP_RESIZE_PTR(16s,C3); break; - case CV_16SC4: SET_IPP_RESIZE_PTR(16s,C4); break; - case CV_32FC1: SET_IPP_RESIZE_PTR(32f,C1); break; - case CV_32FC3: SET_IPP_RESIZE_PTR(32f,C3); break; - case CV_32FC4: SET_IPP_RESIZE_PTR(32f,C4); break; - case CV_64FC1: SET_IPP_RESIZE_LINEAR_FUNC_64_PTR(64f,C1); break; - case CV_64FC3: SET_IPP_RESIZE_LINEAR_FUNC_64_PTR(64f,C3); break; - case CV_64FC4: SET_IPP_RESIZE_LINEAR_FUNC_64_PTR(64f,C4); break; - default: { *ok = false; return; } break; - } - } - - ~IPPresizeInvoker() - { - } - - virtual void operator() (const Range& range) const - { - if (*ok == false) - return; - - int cn = src.channels(); - int dsty = min(cvRound(range.start * inv_scale_y), dst.rows); - int dstwidth = min(cvRound(src.cols * inv_scale_x), dst.cols); - int dstheight = min(cvRound(range.end * inv_scale_y), dst.rows); - - IppiPoint dstOffset = { 0, dsty }, srcOffset = {0, 0}; - IppiSize dstSize = { dstwidth, dstheight - dsty }; - int bufsize = 0, itemSize = (int)src.elemSize1(); - - CHECK_IPP_STATUS(getBufferSizeFunc(pSpec, dstSize, cn, &bufsize)); - CHECK_IPP_STATUS(getSrcOffsetFunc(pSpec, dstOffset, &srcOffset)); - - const Ipp8u* pSrc = src.ptr(srcOffset.y) + srcOffset.x * cn * itemSize; - Ipp8u* pDst = dst.ptr(dstOffset.y) + dstOffset.x * cn * itemSize; - - AutoBuffer buf(bufsize + 64); - uchar* bufptr = alignPtr((uchar*)buf, 32); - - if( CV_INSTRUMENT_FUN_IPP(ippiResize, pSrc, (int)src.step[0], pDst, (int)dst.step[0], dstOffset, dstSize, ippBorderRepl, 0, pSpec, bufptr) < 0 ) - *ok = false; - else - { - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); - } - } -private: - const Mat & src; - Mat & dst; - double inv_scale_x; - double inv_scale_y; - void *pSpec; - AutoBuffer specBuf; - int mode; - ippiResizeFunc ippiResize; - ippiResizeGetBufferSize getBufferSizeFunc; - ippiResizeGetSrcOffset getSrcOffsetFunc; - bool *ok; - const IPPresizeInvoker& operator= (const IPPresizeInvoker&); -}; - -#endif - #ifdef HAVE_OPENCL - static void ocl_computeResizeAreaTabs(int ssize, int dsize, double scale, int * const map_tab, float * const alpha_tab, int * const ofs_tab) { @@ -3090,28 +2955,190 @@ static bool ocl_resize( InputArray _src, OutputArray _dst, Size dsize, #endif -#if IPP_VERSION_X100 >= 710 -static bool ipp_resize_mt(Mat & src, Mat & dst, - double inv_scale_x, double inv_scale_y, int interpolation) +#ifdef HAVE_IPP +#define IPP_RESIZE_PARALLEL 1 + +#ifdef HAVE_IPP_IW +class ipp_resizeParallel: public ParallelLoopBody { +public: + ipp_resizeParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, bool &ok): + m_src(src), m_dst(dst), m_ok(ok) {} + ~ipp_resizeParallel() + { + } + + void Init(IppiInterpolationType inter) + { + iwiResize.InitAlloc(m_src.m_size, m_dst.m_size, m_src.m_dataType, m_src.m_channels, inter, ::ipp::IwiResizeParams(0, 0, 0.75, 4), ippBorderRepl); + + m_ok = true; + } + + virtual void operator() (const Range& range) const + { + CV_INSTRUMENT_REGION_IPP() + + if(!m_ok) + return; + + try + { + ::ipp::IwiRoi roi = ::ipp::IwiRect(0, range.start, m_dst.m_size.width, range.end - range.start); + CV_INSTRUMENT_FUN_IPP(iwiResize, &m_src, &m_dst, &roi); + } + catch(::ipp::IwException) + { + m_ok = false; + return; + } + } +private: + ::ipp::IwiImage &m_src; + ::ipp::IwiImage &m_dst; + + mutable ::ipp::IwiResize iwiResize; + + volatile bool &m_ok; + const ipp_resizeParallel& operator= (const ipp_resizeParallel&); +}; + +class ipp_resizeAffineParallel: public ParallelLoopBody +{ +public: + ipp_resizeAffineParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, bool &ok): + m_src(src), m_dst(dst), m_ok(ok) {} + ~ipp_resizeAffineParallel() + { + } + + void Init(IppiInterpolationType inter, double scaleX, double scaleY) + { + double shift = (inter == ippNearest)?-1e-10:-0.5; + double coeffs[2][3] = { + {scaleX, 0, shift+0.5*scaleX}, + {0, scaleY, shift+0.5*scaleY} + }; + + iwiWarpAffine.InitAlloc(m_src.m_size, m_dst.m_size, m_src.m_dataType, m_src.m_channels, coeffs, ippWarpForward, inter, ::ipp::IwiWarpAffineParams(0, 0.75, 0), ippBorderRepl); + + m_ok = true; + } + + virtual void operator() (const Range& range) const + { + CV_INSTRUMENT_REGION_IPP() + + if(!m_ok) + return; + + try + { + ::ipp::IwiRoi roi = ::ipp::IwiRect(0, range.start, m_dst.m_size.width, range.end - range.start); + CV_INSTRUMENT_FUN_IPP(iwiWarpAffine, &m_src, &m_dst, &roi); + } + catch(::ipp::IwException) + { + m_ok = false; + return; + } + } +private: + ::ipp::IwiImage &m_src; + ::ipp::IwiImage &m_dst; + + mutable ::ipp::IwiWarpAffine iwiWarpAffine; + + volatile bool &m_ok; + const ipp_resizeAffineParallel& operator= (const ipp_resizeAffineParallel&); +}; +#endif + +static bool ipp_resize(const uchar * src_data, size_t src_step, int src_width, int src_height, + uchar * dst_data, size_t dst_step, int dst_width, int dst_height, double inv_scale_x, double inv_scale_y, + int depth, int channels, int interpolation) +{ +#ifdef HAVE_IPP_IW CV_INSTRUMENT_REGION_IPP() - int mode = -1; - if (interpolation == INTER_LINEAR && src.rows >= 2 && src.cols >= 2) - mode = ippLinear; - else if (interpolation == INTER_CUBIC && src.rows >= 4 && src.cols >= 4) - mode = ippCubic; - else + IppDataType ippDataType = ippiGetDataType(depth); + IppiInterpolationType ippInter = ippiGetInterpolation(interpolation); + if(ippInter < 0) return false; - bool ok = true; - Range range(0, src.rows); - IPPresizeInvoker invoker(src, dst, inv_scale_x, inv_scale_y, mode, &ok); - parallel_for_(range, invoker, dst.total()/(double)(1<<16)); - if( ok ) - return true; +#if IPP_DISABLE_RESIZE_NEAREST + if(ippInter == ippNearest) + return false; +#endif +#if IPP_DISABLE_RESIZE_AREA + if(ippInter == ippSuper) + return false; +#endif + + if(ippInter != ippLinear && ippDataType == ipp64f) + return false; + + // Accuracy mismatch is 1 but affects detectors greatly +#if IPP_DISABLE_RESIZE_8U + if(ippDataType == ipp8u && ippInter == ippLinear) + return false; +#endif + + bool affine = false; + const double IPP_RESIZE_EPS = (depth == CV_64F)?0:1e-10; + double ex = fabs((double)dst_width / src_width - inv_scale_x) / inv_scale_x; + double ey = fabs((double)dst_height / src_height - inv_scale_y) / inv_scale_y; + + // Use affine transform resize to allow sub-pixel accuracy + if(ex > IPP_RESIZE_EPS || ey > IPP_RESIZE_EPS) + affine = true; + + // Affine doesn't support Lanczos and Super interpolations + if(affine && (ippInter == ippLanczos || ippInter == ippSuper)) + return false; + + try + { + ::ipp::IwiImage iwSrc(::ipp::IwiSize(src_width, src_height), ippDataType, channels, 0, (void*)src_data, src_step); + ::ipp::IwiImage iwDst(::ipp::IwiSize(dst_width, dst_height), ippDataType, channels, 0, (void*)dst_data, dst_step); + + bool ok; + int threads = ippiSuggestThreadsNum(iwDst, 1+((double)(src_width*src_height)/(dst_width*dst_height))); + Range range(0, dst_height); + ipp_resizeParallel invokerGeneral(iwSrc, iwDst, ok); + ipp_resizeAffineParallel invokerAffine(iwSrc, iwDst, ok); + ParallelLoopBody *pInvoker = NULL; + if(affine) + { + pInvoker = &invokerAffine; + invokerAffine.Init(ippInter, inv_scale_x, inv_scale_y); + } + else + { + pInvoker = &invokerGeneral; + invokerGeneral.Init(ippInter); + } + + if(IPP_RESIZE_PARALLEL && threads > 1) + parallel_for_(range, *pInvoker, threads*4); + else + pInvoker->operator()(range); + + if(!ok) + return false; + } + catch(::ipp::IwException) + { + return false; + } + return true; +#else + CV_UNUSED(src_data); CV_UNUSED(src_step); CV_UNUSED(src_width); CV_UNUSED(src_height); CV_UNUSED(dst_data); CV_UNUSED(dst_step); + CV_UNUSED(dst_width); CV_UNUSED(dst_height); CV_UNUSED(inv_scale_x); CV_UNUSED(inv_scale_y); CV_UNUSED(depth); + CV_UNUSED(channels); CV_UNUSED(interpolation); return false; +#endif } #endif @@ -3135,6 +3162,13 @@ void resize(int src_type, CALL_HAL(resize, cv_hal_resize, src_type, src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, dst_height, inv_scale_x, inv_scale_y, interpolation); + int depth = CV_MAT_DEPTH(src_type), cn = CV_MAT_CN(src_type); + Size dsize = Size(saturate_cast(src_width*inv_scale_x), + saturate_cast(src_height*inv_scale_y)); + CV_Assert( dsize.area() > 0 ); + + CV_IPP_RUN_FAST(ipp_resize(src_data, src_step, src_width, src_height, dst_data, dst_step, dsize.width, dsize.height, inv_scale_x, inv_scale_y, depth, cn, interpolation)) + static ResizeFunc linear_tab[] = { resizeGeneric_< @@ -3239,7 +3273,6 @@ void resize(int src_type, resizeArea_, 0 }; - int depth = CV_MAT_DEPTH(src_type), cn = CV_MAT_CN(src_type); double scale_x = 1./inv_scale_x, scale_y = 1./inv_scale_y; int iscale_x = saturate_cast(scale_x); @@ -3248,31 +3281,9 @@ void resize(int src_type, bool is_area_fast = std::abs(scale_x - iscale_x) < DBL_EPSILON && std::abs(scale_y - iscale_y) < DBL_EPSILON; - Size dsize = Size(saturate_cast(src_width*inv_scale_x), - saturate_cast(src_height*inv_scale_y)); - CV_Assert( dsize.area() > 0 ); - Mat src(Size(src_width, src_height), src_type, const_cast(src_data), src_step); Mat dst(dsize, src_type, dst_data, dst_step); -#ifdef HAVE_IPP - int mode = -1; - if (interpolation == INTER_LINEAR && src_height >= 2 && src_width >= 2) - mode = INTER_LINEAR; - else if (interpolation == INTER_CUBIC && src_height >= 4 && src_width >= 4) - mode = INTER_CUBIC; - - const double IPP_RESIZE_EPS = 1e-10; - double ex = fabs((double)dsize.width / src_width - inv_scale_x) / inv_scale_x; - double ey = fabs((double)dsize.height / src_height - inv_scale_y) / inv_scale_y; -#endif - 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 || - (depth == CV_64F && mode == INTER_LINEAR)), - ipp_resize_mt(src, dst, inv_scale_x, inv_scale_y, interpolation)) - if( interpolation == INTER_NEAREST ) { resizeNN( src, dst, inv_scale_x, inv_scale_y ); @@ -4829,7 +4840,7 @@ static bool openvx_remap(Mat src, Mat dst, Mat map1, Mat map2, int interpolation } #endif -#if defined HAVE_IPP && IPP_DISABLE_BLOCK +#if defined HAVE_IPP && !IPP_DISABLE_REMAP typedef IppStatus (CV_STDCALL * ippiRemap)(const void * pSrc, IppiSize srcSize, int srcStep, IppiRect srcRoi, const Ipp32f* pxMap, int xMapStep, const Ipp32f* pyMap, int yMapStep, @@ -4861,9 +4872,9 @@ public: return; } - if (CV_INSTRUMENT_FUN_PTR_CALL_IPP(ippFunc,(src.ptr(), ippiSize(src.size()), (int)src.step, srcRoiRect, + if (CV_INSTRUMENT_FUN_IPP(ippFunc, src.ptr(), ippiSize(src.size()), (int)src.step, srcRoiRect, map1.ptr(), (int)map1.step, map2.ptr(), (int)map2.step, - dstRoi.ptr(), (int)dstRoi.step, dstRoiSize, ippInterpolation)) < 0) + dstRoi.ptr(), (int)dstRoi.step, dstRoiSize, ippInterpolation) < 0) *ok = false; else { @@ -4952,7 +4963,7 @@ void cv::remap( InputArray _src, OutputArray _dst, int type = src.type(), depth = CV_MAT_DEPTH(type); -#if defined HAVE_IPP && IPP_DISABLE_BLOCK +#if defined HAVE_IPP && !IPP_DISABLE_REMAP CV_IPP_CHECK() { if ((interpolation == INTER_LINEAR || interpolation == INTER_CUBIC || interpolation == INTER_NEAREST) && @@ -5680,7 +5691,9 @@ private: }; -#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_WARPAFFINE +typedef IppStatus (CV_STDCALL* ippiWarpAffineBackFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [2][3], int); + class IPPWarpAffineInvoker : public ParallelLoopBody { @@ -5711,7 +5724,7 @@ public: } // Aug 2013: problem in IPP 7.1, 8.0 : sometimes function return ippStsCoeffErr - IppStatus status = CV_INSTRUMENT_FUN_PTR_CALL_IPP(func,( src.ptr(), srcsize, (int)src.step[0], srcroi, dst.ptr(), + IppStatus status = CV_INSTRUMENT_FUN_IPP(func,( src.ptr(), srcsize, (int)src.step[0], srcroi, dst.ptr(), (int)dst.step[0], dstroi, coeffs, mode )); if( status < 0) *ok = false; @@ -5988,7 +6001,7 @@ void cv::warpAffine( InputArray _src, OutputArray _dst, M[2] = b1; M[5] = b2; } -#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_WARPAFFINE CV_IPP_CHECK() { int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); @@ -6403,7 +6416,9 @@ private: Scalar borderValue; }; -#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_WARPPERSPECTIVE +typedef IppStatus (CV_STDCALL* ippiWarpPerspectiveFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [3][3], int); + class IPPWarpPerspectiveInvoker : public ParallelLoopBody { @@ -6434,7 +6449,7 @@ public: } } - IppStatus status = CV_INSTRUMENT_FUN_PTR_CALL_IPP(func,(src.ptr(), srcsize, (int)src.step[0], srcroi, dst.ptr(), (int)dst.step[0], dstroi, coeffs, mode)); + IppStatus status = CV_INSTRUMENT_FUN_IPP(func,(src.ptr(), srcsize, (int)src.step[0], srcroi, dst.ptr(), (int)dst.step[0], dstroi, coeffs, mode)); if (status != ippStsNoErr) *ok = false; else @@ -6507,7 +6522,7 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0, CV_Assert( (M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 3 && M0.cols == 3 ); M0.convertTo(matM, matM.type()); -#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && IPP_DISABLE_BLOCK +#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_WARPPERSPECTIVE CV_IPP_CHECK() { int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 4dd0508514..982b2946fe 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1113,68 +1113,20 @@ static bool halMorph(int op, int src_type, int dst_type, } // ===== 2. IPP implementation - #ifdef HAVE_IPP - -#if IPP_VERSION_X100 >= 810 - -template struct IppMorphTrait {}; - -#if IPP_VERSION_X100 >= 900 - -#define DEFINE_TRAIT(cvtype, ipptype, flavor, channels, zerodef)\ -template <>\ -struct IppMorphTrait\ -{\ - typedef Ipp##ipptype ipp_data_type;\ - enum { cn = channels };\ - IppDataType getDataType() {return ipp##ipptype;}\ -\ - IppStatus getMorphSize(IppiSize roiSize, IppiSize maskSize, int* pSpecSize, int* pBufferSize) {return ippiMorphologyBorderGetSize_##flavor(roiSize, maskSize, pSpecSize, pBufferSize);}\ - IppStatus morphInit(IppiSize roiSize, const Ipp8u* pMask, IppiSize maskSize, IppiMorphState* pMorphSpec, Ipp8u* pBuffer) {return ippiMorphologyBorderInit_##flavor(roiSize, pMask, maskSize, pMorphSpec, pBuffer);}\ - IppStatus filterGetMinSize(IppiSize dstRoiSize, IppiSize maskSize, IppDataType dataType, int numChannels, int* pBufferSize) {return ippiFilterMinBorderGetBufferSize(dstRoiSize, maskSize, dataType, numChannels, pBufferSize);}\ - IppStatus filterGetMaxSize(IppiSize dstRoiSize, IppiSize maskSize, IppDataType dataType, int numChannels, int* pBufferSize) {return ippiFilterMaxBorderGetBufferSize(dstRoiSize, maskSize, dataType, numChannels, pBufferSize);}\ - IppStatus filterMinBorder(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize dstRoiSize, IppiSize maskSize, IppiPoint, Ipp8u* pBuffer) { ipp_data_type zerodef; return CV_INSTRUMENT_FUN_IPP(ippiFilterMinBorder_##flavor, pSrc, srcStep, pDst, dstStep, dstRoiSize, maskSize, ippBorderRepl, zero, pBuffer); }\ - IppStatus filterMaxBorder(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize dstRoiSize, IppiSize maskSize, IppiPoint, Ipp8u* pBuffer) { ipp_data_type zerodef; return CV_INSTRUMENT_FUN_IPP(ippiFilterMaxBorder_##flavor, pSrc, srcStep, pDst, dstStep, dstRoiSize, maskSize, ippBorderRepl, zero, pBuffer); }\ - IppStatus morphDilate(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize roiSize, const IppiMorphState* pMorphSpec, Ipp8u* pBuffer) { ipp_data_type zerodef; return CV_INSTRUMENT_FUN_IPP(ippiDilateBorder_##flavor, pSrc, srcStep, pDst, dstStep, roiSize, ippBorderRepl, zero, pMorphSpec, pBuffer); }\ - IppStatus morphErode(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize roiSize, const IppiMorphState* pMorphSpec, Ipp8u* pBuffer) { ipp_data_type zerodef; return CV_INSTRUMENT_FUN_IPP(ippiErodeBorder_##flavor, pSrc, srcStep, pDst, dstStep, roiSize, ippBorderRepl, zero, pMorphSpec, pBuffer); }\ -}; - -#else - -#define DEFINE_TRAIT(cvtype, ipptype, flavor, channels, zerodef)\ -template <>\ -struct IppMorphTrait\ -{\ - typedef Ipp##ipptype ipp_data_type;\ - enum { cn = channels };\ - IppDataType getDataType() {return ipp##ipptype;}\ -\ - IppStatus getMorphSize(IppiSize roiSize, IppiSize maskSize, int* pSpecSize, int* pBufferSize) {return ippiMorphologyBorderGetSize_##flavor(roiSize.width, maskSize, pSpecSize, pBufferSize);}\ - IppStatus morphInit(IppiSize roiSize, const Ipp8u* pMask, IppiSize maskSize, IppiMorphState* pMorphSpec, Ipp8u* pBuffer) {return ippiMorphologyBorderInit_##flavor(roiSize.width, pMask, maskSize, pMorphSpec, pBuffer);}\ - IppStatus filterGetMinSize(IppiSize dstRoiSize, IppiSize maskSize, IppDataType, int, int* pBufferSize) {return ippiFilterMinGetBufferSize_##flavor(dstRoiSize.width, maskSize, pBufferSize);}\ - IppStatus filterGetMaxSize(IppiSize dstRoiSize, IppiSize maskSize, IppDataType, int, int* pBufferSize) {return ippiFilterMinGetBufferSize_##flavor(dstRoiSize.width, maskSize, pBufferSize);}\ - IppStatus filterMinBorder(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize dstRoiSize, IppiSize maskSize, IppiPoint anchor, Ipp8u* pBuffer) { return ippiFilterMinBorderReplicate_##flavor(pSrc, srcStep, pDst, dstStep, dstRoiSize, maskSize, anchor, pBuffer); }\ - IppStatus filterMaxBorder(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize dstRoiSize, IppiSize maskSize, IppiPoint anchor, Ipp8u* pBuffer) { return ippiFilterMaxBorderReplicate_##flavor(pSrc, srcStep, pDst, dstStep, dstRoiSize, maskSize, anchor, pBuffer); }\ - IppStatus morphDilate(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize roiSize, const IppiMorphState* pMorphSpec, Ipp8u* pBuffer) {return ippiDilateBorder_##flavor(pSrc, srcStep, pDst, dstStep, roiSize, ippBorderRepl, 0, pMorphSpec, pBuffer);}\ - IppStatus morphErode(const ipp_data_type* pSrc, int srcStep, ipp_data_type* pDst, int dstStep, IppiSize roiSize, const IppiMorphState* pMorphSpec, Ipp8u* pBuffer) {return ippiErodeBorder_##flavor(pSrc, srcStep, pDst, dstStep, roiSize, ippBorderRepl, 0, pMorphSpec, pBuffer);}\ -}; - +#ifdef HAVE_IPP_IW +static inline IwiMorphologyType ippiGetMorphologyType(int morphOp) +{ + return morphOp == MORPH_ERODE ? iwiMorphErode : + morphOp == MORPH_DILATE ? iwiMorphDilate : + morphOp == MORPH_OPEN ? iwiMorphOpen : + morphOp == MORPH_CLOSE ? iwiMorphClose : + morphOp == MORPH_GRADIENT ? iwiMorphGradient : + morphOp == MORPH_TOPHAT ? iwiMorphTophat : + morphOp == MORPH_BLACKHAT ? iwiMorphBlackhat : (IwiMorphologyType)-1; +} #endif -DEFINE_TRAIT(CV_8UC1, 8u, 8u_C1R, 1, zero = 0) -DEFINE_TRAIT(CV_8UC3, 8u, 8u_C3R, 3, zero[3] = {0}) -DEFINE_TRAIT(CV_8UC4, 8u, 8u_C4R, 4, zero[4] = {0}) -DEFINE_TRAIT(CV_32FC1, 32f, 32f_C1R, 1, zero = 0) -DEFINE_TRAIT(CV_32FC3, 32f, 32f_C3R, 3, zero[3] = {0}) -DEFINE_TRAIT(CV_32FC4, 32f, 32f_C4R, 4, zero[4] = {0}) - -#undef DEFINE_TRAIT - -//-------------------------------------- - - -template static bool ippMorph(int op, int src_type, int dst_type, const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, @@ -1185,146 +1137,131 @@ static bool ippMorph(int op, int src_type, int dst_type, int kernel_width, int kernel_height, int anchor_x, int anchor_y, int borderType, const double borderValue[4], int iterations, bool isSubmatrix) { - IppMorphTrait trait; - typedef typename IppMorphTrait::ipp_data_type ipp_data_type; - IppAutoBuffer specBuf; - IppAutoBuffer workBuf; - IppiSize kernelSize; - bool rectKernel; - IppiPoint anchor; - +#ifdef HAVE_IPP_IW CV_INSTRUMENT_REGION_IPP() - CV_UNUSED(roi_width); CV_UNUSED(roi_height); CV_UNUSED(roi_x); CV_UNUSED(roi_y); - CV_UNUSED(roi_width2); CV_UNUSED(roi_height2); CV_UNUSED(roi_x2); CV_UNUSED(roi_y2); - CV_UNUSED(dst_type); + // Problem with SSE42 optimizations +#if IPP_DISABLE_PERF_MORPH_SSE42 + if(!(ipp::getIppFeatures()&ippCPUID_AVX)) + return false; +#endif - anchor = ippiPoint(anchor_x, anchor_y); + ::ipp::IwAutoBuffer kernelTempBuffer; + ::ipp::IwiBorderSize iwBorderSize; + ::ipp::IwiBorderType iwBorderType; + ::ipp::IwiImage iwMask; + ::ipp::IwiImage iwInter; + ::ipp::IwiSize initSize(width, height); + ::ipp::IwiSize kernelSize(kernel_width, kernel_height); + ::ipp::IwiPoint anchor(anchor_x, anchor_y); + IppDataType type = ippiGetDataType(CV_MAT_DEPTH(src_type)); + int channels = CV_MAT_CN(src_type); + IwiMorphologyType morphType = ippiGetMorphologyType(op); - Mat kernel(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step); - int depth = CV_MAT_DEPTH(src_type), cn = CV_MAT_CN(src_type); + CV_UNUSED(isSubmatrix); - if( !( depth == CV_8U || depth == CV_32F ) - || !(cn == 1 || cn == 3 || cn == 4) - || !( borderType == cv::BORDER_REPLICATE - || (borderType == cv::BORDER_CONSTANT && Vec(borderValue) == morphologyDefaultBorderValue() && kernel.size() == Size(3,3))) - || !( op == MORPH_DILATE || op == MORPH_ERODE) - || isSubmatrix - || src_data == dst_data) + if(morphType < 0) return false; - // In case BORDER_CONSTANT, IPPMorphReplicate works correct with kernels of size 3*3 only - if( borderType == cv::BORDER_CONSTANT && kernel.data ) - { - int x, y; - for( y = 0; y < kernel.rows; y++ ) - { - if( kernel.at(y, anchor.x) != 0 ) - continue; - for( x = 0; x < kernel.cols; x++ ) - { - if( kernel.at(y,x) != 0 ) - return false; - } - } - for( x = 0; x < kernel.cols; x++ ) - { - if( kernel.at(anchor.y, x) != 0 ) - continue; - for( y = 0; y < kernel.rows; y++ ) - { - if( kernel.at(y,x) != 0 ) - return false; - } - } - - } - - Size ksize = !kernel.empty() ? kernel.size() : Size(3,3); - - rectKernel = false; - if( kernel.empty() ) - { - ksize = Size(1+iterations*2,1+iterations*2); - anchor = ippiPoint(iterations, iterations); - rectKernel = true; - iterations = 1; - } - else if( iterations >= 1 && countNonZero(kernel) == kernel.rows*kernel.cols ) - { - ksize = Size(ksize.width + (iterations-1)*(ksize.width-1), - ksize.height + (iterations-1)*(ksize.height-1)), - anchor = ippiPoint(anchor.x*iterations, anchor.y*iterations); - kernel = Mat(); - rectKernel = true; - iterations = 1; - } - - // TODO: implement the case of iterations > 1. - if( iterations > 1 ) + if(iterations > 1 && morphType != iwiMorphErode && morphType != iwiMorphDilate) return false; - IppiSize roiSize = {width, height}; - kernelSize = ippiSize(ksize); + if(src_type != dst_type) + return false; - IppStatus res; - if (!rectKernel) + try { - if (((kernel.cols - 1) / 2 != anchor.x) || ((kernel.rows - 1) / 2 != anchor.y)) + ::ipp::IwiImage iwSrc(initSize, type, channels, ::ipp::IwiBorderSize(roi_x, roi_y, roi_width-roi_x-width, roi_height-roi_y-height), (void*)src_data, src_step); + ::ipp::IwiImage iwDst(initSize, type, channels, ::ipp::IwiBorderSize(roi_x2, roi_y2, roi_width2-roi_x2-width, roi_height2-roi_y2-height), (void*)dst_data, dst_step); + + ::ipp::iwiFilterMorphology_GetBorderSize(morphType, kernelSize, iwBorderSize); + if(morphType != iwiMorphErode && morphType != iwiMorphDilate) + { + iwBorderSize.borderLeft /= 2; + iwBorderSize.borderTop /= 2; + iwBorderSize.borderRight /= 2; + iwBorderSize.borderBottom /= 2; + } + + iwBorderType = ippiGetBorder(iwSrc, borderType, iwBorderSize); + if(!iwBorderType.m_borderType || ((iwBorderType.m_borderFlags&ippBorderInMem) && (iwBorderType.m_borderFlags&ippBorderInMem) != ippBorderInMem)) return false; - int specSize = 0, bufferSize = 0; - res = trait.getMorphSize(roiSize, kernelSize, &specSize, &bufferSize); - if (res >= 0) + + if(iwBorderType.m_borderType == ippBorderConst) { - specBuf.Alloc(specSize); - workBuf.Alloc(bufferSize); - res = trait.morphInit(roiSize, kernel.ptr(), kernelSize, specBuf, workBuf); - if (res < 0) - return false; - } - } - else - { - if (((kernelSize.width - 1) / 2 != anchor.x) || ((kernelSize.height - 1) / 2 != anchor.y)) - return false; - if (op == MORPH_ERODE) - { - int bufSize = 0; - res = trait.filterGetMinSize(roiSize, kernelSize, trait.getDataType(), trait.cn, &bufSize); - if (res >= 0) - workBuf.Alloc(bufSize); + if(Vec(borderValue) == morphologyDefaultBorderValue()) + iwBorderType.m_borderType = ippBorderDefault; else - return false; + iwBorderType.SetValue(borderValue[0], borderValue[1], borderValue[2], borderValue[3]); + } + if(morphType != iwiMorphErode && morphType != iwiMorphDilate) + { + if((iwBorderType.m_borderFlags&ippBorderInMem) == ippBorderInMem) + iwBorderType.m_borderFlags = ippBorderFirstStageInMem; + } + + // Test input parameters on dummy structures + { + ::ipp::IwiImage testSrc(initSize, type, channels); + ::ipp::IwiImage testDst(initSize, type, channels); + ::ipp::IwiImage testMask(ippiSize(kernel_width, kernel_height), ipp8u, CV_MAT_CN(kernel_type)); + + ::ipp::iwiFilterMorphology(&testSrc, &testDst, morphType, &testMask, &anchor, iwBorderType); + } + + iwMask.Init(ippiSize(kernel_width, kernel_height), ippiGetDataType(CV_MAT_DEPTH(kernel_type)), CV_MAT_CN(kernel_type), 0, kernel_data, kernel_step); + if((int)kernel_step != kernel_width || CV_MAT_DEPTH(kernel_type) != CV_8U) + { + kernelTempBuffer.Alloc(kernel_width*kernel_height); + ::ipp::IwiImage iwMaskTmp(ippiSize(kernel_width, kernel_height), ipp8u, 1, 0, kernelTempBuffer, kernel_width); + ::ipp::iwiScale(&iwMask, &iwMaskTmp, 1, 0); + iwMask = iwMaskTmp; + } + + if(iterations > 1) + { + iwInter.Alloc(initSize, type, channels); + + ::ipp::IwiImage *pSwap[2] = {&iwInter, &iwDst}; + ::ipp::IwiBorderType iterBorder = iwBorderType; + iterBorder.m_borderFlags = 0; + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterMorphology, &iwSrc, &iwInter, morphType, &iwMask, NULL, iwBorderType); + + for(int i = 0; i < iterations-1; i++) + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterMorphology, pSwap[i&0x1], pSwap[(i+1)&0x1], morphType, &iwMask, NULL, iterBorder); + if(iterations&0x1) + CV_INSTRUMENT_FUN_IPP(::ipp::iwiCopyMask, &iwInter, &iwDst); } else { - int bufSize = 0; - res = trait.filterGetMaxSize(roiSize, kernelSize, trait.getDataType(), trait.cn, &bufSize); - if (res >= 0) - workBuf.Alloc(bufSize); + if(src_data == dst_data) + { + iwInter.Alloc(initSize, type, channels); + + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterMorphology, &iwSrc, &iwInter, morphType, &iwMask, NULL, iwBorderType); + CV_INSTRUMENT_FUN_IPP(::ipp::iwiCopyMask, &iwInter, &iwDst); + } else - return false; + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterMorphology, &iwSrc, &iwDst, morphType, &iwMask, NULL, iwBorderType); } } + catch(::ipp::IwException ex) + { + return false; + } - if (!rectKernel) - { - if (op == MORPH_ERODE) - res = (trait.morphErode((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, specBuf, workBuf)); - else - res = (trait.morphDilate((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, specBuf, workBuf)); - } - else - { - if (op == MORPH_ERODE) - res = (trait.filterMinBorder((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, kernelSize, anchor, workBuf)); - else - res = (trait.filterMaxBorder((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, kernelSize, anchor, workBuf)); - } - return res >= 0; -} + return true; +#else + CV_UNUSED(op); CV_UNUSED(src_type); CV_UNUSED(dst_type); CV_UNUSED(src_data); CV_UNUSED(src_step); CV_UNUSED(dst_data); + CV_UNUSED(dst_step); CV_UNUSED(width); CV_UNUSED(height); CV_UNUSED(roi_width); CV_UNUSED(roi_height); + CV_UNUSED(roi_x); CV_UNUSED(roi_y); CV_UNUSED(roi_width2); CV_UNUSED(roi_height2); CV_UNUSED(roi_x2); CV_UNUSED(roi_y2); + CV_UNUSED(kernel_type); CV_UNUSED(kernel_data); CV_UNUSED(kernel_step); CV_UNUSED(kernel_width); CV_UNUSED(kernel_height); + CV_UNUSED(anchor_x); CV_UNUSED(anchor_y); CV_UNUSED(borderType); CV_UNUSED(borderValue); CV_UNUSED(iterations); + CV_UNUSED(isSubmatrix); + return false; +#endif +}; -#endif // IPP_VERSION_X100 >= 810 #endif // HAVE_IPP // ===== 3. Fallback implementation @@ -1393,37 +1330,12 @@ void morph(int op, int src_type, int dst_type, return; } -#if defined(HAVE_IPP) && IPP_VERSION_X100 >= 810 - -#define ONE_CASE(type) \ - case type: \ - res = ippMorph(op, src_type, dst_type, src_data, src_step, dst_data, dst_step, width, height, \ - roi_width, roi_height, roi_x, roi_y, \ - roi_width2, roi_height2, roi_x2, roi_y2, \ - kernel_type, kernel_data, kernel_step, \ - kernel_width, kernel_height, anchor_x, anchor_y, \ - borderType, borderValue, iterations, isSubmatrix); \ - break; - - CV_IPP_CHECK() - { - bool res = false; - switch (src_type) - { - ONE_CASE(CV_8UC1) - ONE_CASE(CV_8UC3) - ONE_CASE(CV_8UC4) - ONE_CASE(CV_32FC1) - ONE_CASE(CV_32FC3) - ONE_CASE(CV_32FC4) - } - if (res) - return; - } - -#undef ONE_CASE - -#endif + CV_IPP_RUN_FAST(ippMorph(op, src_type, dst_type, src_data, src_step, dst_data, dst_step, width, height, + roi_width, roi_height, roi_x, roi_y, + roi_width2, roi_height2, roi_x2, roi_y2, + kernel_type, kernel_data, kernel_step, + kernel_width, kernel_height, anchor_x, anchor_y, + borderType, borderValue, iterations, isSubmatrix)); ocvMorph(op, src_type, dst_type, src_data, src_step, dst_data, dst_step, width, height, roi_width, roi_height, roi_x, roi_y, @@ -1854,6 +1766,8 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { + CV_INSTRUMENT_REGION() + Mat kernel = _kernel.getMat(); Size ksize = !kernel.empty() ? kernel.size() : Size(3,3); anchor = normalizeAnchor(anchor, ksize); @@ -1996,7 +1910,77 @@ static bool ocl_morphologyEx(InputArray _src, OutputArray _dst, int op, } } +#endif +#ifdef HAVE_IPP +#if !IPP_DISABLE_MORPH_ADV +namespace cv { +static bool ipp_morphologyEx(int op, InputArray _src, OutputArray _dst, + InputArray _kernel, + Point anchor, int iterations, + int borderType, const Scalar& borderValue) +{ +#if defined HAVE_IPP_IW + Mat kernel = _kernel.getMat(); + Size ksize = !kernel.empty() ? kernel.size() : Size(3,3); + anchor = normalizeAnchor(anchor, ksize); + + if (iterations == 0 || kernel.rows*kernel.cols == 1) + { + _src.copyTo(_dst); + return true; + } + + if (kernel.empty()) + { + kernel = getStructuringElement(MORPH_RECT, Size(1+iterations*2,1+iterations*2)); + anchor = Point(iterations, iterations); + iterations = 1; + } + else if( iterations > 1 && countNonZero(kernel) == kernel.rows*kernel.cols ) + { + anchor = Point(anchor.x*iterations, anchor.y*iterations); + kernel = getStructuringElement(MORPH_RECT, + Size(ksize.width + (iterations-1)*(ksize.width-1), + ksize.height + (iterations-1)*(ksize.height-1)), + anchor); + iterations = 1; + } + + Mat src = _src.getMat(); + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); + + Point s_ofs; + Size s_wsz(src.cols, src.rows); + Point d_ofs; + Size d_wsz(dst.cols, dst.rows); + bool isolated = (borderType&BORDER_ISOLATED)?true:false; + borderType = (borderType&~BORDER_ISOLATED); + + if(!isolated) + { + src.locateROI(s_wsz, s_ofs); + dst.locateROI(d_wsz, d_ofs); + } + + return ippMorph(op, src.type(), dst.type(), + src.data, src.step, + dst.data, dst.step, + src.cols, src.rows, + s_wsz.width, s_wsz.height, s_ofs.x, s_ofs.y, + d_wsz.width, d_wsz.height, d_ofs.x, d_ofs.y, + kernel.type(), kernel.data, kernel.step, kernel.cols, kernel.rows, anchor.x, anchor.y, + borderType, borderValue.val, iterations, + (src.isSubmatrix() && !isolated)); +#else + CV_UNUSED(op); CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(_kernel); CV_UNUSED(anchor); + CV_UNUSED(iterations); CV_UNUSED(borderType); CV_UNUSED(borderValue); + return false; +#endif +} +} +#endif #endif void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, @@ -2024,7 +2008,11 @@ void cv::morphologyEx( InputArray _src, OutputArray _dst, int op, _dst.create(src.size(), src.type()); Mat dst = _dst.getMat(); - Mat k1, k2, e1, e2; //only for hit and miss op +#if !IPP_DISABLE_MORPH_ADV + CV_IPP_RUN_FAST(ipp_morphologyEx(op, src, dst, kernel, anchor, iterations, borderType, borderValue)); +#endif + + Mat k1, k2, e1, e2; //only for hit and miss op switch( op ) { diff --git a/modules/imgproc/src/precomp.hpp b/modules/imgproc/src/precomp.hpp index 20a43a6736..40598a083e 100644 --- a/modules/imgproc/src/precomp.hpp +++ b/modules/imgproc/src/precomp.hpp @@ -93,6 +93,19 @@ extern const float icv8x32fSqrTab[]; #undef CV_CALC_MAX #define CV_CALC_MAX(a, b) if((a) < (b)) (a) = (b) +#ifdef HAVE_IPP +static inline IppiInterpolationType ippiGetInterpolation(int inter) +{ + inter &= cv::INTER_MAX; + return inter == cv::INTER_NEAREST ? ippNearest : + inter == cv::INTER_LINEAR ? ippLinear : + inter == cv::INTER_CUBIC ? ippCubic : + inter == cv::INTER_LANCZOS4 ? ippLanczos : + inter == cv::INTER_AREA ? ippSuper : + (IppiInterpolationType)-1; +} +#endif + #include "_geom.h" #include "filterengine.hpp" diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index d9c88d6dad..ae6629f57c 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -2295,101 +2295,54 @@ static bool openvx_gaussianBlur(InputArray _src, OutputArray _dst, Size ksize, #endif #ifdef HAVE_IPP - -static bool ipp_GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, - double sigma1, double sigma2, - int borderType ) +static bool ipp_GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, + double sigma1, double sigma2, int borderType ) { +#ifdef HAVE_IPP_IW CV_INSTRUMENT_REGION_IPP() -#if IPP_VERSION_X100 >= 810 - if ((borderType & BORDER_ISOLATED) == 0 && _src.isSubmatrix()) +#if IPP_VERSION_X100 <= 201702 && ((defined _MSC_VER && defined _M_IX86) || (defined __GNUC__ && defined __i386__)) + CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ksize); CV_UNUSED(sigma1); CV_UNUSED(sigma2); CV_UNUSED(borderType); + return false; // bug on ia32 +#else + if(sigma1 != sigma2) return false; - int type = _src.type(); - Size size = _src.size(); + if(sigma1 < FLT_EPSILON) + return false; - if( borderType != BORDER_CONSTANT && (borderType & BORDER_ISOLATED) != 0 ) + if(ksize.width != ksize.height) + return false; + + // Acquire data and begin processing + try { - if( size.height == 1 ) - ksize.height = 1; - if( size.width == 1 ) - ksize.width = 1; + Mat src = _src.getMat(); + Mat dst = _dst.getMat(); + ::ipp::IwiImage iwSrc = ippiGetImage(src); + ::ipp::IwiImage iwDst = ippiGetImage(dst); + ::ipp::IwiBorderSize borderSize(::ipp::IwiSize(ippiSize(ksize))); + ::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize)); + if(!ippBorder.m_borderType) + return false; + + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, &iwSrc, &iwDst, ksize.width, (float)sigma1, ippBorder); + } + catch (::ipp::IwException ex) + { + return false; } - int depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - - if ((depth == CV_8U || depth == CV_16U || depth == CV_16S || depth == CV_32F) && (cn == 1 || cn == 3) && - sigma1 == sigma2 && ksize.width == ksize.height && sigma1 != 0.0 ) - { - IppiBorderType ippBorder = ippiGetBorderType(borderType); - if (ippBorderConst == ippBorder || ippBorderRepl == ippBorder) - { - Mat src = _src.getMat(), dst = _dst.getMat(); - IppiSize roiSize = { src.cols, src.rows }; - IppDataType dataType = ippiGetDataType(depth); - Ipp32s specSize = 0, bufferSize = 0; - - if (ippiFilterGaussianGetBufferSize(roiSize, (Ipp32u)ksize.width, dataType, cn, &specSize, &bufferSize) >= 0) - { - IppAutoBuffer spec(specSize); - IppAutoBuffer buffer(bufferSize); - - if (ippiFilterGaussianInit(roiSize, (Ipp32u)ksize.width, (Ipp32f)sigma1, ippBorder, dataType, cn, spec, buffer) >= 0) - { -#define IPP_FILTER_GAUSS_C1(ippfavor) \ - { \ - Ipp##ippfavor borderValues = 0; \ - status = CV_INSTRUMENT_FUN_IPP(ippiFilterGaussianBorder_##ippfavor##_C1R, src.ptr(), (int)src.step, \ - dst.ptr(), (int)dst.step, roiSize, borderValues, spec, buffer); \ - } - -#define IPP_FILTER_GAUSS_CN(ippfavor, ippcn) \ - { \ - Ipp##ippfavor borderValues[] = { 0, 0, 0 }; \ - status = CV_INSTRUMENT_FUN_IPP(ippiFilterGaussianBorder_##ippfavor##_C##ippcn##R, src.ptr(), (int)src.step, \ - dst.ptr(), (int)dst.step, roiSize, borderValues, spec, buffer); \ - } - - IppStatus status = ippStsErr; -#if IPP_VERSION_X100 > 900 // Buffer overflow may happen in IPP 9.0.0 and less - if (type == CV_8UC1) - IPP_FILTER_GAUSS_C1(8u) - else + return true; #endif - if (type == CV_8UC3) - IPP_FILTER_GAUSS_CN(8u, 3) - else if (type == CV_16UC1) - IPP_FILTER_GAUSS_C1(16u) - else if (type == CV_16UC3) - IPP_FILTER_GAUSS_CN(16u, 3) - else if (type == CV_16SC1) - IPP_FILTER_GAUSS_C1(16s) - else if (type == CV_16SC3) - IPP_FILTER_GAUSS_CN(16s, 3) - else if (type == CV_32FC3) - IPP_FILTER_GAUSS_CN(32f, 3) - else if (type == CV_32FC1) - IPP_FILTER_GAUSS_C1(32f) - - if(status >= 0) - return true; - -#undef IPP_FILTER_GAUSS_C1 -#undef IPP_FILTER_GAUSS_CN - } - } - } - } #else CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ksize); CV_UNUSED(sigma1); CV_UNUSED(sigma2); CV_UNUSED(borderType); -#endif return false; +#endif } #endif } - void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) @@ -2423,17 +2376,18 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, if(sigma1 == 0 && sigma2 == 0 && tegra::useTegra() && tegra::gaussian(src, dst, ksize, borderType)) return; #endif + bool useOpenCL = (_dst.isUMat() && _src.dims() <= 2 && + ((ksize.width == 3 && ksize.height == 3) || + (ksize.width == 5 && ksize.height == 5)) && + _src.rows() > ksize.height && _src.cols() > ksize.width); + (void)useOpenCL; - CV_IPP_RUN(!(ocl::useOpenCL() && _dst.isUMat()), ipp_GaussianBlur( _src, _dst, ksize, sigma1, sigma2, borderType)); + CV_IPP_RUN(!useOpenCL, ipp_GaussianBlur( _src, _dst, ksize, sigma1, sigma2, borderType)); Mat kx, ky; createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2); - CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && - ((ksize.width == 3 && ksize.height == 3) || - (ksize.width == 5 && ksize.height == 5)) && - (size_t)_src.rows() > ky.total() && (size_t)_src.cols() > kx.total(), - ocl_GaussianBlur_8UC1(_src, _dst, ksize, CV_MAT_DEPTH(type), kx, ky, borderType)); + CV_OCL_RUN(useOpenCL, ocl_GaussianBlur_8UC1(_src, _dst, ksize, CV_MAT_DEPTH(type), kx, ky, borderType)); sepFilter2D(_src, _dst, CV_MAT_DEPTH(type), kx, ky, Point(-1,-1), 0, borderType ); } @@ -3430,60 +3384,69 @@ namespace cv #ifdef HAVE_IPP namespace cv { -static bool ipp_medianFilter( InputArray _src0, OutputArray _dst, int ksize ) +static bool ipp_medianFilter(Mat &src0, Mat &dst, int ksize) { CV_INSTRUMENT_REGION_IPP() -#if IPP_VERSION_X100 >= 810 - Mat src0 = _src0.getMat(); - _dst.create( src0.size(), src0.type() ); - Mat dst = _dst.getMat(); - -#define IPP_FILTER_MEDIAN_BORDER(ippType, ippDataType, flavor) \ - do \ - { \ - if (ippiFilterMedianBorderGetBufferSize(dstRoiSize, maskSize, \ - ippDataType, CV_MAT_CN(type), &bufSize) >= 0) \ - { \ - Ipp8u * buffer = ippsMalloc_8u(bufSize); \ - IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_##flavor, src.ptr(), (int)src.step, \ - dst.ptr(), (int)dst.step, dstRoiSize, maskSize, \ - ippBorderRepl, (ippType)0, buffer); \ - ippsFree(buffer); \ - if (status >= 0) \ - { \ - CV_IMPL_ADD(CV_IMPL_IPP); \ - return true; \ - } \ - } \ - } \ - while ((void)0, 0) - - if( ksize <= 5 ) { - Ipp32s bufSize; - IppiSize dstRoiSize = ippiSize(dst.cols, dst.rows), maskSize = ippiSize(ksize, ksize); + int bufSize; + IppiSize dstRoiSize = ippiSize(dst.cols, dst.rows), maskSize = ippiSize(ksize, ksize); + IppDataType ippType = ippiGetDataType(src0.type()); + int channels = src0.channels(); + IppAutoBuffer buffer; + + if(src0.isSubmatrix()) + return false; + Mat src; - if( dst.data != src0.data ) + if(dst.data != src0.data) src = src0; else src0.copyTo(src); - int type = src0.type(); - if (type == CV_8UC1) - IPP_FILTER_MEDIAN_BORDER(Ipp8u, ipp8u, 8u_C1R); - else if (type == CV_16UC1) - IPP_FILTER_MEDIAN_BORDER(Ipp16u, ipp16u, 16u_C1R); - else if (type == CV_16SC1) - IPP_FILTER_MEDIAN_BORDER(Ipp16s, ipp16s, 16s_C1R); - else if (type == CV_32FC1) - IPP_FILTER_MEDIAN_BORDER(Ipp32f, ipp32f, 32f_C1R); + if(ippiFilterMedianBorderGetBufferSize(dstRoiSize, maskSize, ippType, channels, &bufSize) < 0) + return false; + + buffer.allocate(bufSize); + + switch(ippType) + { + case ipp8u: + if(channels == 1) + return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_8u_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0; + else if(channels == 3) + return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_8u_C3R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0; + else if(channels == 4) + return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_8u_C4R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0; + else + return false; + case ipp16u: + if(channels == 1) + return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16u_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0; + else if(channels == 3) + return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16u_C3R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0; + else if(channels == 4) + return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16u_C4R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0; + else + return false; + case ipp16s: + if(channels == 1) + return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16s_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0; + else if(channels == 3) + return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16s_C3R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0; + else if(channels == 4) + return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_16s_C4R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0; + else + return false; + case ipp32f: + if(channels == 1) + return CV_INSTRUMENT_FUN_IPP(ippiFilterMedianBorder_32f_C1R, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, dstRoiSize, maskSize, ippBorderRepl, 0, buffer) >= 0; + else + return false; + default: + return false; + } } -#undef IPP_FILTER_MEDIAN_BORDER -#else - CV_UNUSED(_src0); CV_UNUSED(_dst); CV_UNUSED(ksize); -#endif - return false; } } #endif @@ -3510,7 +3473,7 @@ void cv::medianBlur( InputArray _src0, OutputArray _dst, int ksize ) CV_OVX_RUN(true, openvx_medianFilter(_src0, _dst, ksize)) - CV_IPP_RUN(IPP_VERSION_X100 >= 810 && ksize <= 5, ipp_medianFilter(_src0,_dst, ksize)); + CV_IPP_RUN_FAST(ipp_medianFilter(src0, dst, ksize)); #ifdef HAVE_TEGRA_OPTIMIZATION if (tegra::useTegra() && tegra::medianBlur(src0, dst, ksize)) diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index 5bae692dc7..7ac52d717b 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -560,82 +560,6 @@ static bool ocl_matchTemplate( InputArray _img, InputArray _templ, OutputArray _ #endif -#if defined HAVE_IPP - -typedef IppStatus (CV_STDCALL * ippimatchTemplate)(const void*, int, IppiSize, const void*, int, IppiSize, Ipp32f* , int , IppEnum , Ipp8u*); - -static bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst) -{ - CV_INSTRUMENT_REGION_IPP() - - IppStatus status; - - IppiSize srcRoiSize = {src.cols,src.rows}; - IppiSize tplRoiSize = {tpl.cols,tpl.rows}; - - Ipp8u *pBuffer; - int bufSize=0; - - int depth = src.depth(); - - ippimatchTemplate ippiCrossCorrNorm = - depth==CV_8U ? (ippimatchTemplate)ippiCrossCorrNorm_8u32f_C1R: - depth==CV_32F? (ippimatchTemplate)ippiCrossCorrNorm_32f_C1R: 0; - - if (ippiCrossCorrNorm==0) - return false; - - IppEnum funCfg = (IppEnum)(ippAlgAuto | ippiNormNone | ippiROIValid); - - status = ippiCrossCorrNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize); - if ( status < 0 ) - return false; - - pBuffer = ippsMalloc_8u( bufSize ); - - status = CV_INSTRUMENT_FUN_IPP(ippiCrossCorrNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr(), (int)dst.step, funCfg, pBuffer); - - ippsFree( pBuffer ); - return status >= 0; -} - -static bool ipp_sqrDistance(const Mat& src, const Mat& tpl, Mat& dst) -{ - CV_INSTRUMENT_REGION_IPP() - - IppStatus status; - - IppiSize srcRoiSize = {src.cols,src.rows}; - IppiSize tplRoiSize = {tpl.cols,tpl.rows}; - - Ipp8u *pBuffer; - int bufSize=0; - - int depth = src.depth(); - - ippimatchTemplate ippiSqrDistanceNorm = - depth==CV_8U ? (ippimatchTemplate)ippiSqrDistanceNorm_8u32f_C1R: - depth==CV_32F? (ippimatchTemplate)ippiSqrDistanceNorm_32f_C1R: 0; - - if (ippiSqrDistanceNorm==0) - return false; - - IppEnum funCfg = (IppEnum)(ippAlgAuto | ippiNormNone | ippiROIValid); - - status = ippiSqrDistanceNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize); - if ( status < 0 ) - return false; - - pBuffer = ippsMalloc_8u( bufSize ); - - status = CV_INSTRUMENT_FUN_IPP(ippiSqrDistanceNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr(), (int)dst.step, funCfg, pBuffer); - - ippsFree( pBuffer ); - return status >= 0; -} - -#endif - #include "opencv2/core/hal/hal.hpp" void crossCorr( const Mat& img, const Mat& _templ, Mat& corr, @@ -915,11 +839,7 @@ static void matchTemplateMask( InputArray _img, InputArray _templ, OutputArray _ else CV_Error(Error::StsNotImplemented, ""); } -} - -namespace cv -{ static void common_matchTemplate( Mat& img, Mat& templ, Mat& result, int method, int cn ) { if( method == CV_TM_CCORR ) @@ -1043,26 +963,117 @@ static void common_matchTemplate( Mat& img, Mat& templ, Mat& result, int method, #if defined HAVE_IPP namespace cv { -static bool ipp_matchTemplate( Mat& img, Mat& templ, Mat& result, int method, int cn ) +typedef IppStatus (CV_STDCALL * ippimatchTemplate)(const void*, int, IppiSize, const void*, int, IppiSize, Ipp32f* , int , IppEnum , Ipp8u*); + +static bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst, bool normed) { CV_INSTRUMENT_REGION_IPP() - bool useIppMT = (templ.rows < img.rows/2 && templ.cols < img.cols/2); + IppStatus status; - if(cn == 1 && useIppMT) + IppiSize srcRoiSize = {src.cols,src.rows}; + IppiSize tplRoiSize = {tpl.cols,tpl.rows}; + + IppAutoBuffer buffer; + int bufSize=0; + + int depth = src.depth(); + + ippimatchTemplate ippiCrossCorrNorm = + depth==CV_8U ? (ippimatchTemplate)ippiCrossCorrNorm_8u32f_C1R: + depth==CV_32F? (ippimatchTemplate)ippiCrossCorrNorm_32f_C1R: 0; + + if (ippiCrossCorrNorm==0) + return false; + + IppEnum funCfg = (IppEnum)(ippAlgAuto | ippiROIValid); + if(normed) + funCfg |= ippiNorm; + else + funCfg |= ippiNormNone; + + status = ippiCrossCorrNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize); + if ( status < 0 ) + return false; + + buffer.allocate( bufSize ); + + status = CV_INSTRUMENT_FUN_IPP(ippiCrossCorrNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr(), (int)dst.step, funCfg, buffer); + return status >= 0; +} + +static bool ipp_sqrDistance(const Mat& src, const Mat& tpl, Mat& dst) +{ + CV_INSTRUMENT_REGION_IPP() + + IppStatus status; + + IppiSize srcRoiSize = {src.cols,src.rows}; + IppiSize tplRoiSize = {tpl.cols,tpl.rows}; + + IppAutoBuffer buffer; + int bufSize=0; + + int depth = src.depth(); + + ippimatchTemplate ippiSqrDistanceNorm = + depth==CV_8U ? (ippimatchTemplate)ippiSqrDistanceNorm_8u32f_C1R: + depth==CV_32F? (ippimatchTemplate)ippiSqrDistanceNorm_32f_C1R: 0; + + if (ippiSqrDistanceNorm==0) + return false; + + IppEnum funCfg = (IppEnum)(ippAlgAuto | ippiROIValid | ippiNormNone); + status = ippiSqrDistanceNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize); + if ( status < 0 ) + return false; + + buffer.allocate( bufSize ); + + status = CV_INSTRUMENT_FUN_IPP(ippiSqrDistanceNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr(), (int)dst.step, funCfg, buffer); + return status >= 0; +} + +static bool ipp_matchTemplate( Mat& img, Mat& templ, Mat& result, int method) +{ + CV_INSTRUMENT_REGION_IPP() + + if(img.channels() != 1) + return false; + + // These functions are not efficient if template size is comparable with image size + if(templ.size().area()*4 > img.size().area()) + return false; + + if(method == CV_TM_SQDIFF) { - if(method == CV_TM_SQDIFF) + if(ipp_sqrDistance(img, templ, result)) + return true; + } + else if(method == CV_TM_SQDIFF_NORMED) + { + if(ipp_crossCorr(img, templ, result, false)) { - if (ipp_sqrDistance(img, templ, result)) - return true; + common_matchTemplate(img, templ, result, CV_TM_SQDIFF_NORMED, 1); + return true; } - else + } + else if(method == CV_TM_CCORR) + { + if(ipp_crossCorr(img, templ, result, false)) + return true; + } + else if(method == CV_TM_CCORR_NORMED) + { + if(ipp_crossCorr(img, templ, result, true)) + return true; + } + else if(method == CV_TM_CCOEFF || method == CV_TM_CCOEFF_NORMED) + { + if(ipp_crossCorr(img, templ, result, false)) { - if(ipp_crossCorr(img, templ, result)) - { - common_matchTemplate(img, templ, result, method, cn); - return true; - } + common_matchTemplate(img, templ, result, method, 1); + return true; } } @@ -1109,7 +1120,7 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, return; #endif - CV_IPP_RUN(true, ipp_matchTemplate(img, templ, result, method, cn)) + CV_IPP_RUN_FAST(ipp_matchTemplate(img, templ, result, method)) crossCorr( img, templ, result, result.size(), result.type(), Point(0,0), 0, 0); diff --git a/modules/imgproc/test/test_filter.cpp b/modules/imgproc/test/test_filter.cpp index 886c5ab90a..6452aec232 100644 --- a/modules/imgproc/test/test_filter.cpp +++ b/modules/imgproc/test/test_filter.cpp @@ -715,7 +715,7 @@ void CV_SmoothBaseTest::get_test_array_types_and_sizes( int test_case_idx, double CV_SmoothBaseTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ ) { int depth = test_mat[INPUT][0].depth(); - return depth <= CV_8S ? 1 : 1e-5; + return depth < CV_32F ? 1 : 1e-5; }