|
|
|
@ -288,7 +288,7 @@ namespace cv{ |
|
|
|
|
int r = range.start; |
|
|
|
|
chunksSizeAndLabels_[r] = range.end; |
|
|
|
|
|
|
|
|
|
LabelT label = LabelT(r *imgLabels_.cols / 4 + 1); |
|
|
|
|
LabelT label = LabelT((r * imgLabels_.cols + 1) / 2 + 1); |
|
|
|
|
|
|
|
|
|
const LabelT firstLabel = label; |
|
|
|
|
const int w = img_.cols; |
|
|
|
@ -390,7 +390,7 @@ namespace cv{ |
|
|
|
|
int r = range.start; |
|
|
|
|
chunksSizeAndLabels_[r] = range.end; |
|
|
|
|
|
|
|
|
|
LabelT label = LabelT(r *imgLabels_.cols / 4 + 1); |
|
|
|
|
LabelT label = LabelT((r * imgLabels_.cols + 1) / 2 + 1); |
|
|
|
|
|
|
|
|
|
const LabelT firstLabel = label; |
|
|
|
|
const int w = img_.cols; |
|
|
|
@ -606,6 +606,7 @@ namespace cv{ |
|
|
|
|
P[0] = 0; |
|
|
|
|
|
|
|
|
|
cv::Range range(0, h); |
|
|
|
|
LabelT nLabels = 1; |
|
|
|
|
|
|
|
|
|
if (connectivity == 8){ |
|
|
|
|
//First scan, each thread works with chunk of img.rows/nThreads rows
|
|
|
|
@ -623,10 +624,9 @@ namespace cv{ |
|
|
|
|
//merge labels of different chunks
|
|
|
|
|
mergeLabels4Connectivity(imgLabels, P, chunksSizeAndLabels); |
|
|
|
|
} |
|
|
|
|
LabelT nLabels = 1; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < h; i = chunksSizeAndLabels[i]){ |
|
|
|
|
flattenL(P, i * w / 4 + 1, chunksSizeAndLabels[i + 1], nLabels); |
|
|
|
|
flattenL(P, (i * w + 1) / 2 + 1, chunksSizeAndLabels[i + 1], nLabels); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//Array for statistics dataof threads
|
|
|
|
@ -650,7 +650,6 @@ namespace cv{ |
|
|
|
|
//Kesheng Wu, et al
|
|
|
|
|
template<typename LabelT, typename PixelT, typename StatsOp = NoOp > |
|
|
|
|
struct LabelingWu{ |
|
|
|
|
|
|
|
|
|
LabelT operator()(const cv::Mat& img, cv::Mat& imgLabels, int connectivity, StatsOp& sop){ |
|
|
|
|
CV_Assert(imgLabels.rows == img.rows); |
|
|
|
|
CV_Assert(imgLabels.cols == img.cols); |
|
|
|
@ -842,7 +841,7 @@ namespace cv{ |
|
|
|
|
|
|
|
|
|
chunksSizeAndLabels_[r] = range.end + (range.end % 2); |
|
|
|
|
|
|
|
|
|
LabelT label = LabelT(r *imgLabels_.cols / 4 + 1); |
|
|
|
|
LabelT label = LabelT((r + 1) * (imgLabels_.cols + 1) / 4); |
|
|
|
|
|
|
|
|
|
const LabelT firstLabel = label; |
|
|
|
|
const int h = img_.rows, w = img_.cols; |
|
|
|
@ -2562,7 +2561,7 @@ namespace cv{ |
|
|
|
|
|
|
|
|
|
LabelT nLabels = 1; |
|
|
|
|
for (int i = 0; i < h; i = chunksSizeAndLabels[i]){ |
|
|
|
|
flattenL(P, i *w / 4 + 1, chunksSizeAndLabels[i + 1], nLabels); |
|
|
|
|
flattenL(P, (i + 1) * (w + 1) / 4, chunksSizeAndLabels[i + 1], nLabels); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//Array for statistics data
|
|
|
|
@ -3932,30 +3931,28 @@ namespace cv{ |
|
|
|
|
int lDepth = L.depth(); |
|
|
|
|
int iDepth = I.depth(); |
|
|
|
|
const char *currentParallelFramework = cv::currentParallelFramework(); |
|
|
|
|
const int numberOfCPUs = cv::getNumberOfCPUs(); |
|
|
|
|
|
|
|
|
|
CV_Assert(iDepth == CV_8U || iDepth == CV_8S); |
|
|
|
|
|
|
|
|
|
//Run parallel labeling only if the rows of the image are at least twice the number returned by getNumberOfCPUs
|
|
|
|
|
const bool is_parallel = currentParallelFramework != NULL && numberOfCPUs > 1 && L.rows / numberOfCPUs >= 2; |
|
|
|
|
|
|
|
|
|
if (ccltype == CCL_WU || connectivity == 4){ |
|
|
|
|
// Wu algorithm is used
|
|
|
|
|
using connectedcomponents::LabelingWu; |
|
|
|
|
using connectedcomponents::LabelingWuParallel; |
|
|
|
|
//warn if L's depth is not sufficient?
|
|
|
|
|
if (lDepth == CV_8U){ |
|
|
|
|
if (currentParallelFramework == NULL) |
|
|
|
|
return (int)LabelingWu<uchar, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|
else |
|
|
|
|
return (int)LabelingWuParallel<uchar, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|
//Not supported yet
|
|
|
|
|
} |
|
|
|
|
else if (lDepth == CV_16U){ |
|
|
|
|
if (currentParallelFramework == NULL) |
|
|
|
|
return (int)LabelingWu<ushort, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|
else |
|
|
|
|
return (int)LabelingWuParallel<ushort, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|
} |
|
|
|
|
else if (lDepth == CV_32S){ |
|
|
|
|
//note that signed types don't really make sense here and not being able to use unsigned matters for scientific projects
|
|
|
|
|
//OpenCV: how should we proceed? .at<T> typechecks in debug mode
|
|
|
|
|
if (currentParallelFramework == NULL) |
|
|
|
|
if (!is_parallel) |
|
|
|
|
return (int)LabelingWu<int, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|
else |
|
|
|
|
return (int)LabelingWuParallel<int, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
@ -3967,21 +3964,15 @@ namespace cv{ |
|
|
|
|
using connectedcomponents::LabelingGranaParallel; |
|
|
|
|
//warn if L's depth is not sufficient?
|
|
|
|
|
if (lDepth == CV_8U){ |
|
|
|
|
if (currentParallelFramework == NULL) |
|
|
|
|
return (int)LabelingGrana<uchar, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|
else |
|
|
|
|
return (int)LabelingGranaParallel<uchar, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|
//Not supported yet
|
|
|
|
|
} |
|
|
|
|
else if (lDepth == CV_16U){ |
|
|
|
|
if (currentParallelFramework == NULL) |
|
|
|
|
return (int)LabelingGrana<ushort, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|
else |
|
|
|
|
return (int)LabelingGranaParallel<ushort, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|
} |
|
|
|
|
else if (lDepth == CV_32S){ |
|
|
|
|
//note that signed types don't really make sense here and not being able to use unsigned matters for scientific projects
|
|
|
|
|
//OpenCV: how should we proceed? .at<T> typechecks in debug mode
|
|
|
|
|
if (currentParallelFramework == NULL) |
|
|
|
|
if (!is_parallel) |
|
|
|
|
return (int)LabelingGrana<int, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|
else |
|
|
|
|
return (int)LabelingGranaParallel<int, uchar, StatsOp>()(I, L, connectivity, sop); |
|
|
|
|