gpt4 book ai didi

c++ - OpenCV floodFill() 填充未连接的区域

转载 作者:太空宇宙 更新时间:2023-11-04 13:55:02 31 4
gpt4 key购买 nike

我已经实现了来自 here 的连接组件识别算法,但在某些情况下,cv::floodFill(...) 似乎会填充未连接的区域。

首先,这是代码:

void ImageMatchingOpenCV::getConnectedComponents(const cv::Mat& binImg, vector<vector<cv::Point>>& components, vector<vector<cv::Point>>& contours, const int minSize)
{
cv::Mat ccImg;
binImg.convertTo(ccImg, CV_32FC1);

int gap=startPointParams.gap;
int label = 1;
for(int y=gap; y<binImg.rows-gap; ++y)
{
for(int x=gap; x<binImg.cols-gap; ++x)
{
if((int)ccImg.at<float>(y, x)!=255) continue;
cv::Rect bBox;
cv::floodFill(ccImg, cv::Point(x, y), cv::Scalar(label), &bBox, cv::Scalar(0), cv::Scalar(0), 4 /*| cv::FLOODFILL_FIXED_RANGE*/);
if(bBox.x<gap || bBox.y<gap || bBox.x+bBox.width>=binImg.cols-gap || bBox.y+bBox.height>=binImg.rows-gap) continue;
components.push_back(vector<cv::Point>()); contours.push_back(vector<cv::Point>());
for(int i=bBox.y; i<bBox.y+bBox.height; ++i)
{
for(int j=bBox.x; j<bBox.x+bBox.width; ++j)
{
if((int)ccImg.at<float>(i, j)!=label) continue;
components.back().push_back(cv::Point(j, i));
if( (int)ccImg.at<float>(i+1, j)!=label
|| (int)ccImg.at<float>(i-1, j)!=label
|| (int)ccImg.at<float>(i, j+1)!=label
|| (int)ccImg.at<float>(i, j-1)!=label) contours.back().push_back(cv::Point(j, i));
}
}
if(components.back().size()<minSize)
{
components.pop_back();
contours.pop_back();
}
else
{
++label;
if(label==255) ++label;
break;
}
}
if(label!=1) break;
}
}

输入 cv::Mat 包含大小为 CV_8U 的 2448x2050 像素。像素值为 0(背景)或 255(前景)。图像中有 17 个连通分量。除第一个组件外,所有组件均已正确识别。错误的组件是迄今为止最大的一个(约 150 万像素),并且包含一些小的断开连接的像素组。它包含所有其他组件。错误分配给第一个组件的小的不连接像素组都连接到组件边界框的顶部。

编辑:我添加了一些图像来可视化问题。第一张图片显示了所有已识别的连接组件。第二张图片只显示了错误的组件(注意顶部断开连接的小像素组)。第三张图片放大了第二张图片的一部分:

All components

The erroneous component

Zoomed erroneous component

如果有人知道错误可能在哪里,我将不胜感激。

最佳答案

我自己发现了这个错误。在方法结束时,小组件被丢弃。在这种情况下,组件的编号(标签)不会增加:

if(components.back().size()<minSize)
{
components.pop_back();
contours.pop_back();
}
else
{
++label;
if(label==255) ++label;
}

这意味着,标签编号再次用于标记图像中的下一个组件。因此,几个小组件和一个足够大的组件可能具有相同的标签号。如果现在迭代大组件的边界框,那么这个边界框可能包含一些以前识别但未使用的具有相同标签号的小组件。

解决方案是删除 else 分支,而是始终增加标签编号。

关于c++ - OpenCV floodFill() 填充未连接的区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21906305/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com