Merge pull request #24535 from dkurt:ipp_distransform_update

Handle huge images in IPP distanceTransform #24535

### Pull Request Readiness Checklist

* Do not use IPP for huge Mat (reproduced with https://github.com/opencv/opencv/issues/23895#issuecomment-1708132367 on `DIST_MASK_5`)

  I have observed two types of errors on the reproducer from the issue:

  1. When `temp` is not allocated:

    ```
    Thread 1 "app" received signal SIGSEGV, Segmentation fault.
    0x00007ffff65dc755 in icv_l9_ownDistanceTransform_5x5_8u32f_C1R_21B_g9e9 () from /home/dkurtaev/opencv_install/bin/../lib/libopencv_imgproc.so.408
    (gdb) bt
    #0  0x00007ffff65dc755 in icv_l9_ownDistanceTransform_5x5_8u32f_C1R_21B_g9e9 () from /home/dkurtaev/opencv_install/bin/../lib/libopencv_imgproc.so.408
    #1  0x00007ffff659e8df in icv_l9_ippiDistanceTransform_5x5_8u32f_C1R () from /home/dkurtaev/opencv_install/bin/../lib/libopencv_imgproc.so.408
    #2  0x00007ffff5c390f0 in cv::distanceTransform (_src=..., _dst=..., _labels=..., distType=2, maskSize=5, labelType=1) at /home/dkurtaev/opencv/modules/imgproc/src/distransform.cpp:854
    #3  0x00007ffff5c396ef in cv::distanceTransform (_src=..., _dst=..., distanceType=2, maskSize=5, dstType=5) at /home/dkurtaev/opencv/modules/imgproc/src/distransform.cpp:903
    #4  0x000055555555669e in main (argc=1, argv=0x7fffffffdef8) at /home/dkurtaev/main.cpp:18
    ```

  2. When we keep `temp` allocated every time:

    ```
    OpenCV(4.8.0-dev) Error: Assertion failed (udata < (uchar*)ptr && ((uchar*)ptr - udata) <= (ptrdiff_t)(sizeof(void*)+64)) in fastFree, file /home/dkurtaev/opencv/modules/core/src/alloc.cpp, line 191
    terminate called after throwing an instance of 'cv::Exception'
      what():  OpenCV(4.8.0-dev) /home/dkurtaev/opencv/modules/core/src/alloc.cpp:191: error: (-215:Assertion failed) udata < (uchar*)ptr && ((uchar*)ptr - udata) <= (ptrdiff_t)(sizeof(void*)+64) in function 'fastFree'
    ```

* Try enable IPP for 3x3 (see https://github.com/opencv/opencv/issues/15904)
* Reduce memory footprint with IPP

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
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
pull/24549/head
Dmitry Kurtaev 1 year ago committed by GitHub
parent 4a69877eaa
commit ec97c38ff9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      modules/imgproc/src/distransform.cpp

@ -817,14 +817,15 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
Size size = src.size(); Size size = src.size();
int border = maskSize == CV_DIST_MASK_3 ? 1 : 2; int border = maskSize == CV_DIST_MASK_3 ? 1 : 2;
Mat temp( size.height + border*2, size.width + border*2, CV_32SC1 ); Mat temp;
if( !need_labels ) if( !need_labels )
{ {
if( maskSize == CV_DIST_MASK_3 ) if( maskSize == CV_DIST_MASK_3 )
{ {
#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) && 0 // disabled: https://github.com/opencv/opencv/issues/15904 #if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700)
CV_IPP_CHECK() bool has_int_overflow = (int64)src.cols * src.rows >= INT_MAX;
if (!has_int_overflow && CV_IPP_CHECK_COND)
{ {
IppiSize roi = { src.cols, src.rows }; IppiSize roi = { src.cols, src.rows };
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_3x3_8u32f_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, _mask) >= 0) if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_3x3_8u32f_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, _mask) >= 0)
@ -836,12 +837,14 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
} }
#endif #endif
temp.create(size.height + border*2, size.width + border*2, CV_32SC1);
distanceTransform_3x3(src, temp, dst, _mask); distanceTransform_3x3(src, temp, dst, _mask);
} }
else else
{ {
#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700) #if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700)
CV_IPP_CHECK() bool has_int_overflow = (int64)src.cols * src.rows >= INT_MAX;
if (!has_int_overflow && CV_IPP_CHECK_COND)
{ {
IppiSize roi = { src.cols, src.rows }; IppiSize roi = { src.cols, src.rows };
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_5x5_8u32f_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, _mask) >= 0) if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_5x5_8u32f_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, _mask) >= 0)
@ -853,6 +856,7 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
} }
#endif #endif
temp.create(size.height + border*2, size.width + border*2, CV_32SC1);
distanceTransform_5x5(src, temp, dst, _mask); distanceTransform_5x5(src, temp, dst, _mask);
} }
} }
@ -879,7 +883,8 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
} }
} }
distanceTransformEx_5x5( src, temp, dst, labels, _mask ); temp.create(size.height + border*2, size.width + border*2, CV_32SC1);
distanceTransformEx_5x5( src, temp, dst, labels, _mask );
} }
} }

Loading…
Cancel
Save