1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 15:23:05 +04:00

imgproc: accept CV_Bool masks in connected components

This commit is contained in:
jeevan6996
2026-07-27 18:54:59 +01:00
parent 53d308c2a5
commit e1f1495faa
2 changed files with 68 additions and 1 deletions
+1 -1
View File
@@ -5659,7 +5659,7 @@ namespace cv{
const char *currentParallelFramework = cv::currentParallelFramework();
const int nThreads = cv::getNumThreads();
CV_Assert(iDepth == CV_8U || iDepth == CV_8S);
CV_Assert(iDepth == CV_8U || iDepth == CV_8S || iDepth == CV_Bool);
//Run parallel labeling only if the rows of the image are at least twice the number of available threads
const bool is_parallel = currentParallelFramework != NULL && nThreads > 1 && L.rows / nThreads >= 2;
@@ -743,6 +743,73 @@ TEST(Imgproc_ConnectedComponents, single_column)
}
// See https://github.com/opencv/opencv/issues/29593
// cv::Mat_<bool>::depth() returns CV_Bool in 5.0, where it was CV_8U in 4.x, so
// connected components should keep accepting boolean masks as binary input.
TEST(Imgproc_ConnectedComponents, bool_mask_29593)
{
Mat_<bool> input_bool(5, 6, false);
input_bool(0, 0) = true;
input_bool(0, 1) = true;
input_bool(1, 1) = true;
input_bool(2, 4) = true;
input_bool(3, 4) = true;
input_bool(3, 5) = true;
input_bool(4, 2) = true;
Mat1b input_uchar(input_bool.size(), uchar(0));
for (int r = 0; r < input_bool.rows; ++r)
{
for (int c = 0; c < input_bool.cols; ++c)
{
input_uchar(r, c) = input_bool(r, c) ? uchar(255) : uchar(0);
}
}
ASSERT_EQ(input_bool.depth(), CV_Bool);
const int ccltype[] = { cv::CCL_DEFAULT, cv::CCL_WU, cv::CCL_GRANA, cv::CCL_BOLELLI,
cv::CCL_SAUF, cv::CCL_BBDT, cv::CCL_SPAGHETTI };
for (int connectivity : {4, 8})
{
for (size_t cclt = 0; cclt < sizeof(ccltype) / sizeof(ccltype[0]); ++cclt)
{
Mat1i labels_bool, labels_uchar;
int nlabels_bool = 0;
ASSERT_NO_THROW(nlabels_bool = connectedComponents(
input_bool, labels_bool, connectivity, CV_32S, ccltype[cclt]));
const int nlabels_uchar = connectedComponents(
input_uchar, labels_uchar, connectivity, CV_32S, ccltype[cclt]);
normalizeLabels(labels_bool, nlabels_bool);
normalizeLabels(labels_uchar, nlabels_uchar);
EXPECT_EQ(nlabels_bool, nlabels_uchar)
<< "connectivity = " << connectivity << ", ccltype = " << ccltype[cclt];
EXPECT_EQ(countNonZero(labels_bool != labels_uchar), 0)
<< "connectivity = " << connectivity << ", ccltype = " << ccltype[cclt];
Mat stats_bool, centroids_bool, stats_uchar, centroids_uchar;
ASSERT_NO_THROW(nlabels_bool = connectedComponentsWithStats(
input_bool, labels_bool, stats_bool, centroids_bool, connectivity, CV_32S, ccltype[cclt]));
const int nlabels_uchar_with_stats = connectedComponentsWithStats(
input_uchar, labels_uchar, stats_uchar, centroids_uchar, connectivity, CV_32S, ccltype[cclt]);
normalizeLabels(labels_bool, nlabels_bool);
normalizeLabels(labels_uchar, nlabels_uchar_with_stats);
EXPECT_EQ(nlabels_bool, nlabels_uchar_with_stats)
<< "connectivity = " << connectivity << ", ccltype = " << ccltype[cclt];
EXPECT_EQ(countNonZero(labels_bool != labels_uchar), 0)
<< "connectivity = " << connectivity << ", ccltype = " << ccltype[cclt];
EXPECT_EQ(countNonZero(stats_bool != stats_uchar), 0)
<< "connectivity = " << connectivity << ", ccltype = " << ccltype[cclt];
EXPECT_EQ(cv::norm(centroids_bool, centroids_uchar, NORM_INF), 0)
<< "connectivity = " << connectivity << ", ccltype = " << ccltype[cclt];
}
}
}
TEST(Imgproc_ConnectedComponents, 4conn_regression_21366)
{