为什么cv::findContoursreturn那么多等高线?

Why cv::findContours return so many contours?

我读过 this post,但即使在使用 cv::threshold 创建真正的二进制图像后,我仍然得到约 500 个轮廓。我做错了什么?

不应该 cv::findContours return 只有 13 个轮廓,因为有 13 个清晰的斑点?

Mat img = imread("img.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat img_thresh;
threshold(img, img_thresh, 0, 255, CV_THRESH_BINARY);

vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
cv::findContours(img_thresh, contours, hierarchy, RetrievalModes::RETR_TREE, ContourApproximationModes::CHAIN_APPROX_SIMPLE);

RNG rng(12345);
Mat drawing = Mat::zeros(img_thresh.size(), CV_8UC3);
for (int i = 0; i< contours.size(); i++)
{
    Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
}
imshow("drawing", drawing);
waitKey();

更新1 使用 cv::RETR_EXTERNAL 而不是 cv::RETR_TREE,但仍然 return 比应有的轮廓多得多。

如果你检查你的二进制图像,你会看到有很多独立的轮廓:

所以你首先需要通过腐蚀扩张来清理它们,如下代码:

你会得到这样的结果:

比原来的更干净。

全部是代码:

cv::namedWindow("result", cv::WINDOW_FREERATIO);
cv::Mat img = cv::imread(R"(rUYLL.png)");

// to gray
cv::Mat gray;
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);

cv::threshold(gray, gray, 0, 255, cv::THRESH_BINARY);
cv::erode(gray, gray, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)));
cv::dilate(gray, gray, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)));

std::vector<std::vector<cv::Point> > contours;
cv::findContours(gray, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
cv::drawContours(img, contours, -1, cv::Scalar(0, 255, 0), 2, 8);

cv::imshow("result", img);
cv::waitKey();

它是输出:

希望对您有所帮助!


还有一个最简单的方法,如果它适合你,你也可以考虑,只需将下限从 0 增加到 80,完成

cv::threshold(gray, gray, 80, 255, cv::THRESH_BINARY);

只是玩阈值并检查结果。

只需更改阈值即可获得相同的输出: