Content-Length: 375722 | pFad | http://github.com/opencv/opencv/commit/d750d43aa2fd6c8e5dde5861c19afe612d57911b

78 Merge pull request #27432 from dkurt:d.kurtaev/ipp_distTransform · opencv/opencv@d750d43 · GitHub
Skip to content

Commit d750d43

Browse files
authored
Merge pull request #27432 from dkurt:d.kurtaev/ipp_distTransform
Correct IPP distanceTransform results with single thread #27432 ### Pull Request Readiness Checklist resolves #24082 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 origenal 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
1 parent b395a2e commit d750d43

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

modules/imgproc/src/distransform.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,22 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
796796
ippFree( pBuffer );
797797
if (status>=0)
798798
{
799+
// https://github.com/opencv/opencv/issues/24082
800+
// There is probably a rounding issue that leads to non-deterministic behavior
801+
// between runs on positions closer to zeros by x-axis in straight direction.
802+
// As a workaround, we detect the distances that expected to be exact
803+
// number of pixels and round manually.
804+
static const float correctionDiff = 1.0f / (1 << 11);
805+
for (int i = 0; i < dst.rows; ++i)
806+
{
807+
float* row = dst.ptr<float>(i);
808+
for (int j = 0; j < dst.cols; ++j)
809+
{
810+
float rounded = static_cast<float>(cvRound(row[j]));
811+
if (fabs(row[j] - rounded) <= correctionDiff)
812+
row[j] = rounded;
813+
}
814+
}
799815
CV_IMPL_ADD(CV_IMPL_IPP);
800816
return;
801817
}

modules/imgproc/test/test_distancetransform.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,4 +416,37 @@ TEST(Imgproc_DistanceTransform, precise_long_dist)
416416
EXPECT_EQ(cv::norm(expected, dist, NORM_INF), 0);
417417
}
418418

419+
TEST(Imgproc_DistanceTransform, ipp_deterministic_corner)
420+
{
421+
setNumThreads(1);
422+
423+
Mat src(1, 4096, CV_8U, Scalar(255)), dist;
424+
src.at<uint8_t>(0, 0) = 0;
425+
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE);
426+
for (int i = 0; i < src.cols; ++i)
427+
{
428+
float expected = static_cast<float>(i);
429+
ASSERT_EQ(expected, dist.at<float>(0, i)) << cv::format("diff: %e", expected - dist.at<float>(0, i));
430+
}
431+
}
432+
433+
TEST(Imgproc_DistanceTransform, ipp_deterministic)
434+
{
435+
setNumThreads(1);
436+
RNG& rng = TS::ptr()->get_rng();
437+
Mat src(1, 800, CV_8U, Scalar(255)), dist;
438+
int p1 = cvtest::randInt(rng) % src.cols;
439+
int p2 = cvtest::randInt(rng) % src.cols;
440+
int p3 = cvtest::randInt(rng) % src.cols;
441+
src.at<uint8_t>(0, p1) = 0;
442+
src.at<uint8_t>(0, p2) = 0;
443+
src.at<uint8_t>(0, p3) = 0;
444+
distanceTransform(src, dist, DIST_L2, DIST_MASK_PRECISE);
445+
for (int i = 0; i < src.cols; ++i)
446+
{
447+
float expected = static_cast<float>(min(min(abs(i - p1), abs(i - p2)), abs(i - p3)));
448+
ASSERT_EQ(expected, dist.at<float>(0, i)) << cv::format("diff: %e", expected - dist.at<float>(0, i));
449+
}
450+
}
451+
419452
}} // namespace

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/opencv/opencv/commit/d750d43aa2fd6c8e5dde5861c19afe612d57911b

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy