我想出了这个解决方案:
Mat threshUpper, threshLower;
threshold(inImage, threshUpper, inThreshold, 128, CV_THRESH_BINARY);
threshold(inImage, threshLower, inThreshold-inHysteresis, 128, CV_THRESH_BINARY);
// Find the contours to get the seed from which starting floodfill
vector<vector<Point>> contoursUpper;
cv::findContours(threshUpper, contoursUpper, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
// Makes brighter the regions that contain a seed
for(auto cnt : contoursUpper){
cv::floodFill(threshLower, cnt[0], 255, 0, 2, 2, CV_FLOODFILL_FIXED_RANGE);
}
//Threshold the image again to make black the not filled regions
threshold(threshLower, outImg, 200, 255, CV_THRESH_BINARY);
尽管如此,我仍在试图弄清楚为什么 Floodfill 在某些输入上花费大量时间(大约 1.5 秒)而在其他输入上(5 毫秒)平稳运行!
编辑:如果您不关心具有区域的二进制图像但您对轮廓属性感兴趣,则可以只拥有两个阈值图像并执行以下说明。有两种解决方案,一种保证滞后的正确性,但为 O(n^2),另一种用其边界框近似区域并运行在 O(n)
vector<vector<Point>> contoursUpper, contoursLower;
cv::findContours(threshUpper, contoursUpper, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
cv::findContours(threshLower, contoursLower, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
// Correct solution O(n^2)
for(auto cntU : contoursUpper){
for(auto cntL : contoursLower){
if(cv::pointPolygonTest(cntL, cntU[0], false) >= 0){
///@todo: Do something with the cntL region (e.g. compute bounding box etc.)
break; //Already found the connected region the others cannot be connected too
}
}
}
// Approx. solution: O(n)
double minV, maxV;
for(auto cntL : largerContours){
auto minBoundingBox = boundingRect(cntL);
minMaxLoc(narrowThreshold(minBoundingBox), &minV, &maxV);
if(maxV > 1){
///@todo: Do something with the cntL region (e.g. compute bounding box etc.)
}
}