Skip to content

Commit 933b011

Browse files
committed
Merge pull request #3153 from stal12:4.x
2 parents 51078a5 + 80eb045 commit 933b011

File tree

6 files changed

+985
-0
lines changed

6 files changed

+985
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@article{Allegretti2019,
2+
title={Optimized block-based algorithms to label connected components on GPUs},
3+
author={Allegretti, Stefano and Bolelli, Federico and Grana, Costantino},
4+
journal={IEEE Transactions on Parallel and Distributed Systems},
5+
volume={31},
6+
number={2},
7+
pages={423--438},
8+
year={2019},
9+
publisher={IEEE}
10+
}

modules/cudaimgproc/include/opencv2/cudaimgproc.hpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,50 @@ type.
731731
CV_EXPORTS_W void blendLinear(InputArray img1, InputArray img2, InputArray weights1, InputArray weights2,
732732
OutputArray result, Stream& stream = Stream::Null());
733733

734+
/////////////////// Connected Components Labeling /////////////////////
735+
736+
//! Connected Components Algorithm
737+
enum ConnectedComponentsAlgorithmsTypes {
738+
CCL_DEFAULT = -1, //!< BKE @cite Allegretti2019 algorithm for 8-way connectivity.
739+
CCL_BKE = 0, //!< BKE @cite Allegretti2019 algorithm for 8-way connectivity.
740+
};
741+
742+
743+
/** @brief Computes the Connected Components Labeled image of a binary image.
744+
745+
The function takes as input a binary image and performs Connected Components Labeling. The output
746+
is an image where each Connected Component is assigned a unique label (integer value).
747+
ltype specifies the output label image type, an important consideration based on the total
748+
number of labels or alternatively the total number of pixels in the source image.
749+
ccltype specifies the connected components labeling algorithm to use, currently
750+
BKE @cite Allegretti2019 is supported, see the #ConnectedComponentsAlgorithmsTypes
751+
for details. Note that labels in the output are not required to be sequential.
752+
753+
@param image The 8-bit single-channel image to be labeled.
754+
@param labels Destination labeled image.
755+
@param connectivity Connectivity to use for the labeling procedure. 8 for 8-way connectivity is supported.
756+
@param ltype Output image label type. Currently CV_32S is supported.
757+
@param ccltype Connected components algorithm type (see the #ConnectedComponentsAlgorithmsTypes).
758+
759+
@note A sample program demonstrating Connected Components Labeling in CUDA can be found at\n
760+
opencv_contrib_source_code/modules/cudaimgproc/samples/connected_components.cpp
761+
762+
*/
763+
CV_EXPORTS_AS(connectedComponentsWithAlgorithm) void connectedComponents(InputArray image, OutputArray labels,
764+
int connectivity, int ltype, cv::cuda::ConnectedComponentsAlgorithmsTypes ccltype);
765+
766+
767+
/** @overload
768+
769+
@param image The 8-bit single-channel image to be labeled.
770+
@param labels Destination labeled image.
771+
@param connectivity Connectivity to use for the labeling procedure. 8 for 8-way connectivity is supported.
772+
@param ltype Output image label type. Currently CV_32S is supported.
773+
*/
774+
CV_EXPORTS_W void connectedComponents(InputArray image, OutputArray labels,
775+
int connectivity = 8, int ltype = CV_32S);
776+
777+
734778
//! @}
735779

