mirror of
https://github.com/opencv/opencv.git
synced 2026-09-12 13:23:03 -05:00
Merge pull request #29771 from intel-staging:warp_reenable_5
Enabled WarpAffine and WarpPerspective for IPP HAL - #29771 PR enables Warp* functions that were switched off before. The thing is that I added clear 1 for places that agrees with OpenCV due to the changes in OpenCV. Also restrict the transparent border since OpenCV and IPP differently process transparent border with a workaround for current ICV package since it fails on Windows as it was mentioned in https://github.com/opencv/opencv/pull/29669#issuecomment-5339331722. Locally the `Imgproc_WarpPerspective_Test.accuracy` test passed with ICV that is automatically downloaded by CMake. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -20,10 +20,8 @@
|
||||
#if defined(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]);
|
||||
|
||||
// Does not pass tests in 5.x branch
|
||||
//#undef cv_hal_warpAffine
|
||||
//#define cv_hal_warpAffine ipp_hal_warpAffine
|
||||
#undef cv_hal_warpAffine
|
||||
#define cv_hal_warpAffine ipp_hal_warpAffine
|
||||
|
||||
int ipp_hal_sobel(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
|
||||
int width, int height, int src_depth, int dst_depth, int cn,
|
||||
@@ -45,10 +43,8 @@ int ipp_hal_scharr(const uchar* src_data, size_t src_step, uchar* dst_data, size
|
||||
|
||||
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]);
|
||||
|
||||
// Does not pass tests in 5.x branch
|
||||
//#undef cv_hal_warpPerspective
|
||||
//#define cv_hal_warpPerspective ipp_hal_warpPerspective
|
||||
#undef cv_hal_warpPerspective
|
||||
#define cv_hal_warpPerspective ipp_hal_warpPerspective
|
||||
|
||||
#endif // IPP_VERSION_X100 >= 202600
|
||||
|
||||
|
||||
@@ -89,6 +89,12 @@ int ipp_hal_warpAffine(int src_type, const uchar *src_data, size_t src_step, int
|
||||
if((int)ippInter < 0 || interpolation > 2)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
#if !defined(IPP_CALLS_ENFORCED)
|
||||
// ippBorderTransp does not reproduce cv::BORDER_TRANSPARENT for warping
|
||||
if (borderType == cv::BORDER_TRANSPARENT)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
|
||||
#if defined(IPP_CALLS_ENFORCED)
|
||||
/* C1 C2 C3 C4 */
|
||||
char impl[CV_DEPTH_MAX][4][3]={{{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //8U
|
||||
@@ -99,14 +105,22 @@ int ipp_hal_warpAffine(int src_type, const uchar *src_data, size_t src_step, int
|
||||
{{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //32F
|
||||
{{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}}; //64F
|
||||
#else // IPP_CALLS_ENFORCED is not defined, results are strictly aligned to OpenCV implementation
|
||||
// Zeroed entries diverge:
|
||||
// 16S, 64F - LINEAR differs on 94-99% of pixels (maxdiff 77..106) and NEAREST
|
||||
// differs on ~0.1% of pixels (maxdiff ~3900): IPP has no 16S/64F
|
||||
// warp of its own, so IW falls back to a different code path.
|
||||
// C2 - not implemented by IPP IW yet.
|
||||
// 8S, 32S - not supported by cv::warpAffine itself.
|
||||
// CUBIC - never reaches the HAL: genericWarp() in imgwarp.cpp handles
|
||||
// INTER_CUBIC before hal::warpAffine() is called.
|
||||
/* C1 C2 C3 C4 */
|
||||
char impl[CV_DEPTH_MAX][4][3]={{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8U
|
||||
char impl[CV_DEPTH_MAX][4][3]={{{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 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
|
||||
{{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //16U
|
||||
{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 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
|
||||
{{1, 1, 0}, {0, 0, 0}, {1, 1, 0}, {1, 1, 0}}, //32F
|
||||
{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}}; //64F
|
||||
#endif
|
||||
|
||||
if(impl[CV_TYPE(src_type)][CV_MAT_CN(src_type)-1][interpolation] == 0)
|
||||
@@ -210,6 +224,13 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#if !defined(IPP_CALLS_ENFORCED)
|
||||
if (borderType == cv::BORDER_TRANSPARENT)
|
||||
{
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unsupported source type
|
||||
if (src_type != CV_8UC1 && src_type != CV_8UC3 && src_type != CV_8UC4 &&
|
||||
src_type != CV_16UC1 && src_type != CV_16UC3 && src_type != CV_16UC4 &&
|
||||
@@ -229,13 +250,20 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step
|
||||
{{1, 1}, {0, 0}, {1, 1}, {1, 1}}, //32F
|
||||
{{0, 0}, {0, 0}, {0, 0}, {0, 0}}}; //64F
|
||||
#else // IPP_CALLS_ENFORCED is not defined, results are strictly aligned to OpenCV implementation
|
||||
// Zeroed entries diverge:
|
||||
// NEAREST for 8U/16U/32F - differs on a handful of pixels (1 per channel) where
|
||||
// the sample coordinate lands exactly on a .5 boundary and IPP rounds
|
||||
// the opposite way from cvRound(); maxdiff is a full pixel value.
|
||||
// LINEAR for 16S - differs on 90-97% of pixels (maxdiff 92..100).
|
||||
// C2 - not implemented by IPP IW, always declines.
|
||||
// 8S, 32S, 64F - unsupported: rejected by the src_type check above.
|
||||
/* C1 C2 C3 C4 */
|
||||
char impl[CV_DEPTH_MAX][4][2]={{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, //8U
|
||||
char impl[CV_DEPTH_MAX][4][2]={{{0, 1}, {0, 0}, {0, 1}, {0, 1}}, //8U
|
||||
{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, //8S
|
||||
{{0, 0}, {0, 0}, {0, 0}, {0, 1}}, //16U
|
||||
{{1, 1}, {0, 0}, {1, 0}, {1, 1}}, //16S
|
||||
{{1, 1}, {0, 0}, {1, 0}, {1, 1}}, //32S
|
||||
{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, //32F
|
||||
{{0, 1}, {0, 0}, {0, 1}, {0, 1}}, //16U
|
||||
{{1, 0}, {0, 0}, {1, 0}, {1, 0}}, //16S
|
||||
{{0, 0}, {0, 0}, {0, 0}, {0, 0}}, //32S
|
||||
{{0, 1}, {0, 0}, {0, 1}, {0, 1}}, //32F
|
||||
{{0, 0}, {0, 0}, {0, 0}, {0, 0}}}; //64F
|
||||
#endif
|
||||
|
||||
@@ -259,6 +287,9 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step
|
||||
::ipp::IwiImage iwDst(IwiSize{dst_width, dst_height}, ippiGetDataType(src_type), CV_MAT_CN(src_type), IwiBorderSize(), dst_data, IwSize(dst_step));
|
||||
::ipp::IwiBorderType ippBorder(ippiGetBorderType(borderType), {borderValue, 4});
|
||||
IwTransDirection iwTransDirection = iwTransInverse; //fixed for IPP
|
||||
// This is the workaround for the ICV issue
|
||||
// TODO: remove the workaround when the issue is gone
|
||||
const IppiRect localRectInfinite = {IPP_MIN_32S / 2, IPP_MIN_32S / 2, IPP_MAX_32S, IPP_MAX_32S};
|
||||
if ((int)ippBorder == -1)
|
||||
{
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
@@ -268,7 +299,7 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step
|
||||
// The function is exception safe and sets the 'ok' flag to false if any exception occurs during processing.
|
||||
// The 'ok' flag is checked before and after parallel processing to determine
|
||||
// if the operation was successful or if it should fall back to a non-IPP implementation.
|
||||
auto IPPWarpPerspectiveInvokerLambda = [&iwSrc, &iwDst, dst_width, ippInter, &coeffs, ippBorder, iwTransDirection, &ok](const cv::Range& range)
|
||||
auto IPPWarpPerspectiveInvokerLambda = [&iwSrc, &iwDst, dst_width, ippInter, &coeffs, ippBorder, iwTransDirection, localRectInfinite, &ok](const cv::Range& range)
|
||||
{
|
||||
//CV_INSTRUMENT_REGION_IPP();
|
||||
if (!ok.load(std::memory_order_relaxed))
|
||||
@@ -279,7 +310,7 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step
|
||||
try
|
||||
{
|
||||
::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, dst_width, range.end - range.start);
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpPerspective, iwSrc, iwDst, ippRectInfinite, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpPerspectiveParams(), ippBorder, tile);
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpPerspective, iwSrc, iwDst, localRectInfinite, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpPerspectiveParams(), ippBorder, tile);
|
||||
}
|
||||
catch (const ::ipp::IwException &)
|
||||
{
|
||||
@@ -299,7 +330,7 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpPerspective, iwSrc, iwDst, ippRectInfinite, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpPerspectiveParams(), ippBorder);
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpPerspective, iwSrc, iwDst, localRectInfinite, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpPerspectiveParams(), ippBorder);
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
|
||||
Reference in New Issue
Block a user