From c48dad1d9d92d1bd1b5ba12730feb4a637670371 Mon Sep 17 00:00:00 2001 From: eplankin Date: Fri, 4 Jul 2025 11:04:31 +0200 Subject: [PATCH] Merge pull request #27324 from eplankin:warp_hal_4x * Moved IPP impl of warpAffine to HAL Co-authored-by: victorget --- hal/ipp/CMakeLists.txt | 3 + hal/ipp/include/ipp_hal_imgproc.hpp | 27 ++ hal/ipp/src/precomp_ipp.hpp | 71 ++++ hal/ipp/src/transforms_ipp.cpp | 14 +- hal/ipp/src/warp_ipp.cpp | 367 ++++++++++++++++++ modules/core/include/opencv2/core/private.hpp | 2 - modules/imgproc/src/imgwarp.cpp | 363 +---------------- 7 files changed, 470 insertions(+), 377 deletions(-) create mode 100644 hal/ipp/include/ipp_hal_imgproc.hpp create mode 100644 hal/ipp/src/precomp_ipp.hpp create mode 100644 hal/ipp/src/warp_ipp.cpp diff --git a/hal/ipp/CMakeLists.txt b/hal/ipp/CMakeLists.txt index bf57db6f8e..203e38c6d6 100644 --- a/hal/ipp/CMakeLists.txt +++ b/hal/ipp/CMakeLists.txt @@ -5,6 +5,7 @@ set(IPP_HAL_LIBRARIES "ipphal" CACHE INTERNAL "") set(IPP_HAL_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include" CACHE INTERNAL "") set(IPP_HAL_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/ipp_hal_core.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/include/ipp_hal_imgproc.hpp" CACHE INTERNAL "") add_library(ipphal STATIC @@ -13,6 +14,7 @@ add_library(ipphal STATIC "${CMAKE_CURRENT_SOURCE_DIR}/src/norm_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/cart_polar_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/transforms_ipp.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/warp_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/sum_ipp.cpp" ) @@ -34,6 +36,7 @@ ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-suggest-override) target_include_directories(ipphal PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src" ${CMAKE_SOURCE_DIR}/modules/core/include + ${CMAKE_SOURCE_DIR}/modules/imgproc/include ${IPP_INCLUDE_DIRS} ) diff --git a/hal/ipp/include/ipp_hal_imgproc.hpp b/hal/ipp/include/ipp_hal_imgproc.hpp new file mode 100644 index 0000000000..bafbf3faaf --- /dev/null +++ b/hal/ipp/include/ipp_hal_imgproc.hpp @@ -0,0 +1,27 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#ifndef __IPP_HAL_IMGPROC_HPP__ +#define __IPP_HAL_IMGPROC_HPP__ + +#include +#include "ipp_utils.hpp" + +#ifdef HAVE_IPP_IW + +int ipp_hal_warpAffine(int src_type, 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, const double M[6], int interpolation, int borderType, const double borderValue[4]); + +#undef cv_hal_warpAffine +#define cv_hal_warpAffine ipp_hal_warpAffine +#endif + +#if IPP_VERSION_X100 >= 810 +int ipp_hal_warpPerspective(int src_type, 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, const double M[9], int interpolation, int borderType, const double borderValue[4]); +#undef cv_hal_warpPerspective +#define cv_hal_warpPerspective ipp_hal_warpPerspective +#endif + +#endif //__IPP_HAL_IMGPROC_HPP__ diff --git a/hal/ipp/src/precomp_ipp.hpp b/hal/ipp/src/precomp_ipp.hpp new file mode 100644 index 0000000000..b63e660a94 --- /dev/null +++ b/hal/ipp/src/precomp_ipp.hpp @@ -0,0 +1,71 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#ifndef __PRECOMP_IPP_HPP__ +#define __PRECOMP_IPP_HPP__ + +#include + +#ifdef HAVE_IPP_IW +#include "iw++/iw.hpp" +#endif + +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; +} + +static inline IppiInterpolationType ippiGetInterpolation(int inter) +{ + inter &= cv::InterpolationFlags::INTER_MAX; + return inter == cv::InterpolationFlags::INTER_NEAREST ? ippNearest : + inter == cv::InterpolationFlags::INTER_LINEAR ? ippLinear : + inter == cv::InterpolationFlags::INTER_CUBIC ? ippCubic : + inter == cv::InterpolationFlags::INTER_LANCZOS4 ? ippLanczos : + inter == cv::InterpolationFlags::INTER_AREA ? ippSuper : + (IppiInterpolationType)-1; +} + +static inline IppiBorderType ippiGetBorderType(int borderTypeNI) +{ + return borderTypeNI == cv::BorderTypes::BORDER_CONSTANT ? ippBorderConst : + borderTypeNI == cv::BorderTypes::BORDER_TRANSPARENT ? ippBorderTransp : + borderTypeNI == cv::BorderTypes::BORDER_REPLICATE ? ippBorderRepl : + (IppiBorderType)-1; +} + +static inline int ippiSuggestThreadsNum(size_t width, size_t height, size_t elemSize, double multiplier) +{ + int threads = cv::getNumThreads(); + if(threads > 1 && height >= 64) + { + size_t opMemory = (int)(width*height*elemSize*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; +} + +#ifdef HAVE_IPP_IW +static inline int ippiSuggestThreadsNum(const ::ipp::IwiImage &image, double multiplier) +{ + return ippiSuggestThreadsNum(image.m_size.width, image.m_size.height, image.m_typeSize*image.m_channels, multiplier); +} +#endif + +#endif //__PRECOMP_IPP_HPP__ diff --git a/hal/ipp/src/transforms_ipp.cpp b/hal/ipp/src/transforms_ipp.cpp index 83e66d52a5..0d2e05f291 100644 --- a/hal/ipp/src/transforms_ipp.cpp +++ b/hal/ipp/src/transforms_ipp.cpp @@ -3,6 +3,7 @@ // of this distribution and at http://opencv.org/license.html #include "ipp_hal_core.hpp" +#include "precomp_ipp.hpp" #include #include @@ -72,19 +73,6 @@ int ipp_hal_transpose2d(const uchar* src_data, size_t src_step, uchar* dst_data, #ifdef HAVE_IPP_IW -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; -} - static inline ::ipp::IwiImage ippiGetImage(int src_type, const uchar* src_data, size_t src_step, int src_width, int src_height) { ::ipp::IwiImage dst; diff --git a/hal/ipp/src/warp_ipp.cpp b/hal/ipp/src/warp_ipp.cpp new file mode 100644 index 0000000000..a41d51460a --- /dev/null +++ b/hal/ipp/src/warp_ipp.cpp @@ -0,0 +1,367 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html + +#include "ipp_hal_imgproc.hpp" + +#include +#include +#include "precomp_ipp.hpp" + +#ifdef HAVE_IPP_IW +#include "iw++/iw.hpp" +#endif + +#define IPP_WARPAFFINE_PARALLEL 1 +#define CV_TYPE(src_type) (src_type & (CV_DEPTH_MAX - 1)) +#ifdef HAVE_IPP_IW + +class ipp_warpAffineParallel: public cv::ParallelLoopBody +{ +public: + ipp_warpAffineParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, IppiInterpolationType _inter, double (&_coeffs)[2][3], ::ipp::IwiBorderType _borderType, IwTransDirection _iwTransDirection, bool *_ok):m_src(src), m_dst(dst) + { + pOk = _ok; + + inter = _inter; + borderType = _borderType; + iwTransDirection = _iwTransDirection; + + for( int i = 0; i < 2; i++ ) + for( int j = 0; j < 3; j++ ) + coeffs[i][j] = _coeffs[i][j]; + + *pOk = true; + } + ~ipp_warpAffineParallel() {} + + virtual void operator() (const cv::Range& range) const CV_OVERRIDE + { + //CV_INSTRUMENT_REGION_IPP(); + + if(*pOk == false) + return; + + try + { + ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, m_dst.m_size.width, range.end - range.start); + CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, m_src, m_dst, coeffs, iwTransDirection, inter, ::ipp::IwiWarpAffineParams(), borderType, tile); + } + catch(const ::ipp::IwException &) + { + *pOk = false; + return; + } + } +private: + ::ipp::IwiImage &m_src; + ::ipp::IwiImage &m_dst; + + IppiInterpolationType inter; + double coeffs[2][3]; + ::ipp::IwiBorderType borderType; + IwTransDirection iwTransDirection; + + bool *pOk; + const ipp_warpAffineParallel& operator= (const ipp_warpAffineParallel&); +}; + +#if (IPP_VERSION_X100 >= 700) +int ipp_hal_warpAffine(int src_type, 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, const double M[6], int interpolation, int borderType, const double borderValue[4]) +{ + //CV_INSTRUMENT_REGION_IPP(); + + IppiInterpolationType ippInter = ippiGetInterpolation(interpolation); + if((int)ippInter < 0 || interpolation > 2) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + /* C1 C2 C3 C4 */ + char impl[CV_DEPTH_MAX][4][3]={{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8U + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8S + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {1, 0, 0}}, //16U + {{1, 0, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 0}}, //16S + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //32S + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //32F + {{1, 0, 0}, {0, 0, 0}, {1, 0, 0}, {1, 0, 0}}}; //64F + + if(impl[CV_TYPE(src_type)][CV_MAT_CN(src_type)-1][interpolation] == 0) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + // Acquire data and begin processing + try + { + ::ipp::IwiImage iwSrc; + iwSrc.Init({src_width, src_height}, ippiGetDataType(src_type), CV_MAT_CN(src_type), NULL, src_data, IwSize(src_step)); + ::ipp::IwiImage iwDst({dst_width, dst_height}, ippiGetDataType(src_type), CV_MAT_CN(src_type), NULL, dst_data, dst_step); + ::ipp::IwiBorderType ippBorder(ippiGetBorderType(borderType), {borderValue[0], borderValue[1], borderValue[2], borderValue[3]}); + IwTransDirection iwTransDirection = iwTransForward; + + if((int)ippBorder == -1) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + double coeffs[2][3]; + for( int i = 0; i < 2; i++ ) + for( int j = 0; j < 3; j++ ) + coeffs[i][j] = M[i*3 + j]; + + const int threads = ippiSuggestThreadsNum(iwDst, 2); + + if(IPP_WARPAFFINE_PARALLEL && threads > 1) + { + bool ok = true; + cv::Range range(0, (int)iwDst.m_size.height); + ipp_warpAffineParallel invoker(iwSrc, iwDst, ippInter, coeffs, ippBorder, iwTransDirection, &ok); + if(!ok) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + parallel_for_(range, invoker, threads*4); + + if(!ok) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } else { + CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, iwSrc, iwDst, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpAffineParams(), ippBorder); + } + } + catch (const ::ipp::IwException &) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + return CV_HAL_ERROR_OK; +} +#endif + +typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize); + +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] = cv::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 ) + { + switch( depth ) + { + case CV_8U: + return CV_INSTRUMENT_FUN_IPP(ippiSet_8u_C1R, cv::saturate_cast(value[0]), (Ipp8u *)dataPointer, step, size) >= 0; + case CV_16U: + return CV_INSTRUMENT_FUN_IPP(ippiSet_16u_C1R, cv::saturate_cast(value[0]), (Ipp16u *)dataPointer, step, size) >= 0; + case CV_32F: + return CV_INSTRUMENT_FUN_IPP(ippiSet_32f_C1R, cv::saturate_cast(value[0]), (Ipp32f *)dataPointer, step, size) >= 0; + } + } + else + { + if( channels == 3 ) + { + 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); + } + } + } + return false; +} + +#if (IPP_VERSION_X100 >= 810) +typedef IppStatus (CV_STDCALL* ippiWarpPerspectiveFunc)(const Ipp8u*, int, Ipp8u*, int,IppiPoint, IppiSize, const IppiWarpSpec*,Ipp8u*); + +class IPPWarpPerspectiveInvoker : + public cv::ParallelLoopBody +{ +public: + IPPWarpPerspectiveInvoker(int _src_type, cv::Mat &_src, size_t _src_step, cv::Mat &_dst, size_t _dst_step, IppiInterpolationType _interpolation, + double (&_coeffs)[3][3], int &_borderType, const double _borderValue[4], ippiWarpPerspectiveFunc _func, + bool *_ok) : + ParallelLoopBody(), src_type(_src_type), src(_src), src_step(_src_step), dst(_dst), dst_step(_dst_step), inter(_interpolation), coeffs(_coeffs), + borderType(_borderType), func(_func), ok(_ok) + { + memcpy(this->borderValue, _borderValue, sizeof(this->borderValue)); + *ok = true; + } + + virtual void operator() (const cv::Range& range) const CV_OVERRIDE + { + //CV_INSTRUMENT_REGION_IPP(); + IppiWarpSpec* pSpec = 0; + int specSize = 0, initSize = 0, bufSize = 0; Ipp8u* pBuffer = 0; + IppiPoint dstRoiOffset = {0, 0}; + IppiWarpDirection direction = ippWarpBackward; //fixed for IPP + const Ipp32u numChannels = CV_MAT_CN(src_type); + + IppiSize srcsize = {src.cols, src.rows}; + IppiSize dstsize = {dst.cols, dst.rows}; + IppiRect srcroi = {0, 0, src.cols, src.rows}; + + /* Spec and init buffer sizes */ + IppStatus status = ippiWarpPerspectiveGetSize(srcsize, srcroi, dstsize, ippiGetDataType(src_type), coeffs, inter, ippWarpBackward, ippiGetBorderType(borderType), &specSize, &initSize); + + pSpec = (IppiWarpSpec*)ippMalloc_L(specSize); + + if (inter == ippLinear) + { + status = ippiWarpPerspectiveLinearInit(srcsize, srcroi, dstsize, ippiGetDataType(src_type), coeffs, direction, numChannels, ippiGetBorderType(borderType), + borderValue, 0, pSpec); + } else + { + status = ippiWarpPerspectiveNearestInit(srcsize, srcroi, dstsize, ippiGetDataType(src_type), coeffs, direction, numChannels, ippiGetBorderType(borderType), + borderValue, 0, pSpec); + } + + status = ippiWarpGetBufferSize(pSpec, dstsize, &bufSize); + pBuffer = (Ipp8u*)ippMalloc_L(bufSize); + IppiSize dstRoiSize = dstsize; + + int cnn = src.channels(); + + if( borderType == cv::BorderTypes::BORDER_CONSTANT ) + { + IppiSize setSize = {dst.cols, range.end - range.start}; + void *dataPointer = dst.ptr(range.start); + if( !IPPSet( cv::Scalar(borderValue[0], borderValue[1], borderValue[2], borderValue[3]), dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) ) + { + *ok = false; + return; + } + } + + status = CV_INSTRUMENT_FUN_IPP(func, src.ptr(), (int)src_step, dst.ptr(), (int)dst_step, dstRoiOffset, dstRoiSize, pSpec, pBuffer); + if (status != ippStsNoErr) + *ok = false; + else + { + CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); + } + } +private: + int src_type; + cv::Mat &src; + size_t src_step; + cv::Mat &dst; + size_t dst_step; + IppiInterpolationType inter; + double (&coeffs)[3][3]; + int borderType; + double borderValue[4]; + ippiWarpPerspectiveFunc func; + bool *ok; + + const IPPWarpPerspectiveInvoker& operator= (const IPPWarpPerspectiveInvoker&); +}; + +int ipp_hal_warpPerspective(int src_type, 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, const double M[9], int interpolation, int borderType, const double borderValue[4]) +{ + //CV_INSTRUMENT_REGION_IPP(); + ippiWarpPerspectiveFunc ippFunc = 0; + if (interpolation == cv::InterpolationFlags::INTER_NEAREST) + { + ippFunc = src_type == CV_8UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_8u_C1R : + src_type == CV_8UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_8u_C3R : + src_type == CV_8UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_8u_C4R : + src_type == CV_16UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16u_C1R : + src_type == CV_16UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16u_C3R : + src_type == CV_16UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16u_C4R : + src_type == CV_16SC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16s_C1R : + src_type == CV_16SC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16s_C3R : + src_type == CV_16SC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_16s_C4R : + src_type == CV_32FC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_32f_C1R : + src_type == CV_32FC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_32f_C3R : + src_type == CV_32FC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveNearest_32f_C4R : 0; + } + else if (interpolation == cv::InterpolationFlags::INTER_LINEAR) + { + ippFunc = src_type == CV_8UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_8u_C1R : + src_type == CV_8UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_8u_C3R : + src_type == CV_8UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_8u_C4R : + src_type == CV_16UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16u_C1R : + src_type == CV_16UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16u_C3R : + src_type == CV_16UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16u_C4R : + src_type == CV_16SC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16s_C1R : + src_type == CV_16SC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16s_C3R : + src_type == CV_16SC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_16s_C4R : + src_type == CV_32FC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_32f_C1R : + src_type == CV_32FC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_32f_C3R : + src_type == CV_32FC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveLinear_32f_C4R : 0; + } + else + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + if(src_height == 1 || src_width == 1) return CV_HAL_ERROR_NOT_IMPLEMENTED; + + int mode = + interpolation == cv::InterpolationFlags::INTER_NEAREST ? IPPI_INTER_NN : + interpolation == cv::InterpolationFlags::INTER_LINEAR ? IPPI_INTER_LINEAR : 0; + + if (mode == 0 || ippFunc == 0) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + /* C1 C2 C3 C4 */ + char impl[CV_DEPTH_MAX][4][2]={{{0, 0}, {1, 1}, {0, 0}, {0, 0}}, //8U + {{1, 1}, {1, 1}, {1, 1}, {1, 1}}, //8S + {{0, 0}, {1, 1}, {0, 1}, {0, 1}}, //16U + {{1, 1}, {1, 1}, {1, 1}, {1, 1}}, //16S + {{1, 1}, {1, 1}, {1, 0}, {1, 1}}, //32S + {{1, 0}, {1, 0}, {0, 0}, {1, 0}}, //32F + {{1, 1}, {1, 1}, {1, 1}, {1, 1}}}; //64F + + if(impl[CV_TYPE(src_type)][CV_MAT_CN(src_type)-1][interpolation] == 0) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + double coeffs[3][3]; + for( int i = 0; i < 3; i++ ) + for( int j = 0; j < 3; j++ ) + coeffs[i][j] = M[i*3 + j]; + + bool ok; + cv::Range range(0, dst_height); + cv::Mat src(cv::Size(src_width, src_height), src_type, const_cast(src_data), src_step); + cv::Mat dst(cv::Size(dst_width, dst_height), src_type, dst_data, dst_step); + IppiInterpolationType ippInter = ippiGetInterpolation(interpolation); + IPPWarpPerspectiveInvoker invoker(src_type, src, src_step, dst, dst_step, ippInter, coeffs, borderType, borderValue, ippFunc, &ok); + parallel_for_(range, invoker, dst.total()/(double)(1<<16)); + + if( ok ) + { + CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); + } + return CV_HAL_ERROR_OK; +} +#endif +#endif diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index 4f23abf6de..d6f4425be2 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -197,8 +197,6 @@ T* allocSingletonNew() { return new(allocSingletonNewBuffer(sizeof(T))) T(); } #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_YUV_RGB 1 // accuracy difference #define IPP_DISABLE_RGB_YUV 1 // breaks OCL accuracy tests diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index f348860549..4690265420 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -60,7 +60,7 @@ using namespace cv; namespace cv { -#if defined (HAVE_IPP) && (!IPP_DISABLE_WARPAFFINE || !IPP_DISABLE_WARPPERSPECTIVE || !IPP_DISABLE_REMAP) +#if defined (HAVE_IPP) && (!IPP_DISABLE_REMAP) typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize); template @@ -2207,62 +2207,6 @@ private: const double *M; }; - -#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 -{ -public: - IPPWarpAffineInvoker(Mat &_src, Mat &_dst, double (&_coeffs)[2][3], int &_interpolation, int _borderType, - const Scalar &_borderValue, ippiWarpAffineBackFunc _func, bool *_ok) : - ParallelLoopBody(), src(_src), dst(_dst), mode(_interpolation), coeffs(_coeffs), - borderType(_borderType), borderValue(_borderValue), func(_func), ok(_ok) - { - *ok = true; - } - - virtual void operator() (const Range& range) const CV_OVERRIDE - { - IppiSize srcsize = { src.cols, src.rows }; - IppiRect srcroi = { 0, 0, src.cols, src.rows }; - IppiRect dstroi = { 0, range.start, dst.cols, range.end - range.start }; - int cnn = src.channels(); - if( borderType == BORDER_CONSTANT ) - { - IppiSize setSize = { dst.cols, range.end - range.start }; - void *dataPointer = dst.ptr(range.start); - if( !IPPSet( borderValue, dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) ) - { - *ok = false; - return; - } - } - - // Aug 2013: problem in IPP 7.1, 8.0 : sometimes function return ippStsCoeffErr - 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; - else - { - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); - } - } -private: - Mat &src; - Mat &dst; - int mode; - double (&coeffs)[2][3]; - int borderType; - Scalar borderValue; - ippiWarpAffineBackFunc func; - bool *ok; - const IPPWarpAffineInvoker& operator= (const IPPWarpAffineInvoker&); -}; -#endif - #ifdef HAVE_OPENCL enum { OCL_OP_PERSPECTIVE = 1, OCL_OP_AFFINE = 0 }; @@ -2452,132 +2396,6 @@ static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0, #endif -#ifdef HAVE_IPP -#define IPP_WARPAFFINE_PARALLEL 1 - -#ifdef HAVE_IPP_IW - -class ipp_warpAffineParallel: public ParallelLoopBody -{ -public: - ipp_warpAffineParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, IppiInterpolationType _inter, double (&_coeffs)[2][3], ::ipp::IwiBorderType _borderType, IwTransDirection _iwTransDirection, bool *_ok):m_src(src), m_dst(dst) - { - pOk = _ok; - - inter = _inter; - borderType = _borderType; - iwTransDirection = _iwTransDirection; - - for( int i = 0; i < 2; i++ ) - for( int j = 0; j < 3; j++ ) - coeffs[i][j] = _coeffs[i][j]; - - *pOk = true; - } - ~ipp_warpAffineParallel() {} - - virtual void operator() (const Range& range) const CV_OVERRIDE - { - CV_INSTRUMENT_REGION_IPP(); - - if(*pOk == false) - return; - - try - { - ::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, m_dst.m_size.width, range.end - range.start); - CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, m_src, m_dst, coeffs, iwTransDirection, inter, ::ipp::IwiWarpAffineParams(), borderType, tile); - } - catch(const ::ipp::IwException &) - { - *pOk = false; - return; - } - } -private: - ::ipp::IwiImage &m_src; - ::ipp::IwiImage &m_dst; - - IppiInterpolationType inter; - double coeffs[2][3]; - ::ipp::IwiBorderType borderType; - IwTransDirection iwTransDirection; - - bool *pOk; - const ipp_warpAffineParallel& operator= (const ipp_warpAffineParallel&); -}; - -#endif - -static bool ipp_warpAffine( InputArray _src, OutputArray _dst, int interpolation, int borderType, const Scalar & borderValue, InputArray _M, int flags ) -{ -#ifdef HAVE_IPP_IW - CV_INSTRUMENT_REGION_IPP(); - - if (!cv::ipp::useIPP_NotExact()) - return false; - - IppiInterpolationType ippInter = ippiGetInterpolation(interpolation); - if((int)ippInter < 0) - return false; - - // Acquire data and begin processing - try - { - Mat src = _src.getMat(); - Mat dst = _dst.getMat(); - ::ipp::IwiImage iwSrc = ippiGetImage(src); - ::ipp::IwiImage iwDst = ippiGetImage(dst); - ::ipp::IwiBorderType ippBorder(ippiGetBorderType(borderType), ippiGetValue(borderValue)); - IwTransDirection iwTransDirection; - if(!ippBorder) - return false; - - if( !(flags & WARP_INVERSE_MAP) ) - iwTransDirection = iwTransForward; - else - iwTransDirection = iwTransInverse; - - Mat M = _M.getMat(); - double coeffs[2][3]; - for( int i = 0; i < 2; i++ ) - for( int j = 0; j < 3; j++ ) - coeffs[i][j] = M.at(i, j); - - const int threads = ippiSuggestThreadsNum(iwDst, 2); - - if(IPP_WARPAFFINE_PARALLEL && threads > 1) - { - bool ok = true; - Range range(0, (int)iwDst.m_size.height); - ipp_warpAffineParallel invoker(iwSrc, iwDst, ippInter, coeffs, ippBorder, iwTransDirection, &ok); - if(!ok) - return false; - - parallel_for_(range, invoker, threads*4); - - if(!ok) - return false; - } else { - CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, iwSrc, iwDst, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpAffineParams(), ippBorder); - } - - } - catch (const ::ipp::IwException &) - { - return false; - } - - return true; -#else - CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(interpolation); - CV_UNUSED(borderType); CV_UNUSED(borderValue); CV_UNUSED(_M); CV_UNUSED(flags); - return false; -#endif -} - -#endif - namespace hal { void warpAffine(int src_type, @@ -2729,8 +2547,6 @@ void cv::warpAffine( InputArray _src, OutputArray _dst, CV_Assert( (M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 2 && M0.cols == 3 ); M0.convertTo(matM, matM.type()); - CV_IPP_RUN_FAST(ipp_warpAffine(src, dst, interpolation, borderType, borderValue, matM, flags)); - if( !(flags & WARP_INVERSE_MAP) ) { double D = M[0]*M[4] - M[1]*M[3]; @@ -2743,70 +2559,6 @@ void cv::warpAffine( InputArray _src, OutputArray _dst, M[2] = b1; M[5] = b2; } -#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); - if( ( depth == CV_8U || depth == CV_16U || depth == CV_32F ) && - ( cn == 1 || cn == 3 || cn == 4 ) && - ( interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC) && - ( borderType == cv::BORDER_TRANSPARENT || borderType == cv::BORDER_CONSTANT) ) - { - ippiWarpAffineBackFunc ippFunc = 0; - if ((flags & WARP_INVERSE_MAP) != 0) - { - ippFunc = - type == CV_8UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C1R : - type == CV_8UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C3R : - type == CV_8UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C4R : - type == CV_16UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C1R : - type == CV_16UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C3R : - type == CV_16UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C4R : - type == CV_32FC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C1R : - type == CV_32FC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C3R : - type == CV_32FC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C4R : - 0; - } - else - { - ippFunc = - type == CV_8UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffine_8u_C1R : - type == CV_8UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffine_8u_C3R : - type == CV_8UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffine_8u_C4R : - type == CV_16UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffine_16u_C1R : - type == CV_16UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffine_16u_C3R : - type == CV_16UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffine_16u_C4R : - type == CV_32FC1 ? (ippiWarpAffineBackFunc)ippiWarpAffine_32f_C1R : - type == CV_32FC3 ? (ippiWarpAffineBackFunc)ippiWarpAffine_32f_C3R : - type == CV_32FC4 ? (ippiWarpAffineBackFunc)ippiWarpAffine_32f_C4R : - 0; - } - int mode = - interpolation == INTER_LINEAR ? IPPI_INTER_LINEAR : - interpolation == INTER_NEAREST ? IPPI_INTER_NN : - interpolation == INTER_CUBIC ? IPPI_INTER_CUBIC : - 0; - CV_Assert(mode && ippFunc); - - double coeffs[2][3]; - for( int i = 0; i < 2; i++ ) - for( int j = 0; j < 3; j++ ) - coeffs[i][j] = matM.at(i, j); - - bool ok; - Range range(0, dst.rows); - IPPWarpAffineInvoker invoker(src, dst, coeffs, mode, borderType, borderValue, ippFunc, &ok); - parallel_for_(range, invoker, dst.total()/(double)(1<<16)); - if( ok ) - { - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); - return; - } - setIppErrorStatus(); - } - } -#endif - hal::warpAffine(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows, M, interpolation, borderType, borderValue.val); } @@ -3135,60 +2887,6 @@ private: Scalar borderValue; }; -#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 -{ -public: - IPPWarpPerspectiveInvoker(Mat &_src, Mat &_dst, double (&_coeffs)[3][3], int &_interpolation, - int &_borderType, const Scalar &_borderValue, ippiWarpPerspectiveFunc _func, bool *_ok) : - ParallelLoopBody(), src(_src), dst(_dst), mode(_interpolation), coeffs(_coeffs), - borderType(_borderType), borderValue(_borderValue), func(_func), ok(_ok) - { - *ok = true; - } - - virtual void operator() (const Range& range) const CV_OVERRIDE - { - IppiSize srcsize = {src.cols, src.rows}; - IppiRect srcroi = {0, 0, src.cols, src.rows}; - IppiRect dstroi = {0, range.start, dst.cols, range.end - range.start}; - int cnn = src.channels(); - - if( borderType == BORDER_CONSTANT ) - { - IppiSize setSize = {dst.cols, range.end - range.start}; - void *dataPointer = dst.ptr(range.start); - if( !IPPSet( borderValue, dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) ) - { - *ok = false; - return; - } - } - - 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 - { - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); - } - } -private: - Mat &src; - Mat &dst; - int mode; - double (&coeffs)[3][3]; - int borderType; - const Scalar borderValue; - ippiWarpPerspectiveFunc func; - bool *ok; - - const IPPWarpPerspectiveInvoker& operator= (const IPPWarpPerspectiveInvoker&); -}; -#endif namespace hal { @@ -3309,65 +3007,6 @@ 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_WARPPERSPECTIVE - CV_IPP_CHECK() - { - int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - if( (depth == CV_8U || depth == CV_16U || depth == CV_32F) && - (cn == 1 || cn == 3 || cn == 4) && - ( borderType == cv::BORDER_TRANSPARENT || borderType == cv::BORDER_CONSTANT ) && - (interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC)) - { - ippiWarpPerspectiveFunc ippFunc = 0; - if ((flags & WARP_INVERSE_MAP) != 0) - { - ippFunc = type == CV_8UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_8u_C1R : - type == CV_8UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_8u_C3R : - type == CV_8UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_8u_C4R : - type == CV_16UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_16u_C1R : - type == CV_16UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_16u_C3R : - type == CV_16UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_16u_C4R : - type == CV_32FC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_32f_C1R : - type == CV_32FC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_32f_C3R : - type == CV_32FC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_32f_C4R : 0; - } - else - { - ippFunc = type == CV_8UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_8u_C1R : - type == CV_8UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_8u_C3R : - type == CV_8UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_8u_C4R : - type == CV_16UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_16u_C1R : - type == CV_16UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_16u_C3R : - type == CV_16UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_16u_C4R : - type == CV_32FC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_32f_C1R : - type == CV_32FC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_32f_C3R : - type == CV_32FC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_32f_C4R : 0; - } - int mode = - interpolation == INTER_NEAREST ? IPPI_INTER_NN : - interpolation == INTER_LINEAR ? IPPI_INTER_LINEAR : - interpolation == INTER_CUBIC ? IPPI_INTER_CUBIC : 0; - CV_Assert(mode && ippFunc); - - double coeffs[3][3]; - for( int i = 0; i < 3; i++ ) - for( int j = 0; j < 3; j++ ) - coeffs[i][j] = matM.at(i, j); - - bool ok; - Range range(0, dst.rows); - IPPWarpPerspectiveInvoker invoker(src, dst, coeffs, mode, borderType, borderValue, ippFunc, &ok); - parallel_for_(range, invoker, dst.total()/(double)(1<<16)); - if( ok ) - { - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); - return; - } - setIppErrorStatus(); - } - } -#endif - if( !(flags & WARP_INVERSE_MAP) ) invert(matM, matM);