如何填充触摸图像边框的轮廓?

 十七虾妈妈 发布于 2023-02-12 15:15

假设我从输出中创建了以下二进制图像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_ boundaries(bgr.size());
for (int i = 0; i < bgr.rows; i++) {
    for (int j = 0; j < bgr.cols; j++) {
        boundaries.at(i, j) = (markers.at(i, j) == -1);
    }
}

std::vector > contours;
std::vector 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像素边框的结果(如文档中所述),但该怎么办呢?放弃轮廓似乎是一种可怕的浪费,因为它碰巧刷掉了图像的边框.无论如何,我怎么能找到属于这个类别的轮廓?cv::isContourConvex()在这种情况下不是解决方案; 一个区域可以是凹的但是"封闭",因此没有这个问题.

编辑:关于从边框复制像素的建议.问题是我的标记功能也在绘制"背景"中的所有像素,即那些我确定不属于任何对象的区域:

在此输入图像描述

这导致在输出周围绘制边界.如果我以某种方式避免cv::findContours()削减该边界:

在此输入图像描述

背景的边界与最左边的对象合并:

在此输入图像描述

这导致一个漂亮的白色填充框.

1 个回答
  • 解决方案编号1:使用在每个方向上延伸一个像素的图像:

    Mat extended(bgr.size()+Size(2,2), bgr.type());
    Mat markers = extended(Rect(1, 1, bgr.cols, bgr.rows));
    
    // all your calculation part
    
    std::vector<std::vector<Point> > contours;
    findContours(boundaries, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    
    Mat regions(bgr.size(), CV_8U);
    drawContours(regions, contours, -1, Scalar(255), CV_FILLED, 8, Mat(), INT_MAX, Point(-1,-1));
    

    请注意,轮廓是从扩展图像中提取的,即它们的x和y值比它们应该大1.这就是我使用带有(-1,-1)像素偏移的drawContours的原因.

    解决方案编号2:从图像边界添加白色像素到相邻行/列:

    bitwise_or(boundaries.row(0), boundaries.row(1), boundaries.row(1));
    bitwise_or(boundaries.col(0), boundaries.col(1), boundaries.col(1));
    bitwise_or(boundaries.row(bgr.rows()-1), boundaries.row(bgr.rows()-2), boundaries.row(bgr.rows()-2));
    bitwise_or(boundaries.col(bgr.cols()-1), boundaries.col(bgr.cols()-2), boundaries.col(bgr.cols()-2));
    

    这两种解决方案都是半肮脏的解决方法,但这是我能想到的.

    2023-02-12 15:18 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有