mirror of
https://github.com/opencv/opencv.git
synced 2026-07-28 23:03:03 +04:00
imgproc: accept CV_Bool masks in distanceTransform
cv::Mat_<bool>::depth() returns CV_Bool in 5.0 where it returned CV_8U in 4.x, so distanceTransform started rejecting boolean masks. CV_Bool is a 1-byte type whose values are only zero-tested here, so accept it wherever a CV_8UC1 mask was previously accepted, matching the 4.x behaviour and the 4->5 migration guide. Relaxes the type checks on all four reachable paths: the public wrapper, distanceTransform_L1_8U, trueDistTrans (DIST_MASK_PRECISE) and distanceATS_L1_8u (CV_8U output). Closes #29596
This commit is contained in:
@@ -830,7 +830,7 @@ trueDistTrans( const Mat& src, Mat& dst )
|
||||
|
||||
CV_Assert( src.size() == dst.size() );
|
||||
|
||||
CV_Assert( src.type() == CV_8UC1 && dst.type() == CV_32FC1 );
|
||||
CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_BoolC1) && dst.type() == CV_32FC1 );
|
||||
int i, m = src.rows, n = src.cols;
|
||||
|
||||
cv::AutoBuffer<uchar> _buf(std::max(m*2*sizeof(int) + (m*3+1)*sizeof(int), n*2*sizeof(float)));
|
||||
@@ -886,7 +886,7 @@ distanceATS_L1_8u( const Mat& src, Mat& dst )
|
||||
int srcstep = (int)src.step;
|
||||
int dststep = (int)dst.step;
|
||||
|
||||
CV_Assert( src.type() == CV_8UC1 && dst.type() == CV_8UC1 );
|
||||
CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_BoolC1) && dst.type() == CV_8UC1 );
|
||||
CV_Assert( src.size() == dst.size() );
|
||||
|
||||
////////////////////// forward scan ////////////////////////
|
||||
@@ -957,7 +957,9 @@ static void distanceTransform_L1_8U(InputArray _src, OutputArray _dst)
|
||||
|
||||
Mat src = _src.getMat();
|
||||
|
||||
CV_Assert( src.type() == CV_8UC1);
|
||||
// CV_Bool is a 1-byte mask type (added in 5.0) and is only ever zero-tested
|
||||
// here, so accept it wherever a CV_8UC1 mask was accepted. See #29596.
|
||||
CV_Assert( src.type() == CV_8UC1 || src.type() == CV_BoolC1);
|
||||
|
||||
_dst.create( src.size(), CV_8UC1);
|
||||
Mat dst = _dst.getMat();
|
||||
@@ -978,7 +980,9 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
|
||||
Mat src = _src.getMat(), labels;
|
||||
bool need_labels = _labels.needed();
|
||||
|
||||
CV_Assert( src.type() == CV_8UC1);
|
||||
// CV_Bool is a 1-byte mask type (added in 5.0) and is only ever zero-tested
|
||||
// here, so accept it wherever a CV_8UC1 mask was accepted. See #29596.
|
||||
CV_Assert( src.type() == CV_8UC1 || src.type() == CV_BoolC1);
|
||||
|
||||
_dst.create( src.size(), CV_32F);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
@@ -209,4 +209,49 @@ TEST(Imgproc_DistanceTransform, ipp_deterministic)
|
||||
}
|
||||
}
|
||||
|
||||
// See https://github.com/opencv/opencv/issues/29596
|
||||
// cv::Mat_<bool>::depth() returns CV_Bool in 5.0, where it was CV_8U in 4.x, so
|
||||
// distanceTransform started rejecting boolean masks. CV_Bool is a 1-byte type
|
||||
// whose values are only ever zero-tested here, so the result must match the one
|
||||
// produced by an equivalent CV_8UC1 mask.
|
||||
TEST(Imgproc_DistanceTransform, bool_mask_29596)
|
||||
{
|
||||
Mat_<bool> mask(7, 7, true);
|
||||
mask(3, 3) = false;
|
||||
mask(0, 6) = false;
|
||||
|
||||
Mat_<uchar> ref(7, 7, (uchar)255);
|
||||
ref(3, 3) = 0;
|
||||
ref(0, 6) = 0;
|
||||
|
||||
ASSERT_EQ(mask.depth(), CV_Bool);
|
||||
|
||||
// CV_32F output: 3x3 and 5x5 kernels, plus the precise (trueDistTrans) path
|
||||
const int maskSizes[] = { DIST_MASK_3, DIST_MASK_5, DIST_MASK_PRECISE };
|
||||
for (size_t i = 0; i < sizeof(maskSizes)/sizeof(maskSizes[0]); i++)
|
||||
{
|
||||
Mat dist_bool, dist_ref;
|
||||
ASSERT_NO_THROW(distanceTransform(mask, dist_bool, DIST_L2, maskSizes[i]));
|
||||
distanceTransform(ref, dist_ref, DIST_L2, maskSizes[i]);
|
||||
EXPECT_EQ(cv::norm(dist_bool, dist_ref, NORM_INF), 0) << "maskSize = " << maskSizes[i];
|
||||
}
|
||||
|
||||
// CV_8U output path (distanceTransform_L1_8U -> distanceATS_L1_8u)
|
||||
{
|
||||
Mat dist_bool, dist_ref;
|
||||
ASSERT_NO_THROW(distanceTransform(mask, dist_bool, DIST_L1, DIST_MASK_3, CV_8U));
|
||||
distanceTransform(ref, dist_ref, DIST_L1, DIST_MASK_3, CV_8U);
|
||||
EXPECT_EQ(cv::norm(dist_bool, dist_ref, NORM_INF), 0);
|
||||
}
|
||||
|
||||
// labels overload
|
||||
{
|
||||
Mat dist_bool, labels_bool, dist_ref, labels_ref;
|
||||
ASSERT_NO_THROW(distanceTransform(mask, dist_bool, labels_bool, DIST_L2, DIST_MASK_5));
|
||||
distanceTransform(ref, dist_ref, labels_ref, DIST_L2, DIST_MASK_5);
|
||||
EXPECT_EQ(cv::norm(dist_bool, dist_ref, NORM_INF), 0);
|
||||
EXPECT_EQ(cv::norm(labels_bool, labels_ref, NORM_INF), 0);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
Reference in New Issue
Block a user