Skip to content

Commit

Permalink
Merge pull request #3153 from stal12:4.x
Browse files Browse the repository at this point in the history
  • Loading branch information
alalek committed Feb 4, 2022
2 parents 51078a5 + 80eb045 commit 933b011
Show file tree
Hide file tree
Showing 6 changed files with 985 additions and 0 deletions.
10 changes: 10 additions & 0 deletions modules/cudaimgproc/doc/cudaimgproc.bib
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@article{Allegretti2019,
title={Optimized block-based algorithms to label connected components on GPUs},
author={Allegretti, Stefano and Bolelli, Federico and Grana, Costantino},
journal={IEEE Transactions on Parallel and Distributed Systems},
volume={31},
number={2},
pages={423--438},
year={2019},
publisher={IEEE}
}
44 changes: 44 additions & 0 deletions modules/cudaimgproc/include/opencv2/cudaimgproc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,50 @@ type.
CV_EXPORTS_W void blendLinear(InputArray img1, InputArray img2, InputArray weights1, InputArray weights2,
OutputArray result, Stream& stream = Stream::Null());

/////////////////// Connected Components Labeling /////////////////////

//! Connected Components Algorithm
enum ConnectedComponentsAlgorithmsTypes {
CCL_DEFAULT = -1, //!< BKE @cite Allegretti2019 algorithm for 8-way connectivity.
CCL_BKE = 0, //!< BKE @cite Allegretti2019 algorithm for 8-way connectivity.
};


/** @brief Computes the Connected Components Labeled image of a binary image.

The function takes as input a binary image and performs Connected Components Labeling. The output
is an image where each Connected Component is assigned a unique label (integer value).
ltype specifies the output label image type, an important consideration based on the total
number of labels or alternatively the total number of pixels in the source image.
ccltype specifies the connected components labeling algorithm to use, currently
BKE @cite Allegretti2019 is supported, see the #ConnectedComponentsAlgorithmsTypes
for details. Note that labels in the output are not required to be sequential.

@param image The 8-bit single-channel image to be labeled.
@param labels Destination labeled image.
@param connectivity Connectivity to use for the labeling procedure. 8 for 8-way connectivity is supported.
@param ltype Output image label type. Currently CV_32S is supported.
@param ccltype Connected components algorithm type (see the #ConnectedComponentsAlgorithmsTypes).

@note A sample program demonstrating Connected Components Labeling in CUDA can be found at\n
opencv_contrib_source_code/modules/cudaimgproc/samples/connected_components.cpp

*/
CV_EXPORTS_AS(connectedComponentsWithAlgorithm) void connectedComponents(InputArray image, OutputArray labels,
int connectivity, int ltype, cv::cuda::ConnectedComponentsAlgorithmsTypes ccltype);


/** @overload

@param image The 8-bit single-channel image to be labeled.
@param labels Destination labeled image.
@param connectivity Connectivity to use for the labeling procedure. 8 for 8-way connectivity is supported.
@param ltype Output image label type. Currently CV_32S is supported.
*/
CV_EXPORTS_W void connectedComponents(InputArray image, OutputArray labels,
int connectivity = 8, int ltype = CV_32S);


//! @}

}} // namespace cv { namespace cuda {
Expand Down
58 changes: 58 additions & 0 deletions modules/cudaimgproc/samples/connected_components.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <iostream>

#include <opencv2/core/utility.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/cudaimgproc.hpp"

using namespace cv;
using namespace std;
using namespace cv::cuda;


void colorLabels(const Mat1i& labels, Mat3b& colors) {
colors.create(labels.size());
for (int r = 0; r < labels.rows; ++r) {
int const* labels_row = labels.ptr<int>(r);
Vec3b* colors_row = colors.ptr<Vec3b>(r);
for (int c = 0; c < labels.cols; ++c) {
colors_row[c] = Vec3b(labels_row[c] * 131 % 255, labels_row[c] * 241 % 255, labels_row[c] * 251 % 255);
}
}
}


int main(int argc, const char** argv)
{
CommandLineParser parser(argc, argv, "{@image|stuff.jpg|image for converting to a grayscale}");
parser.about("This program finds connected components in a binary image and assign each of them a different color.\n"
"The connected components labeling is performed in GPU.\n");
parser.printMessage();

String inputImage = parser.get<string>(0);
Mat1b img = imread(samples::findFile(inputImage), IMREAD_GRAYSCALE);
Mat1i labels;

if (img.empty())
{
cout << "Could not read input image file: " << inputImage << endl;
return EXIT_FAILURE;
}


GpuMat d_img, d_labels;
d_img.upload(img);

cuda::connectedComponents(d_img, d_labels, 8, CV_32S);

d_labels.download(labels);

Mat3b colors;
colorLabels(labels, colors);

imshow("Labels", colors);
waitKey(0);

return EXIT_SUCCESS;
}
49 changes: 49 additions & 0 deletions modules/cudaimgproc/src/connectedcomponents.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.

#include "precomp.hpp"

using namespace cv;
using namespace cv::cuda;

#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)

void cv::cuda::connectedComponents(InputArray img_, OutputArray labels_, int connectivity,
int ltype, ConnectedComponentsAlgorithmsTypes ccltype) { throw_no_cuda(); }

#else /* !defined (HAVE_CUDA) */

namespace cv { namespace cuda { namespace device { namespace imgproc {
void BlockBasedKomuraEquivalence(const cv::cuda::GpuMat& img, cv::cuda::GpuMat& labels);
}}}}


void cv::cuda::connectedComponents(InputArray img_, OutputArray labels_, int connectivity,
int ltype, ConnectedComponentsAlgorithmsTypes ccltype) {
const cv::cuda::GpuMat img = img_.getGpuMat();
cv::cuda::GpuMat& labels = labels_.getGpuMatRef();

CV_Assert(img.channels() == 1);
CV_Assert(connectivity == 8);
CV_Assert(ltype == CV_32S);
CV_Assert(ccltype == CCL_BKE || ccltype == CCL_DEFAULT);

int iDepth = img_.depth();
CV_Assert(iDepth == CV_8U || iDepth == CV_8S);

labels.create(img.size(), CV_MAT_DEPTH(ltype));

if ((ccltype == CCL_BKE || ccltype == CCL_DEFAULT) && connectivity == 8 && ltype == CV_32S) {
using cv::cuda::device::imgproc::BlockBasedKomuraEquivalence;
BlockBasedKomuraEquivalence(img, labels);
}

}

void cv::cuda::connectedComponents(InputArray img_, OutputArray labels_, int connectivity, int ltype) {
cv::cuda::connectedComponents(img_, labels_, connectivity, ltype, CCL_DEFAULT);
}


#endif /* !defined (HAVE_CUDA) */
Loading

0 comments on commit 933b011

Please sign in to comment.