【发布时间】:2013-12-16 14:49:18
【问题描述】:
假设我从cv::watershed() 的输出中创建了以下二进制图像:
现在我想找到并填充轮廓,这样我就可以从原始图像中的背景中分离出相应的对象(由分水岭函数分割)。
要分割图像并找到轮廓,我使用以下代码:
cv::Mat bgr = cv::imread("test.png");
// Some function that provides the rough outline for the segmented regions.
cv::Mat markers = find_markers(bgr);
cv::watershed(bgr, markers);
cv::Mat_<bool> boundaries(bgr.size());
for (int i = 0; i < bgr.rows; i++) {
for (int j = 0; j < bgr.cols; j++) {
boundaries.at<bool>(i, j) = (markers.at<int>(i, j) == -1);
}
}
std::vector<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(
boundaries, contours, hierarchy,
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE
);
到目前为止一切顺利。但是,如果我将上面获得的轮廓传递给cv::drawContours(),如下所示:
cv::Mat regions(bgr.size(), CV_32S);
cv::drawContours(
regions, contours, -1, cv::Scalar::all(255),
CV_FILLED, 8, hierarchy, INT_MAX
);
这是我得到的:
最左边的轮廓被cv::findContours()留下,因此它没有被cv::drawContours()填充。
现在我知道这是 cv::findContours() 剪掉图像周围 1 像素边框的结果(如 documentation 中所述),但接下来该怎么办?仅仅因为它碰巧擦掉了图像的边界而丢弃轮廓似乎是一种可怕的浪费。无论如何,我怎么能找到属于这个类别的轮廓? cv::isContourConvex() 在这种情况下不是解决方案;一个区域可以是concave,但“关闭”,因此没有这个问题。
编辑:关于从边框复制像素的建议。问题是我的标记功能也在“背景”中绘制所有像素,即我确定的那些区域不是任何对象的一部分:
这会导致围绕输出绘制边界。如果我以某种方式避免cv::findContours() 剪掉那个边界:
背景的边界与最左边的对象合并:
这会产生一个漂亮的白色填充框。
【问题讨论】: