Я реализовал алгоритм идентификации подключенных компонентов из здесь, но он кажется, что 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 содержит 2448x2050 пикселей размера CV_8U. Значения пикселей равны 0 (фон) или 255 (передний план). На изображении 17 связанных компонентов. Все компоненты, кроме первого, определены правильно. Ошибочный компонент намного больше (~ 1,5 миллиона пикселей) и содержит несколько небольших несвязанных групп пикселей. Он включает в себя все остальные компоненты. Небольшие несвязанные группы пикселей, которые ошибочно назначены первому компоненту, все связаны с верхней частью ограничивающей рамки компонентов.
РЕДАКТИРОВАТЬ: я добавил несколько изображений, чтобы визуализировать проблему. На первом изображении показаны все идентифицированные подключенные компоненты. На втором изображении показан только ошибочный компонент (обратите внимание на небольшие несвязанные группы пикселей вверху). Третье изображение увеличивает часть второго изображения:
Если у кого-то есть идея, где может быть ошибка, я был бы благодарен.