736780
}} // namespace cv { namespace cuda {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <iostream>
2+
3+
#include <opencv2/core/utility.hpp>
4+
#include "opencv2/imgproc.hpp"
5+
#include "opencv2/imgcodecs.hpp"
6+
#include "opencv2/highgui.hpp"
7+
#include "opencv2/cudaimgproc.hpp"
8+
9+
using namespace cv;
10+
using namespace std;
11+
using namespace cv::cuda;
12+
13+
14+
void colorLabels(const Mat1i& labels, Mat3b& colors) {
15+
colors.create(labels.size());
16+
for (int r = 0; r < labels.rows; ++r) {
17+
int const* labels_row = labels.ptr<int>(r);
18+
Vec3b* colors_row = colors.ptr<Vec3b>(r);
19+
for (int c = 0; c < labels.cols; ++c) {
20+
colors_row[c] = Vec3b(labels_row[c] * 131 % 255, labels_row[c] * 241 % 255, labels_row[c] * 251 % 255);
21+
}
22+
}
23+
}
24+
25+
26+
int main(int argc, const char** argv)
27+
{
28+
CommandLineParser parser(argc, argv, "{@image|stuff.jpg|image for converting to a grayscale}");
29+
parser.about("This program finds connected components in a binary image and assign each of them a different color.\n"
30+
"The connected components labeling is performed in GPU.\n");
31+
parser.printMessage();
32+
33+
String inputImage = parser.get<string>(0);
34+
Mat1b img = imread(samples::findFile(inputImage), IMREAD_GRAYSCALE);
35+
Mat1i labels;
36+
37+
if (img.empty())
38+
{
39+
cout << "Could not read input image file: " << inputImage << endl;
40+
return EXIT_FAILURE;
41+
}
42+
43+
44+
GpuMat d_img, d_labels;
45+
d_img.upload(img);
46+
47+
cuda::connectedComponents(d_img, d_labels, 8, CV_32S);
48+
49+
d_labels.download(labels);
50+
51+
Mat3b colors;
52+
colorLabels(labels, colors);
53+
54+
imshow("Labels", colors);
55+
waitKey(0);
56+
57+
return EXIT_SUCCESS;
58+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html.
4+
5+
#include "precomp.hpp"
6+
7+
using namespace cv;
8+
using namespace cv::cuda;
9+
10+
#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
11+
12+
void cv::cuda::connectedComponents(InputArray img_, OutputArray labels_, int connectivity,
13+
int ltype, ConnectedComponentsAlgorithmsTypes ccltype) { throw_no_cuda(); }
14+
15+
#else /* !defined (HAVE_CUDA) */
16+
17+
namespace cv { namespace cuda { namespace device { namespace imgproc {
18+
void BlockBasedKomuraEquivalence(const cv::cuda::GpuMat& img, cv::cuda::GpuMat& labels);
19+
}}}}
20+
21+
22+
void cv::cuda::connectedComponents(InputArray img_, OutputArray labels_, int connectivity,
23+
int ltype, ConnectedComponentsAlgorithmsTypes ccltype) {
24+
const cv::cuda::GpuMat img = img_.getGpuMat();
25+
cv::cuda::GpuMat& labels = labels_.getGpuMatRef();
26+
27+
CV_Assert(img.channels() == 1);
28+
CV_Assert(connectivity == 8);
29+
CV_Assert(ltype == CV_32S);
30+
CV_Assert(ccltype == CCL_BKE || ccltype == CCL_DEFAULT);
31+
32+
int iDepth = img_.depth();
33+
CV_Assert(iDepth == CV_8U || iDepth == CV_8S);
34+
35+
labels.create(img.size(), CV_MAT_DEPTH(ltype));
36+
37+
if ((ccltype == CCL_BKE || ccltype == CCL_DEFAULT) && connectivity == 8 && ltype == CV_32S) {
38+
using cv::cuda::device::imgproc::BlockBasedKomuraEquivalence;
39+
BlockBasedKomuraEquivalence(img, labels);
40+
}
41+
42+
}
43+
44+
void cv::cuda::connectedComponents(InputArray img_, OutputArray labels_, int connectivity, int ltype) {
45+
cv::cuda::connectedComponents(img_, labels_, connectivity, ltype, CCL_DEFAULT);
46+
}
47+
48+
49+
#endif /* !defined (HAVE_CUDA) */

0 commit comments

Comments
 (0)