我有一个问题,就是如何根据颜色过滤一些轮廓。我想删除所有黑色像素的等高线,只保留白色像素的等高线(见下图)。
创建等高线列表的代码。我使用了RETR_TREE等高线检索模式和CHAIN_APPROX_SIMPLE点选择来避免等高线内的大量点。
cv::cvtColor(src_img, gray_img, cv::COLOR_BGR2GRAY);
cv::threshold(gray_img, bin_img, minRGB, maxRGB, cv::THRESH_BINARY_INV);
std::vector<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(bin_img, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
然后,使用这些等高线,我已经建立了封闭的路径,并在屏幕上显示它们。
一个输入图像。
目前我的结果。
我需要的是: 只填充等高线,其中有白色内容。
我试着将所有等高线放大到1个像素,并检查是否所有的像素都等于暗色,但它并没有像我所期望的那样工作。请看下面的代码。
double scaleX = (double(src_img.cols) - 2) / double(src_img.cols);
double scaleY = (double(src_img.rows) - 2) / double(src_img.rows);
for (int i = 0; i < contours.size(); i++) {
std::vector<cv::Point> contour = contours[i];
cv::Moments M = cv::moments(contour);
int cx = int(M.m10 / M.m00);
int cy = int(M.m01 / M.m00);
std::vector<cv::Point> scaledContour(contour.size());
for (int j = 0; j < contour.size(); j++) {
cv::Point point = contour[j];
point = cv::Point(point.x - cx, point.y - cy);
point = cv::Point(point.x * scaleX, point.y * scaleY);
point = cv::Point(point.x + cx, point.y + cy);
scaledContour[j] = point;
}
contours[i] = scaledContour;
}
如果您能提供任何想法或解决方案,我将非常感激,非常感谢您!
希望有一件事是清楚的,图像中的对象应该是白色的,而背景是黑色的,当你通过使用 THRESH_BINARY_INV
.
所以我们基本上是想找到白线而不是黑线。我不提供代码,因为我在python中工作,但我将列出它可以如何完成。
mask
.mask
与白色即255,同时提供了。thickness=-1
. 这意味着我们基本上是在填充轮廓。mask
这次用厚度为1的黑色。bitwise_and
图像和蒙版之间。只有轮廓内有白色的区域才会被留下。现在你只需要看看输出是否完全是黑色的。如果不是,那就意味着你不需要填充那个轮廓,因为它里面有东西。
编辑
哦,我不知道你的图像会有600个轮廓,是的,这将需要大量的时间,我不知道为什么我没有想到使用。hierarchy
前。
你可以使用 RETR_TREE
本身和层次结构值是 [next, previous, first_child, parent]
. 所以我们只需要检查一下 first_child=-1
那就意味着里面没有轮廓,你可以填充它。
我已经把模式改为 RETR_CCOMP 并增加一个区域过滤,由 层次结构[轮廓指数][3] != -1 意思是,没有父母),我的问题就解决了。谢谢你