分享一个Opencv二值图像孔洞填充算法

meadow 2015-08-07 10:23:56
加精
在Matlab下,使用imfill可以很容易的完成孔洞填充操作,感觉这是一个极为常用的方法,然而不知道为什么Opencv里面却没有集成这个函数。在网上查了好多关于Opencv下的孔洞填充方法,大部分使用轮廓查找方法去做的,但对于这种方法,总感觉不是特别好。之前了解过冈萨雷斯那本书上的孔洞填充算法,所以想着手重新写一个。这里借鉴了冈萨雷斯书上的集合运算方法(并不完全一样)

大致思路如下:

0, 设原图像为 A。

1, 首先A向外延展一到两个像素,并将值填充为背景色(0),标记为B。

2, 使用floodFill函数将B的大背景填充,填充值为前景色(255),种子点为(0,0)即可(步骤一可以确保(0,0)点位于大背景),标记为C。

3, 将填充好的图像裁剪为原图像大小(去掉延展区域),标记为D。

4, 将D取反与A相加即得填充的图像,E=A|(~D)。



下面使用OpenCV对算法进行函数封装(越短小越精悍)
void fillHole(const Mat srcBw, Mat &dstBw)
{
Size m_Size = srcBw.size();
Mat Temp=Mat::zeros(m_Size.height+2,m_Size.width+2,srcBw.type());//延展图像
srcBw.copyTo(Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)));

cv::floodFill(Temp, Point(0, 0), Scalar(255));

Mat cutImg;//裁剪延展的图像
Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)).copyTo(cutImg);

dstBw = srcBw | (~cutImg);
}

...全文
10808 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
岚止 2019-01-16
  • 打赏
  • 举报
回复
学到了,感谢楼主!
沐细雨如春风 2016-08-12
  • 打赏
  • 举报
回复
今天借用了一下,确实要先取反,以黑色为背景,不然一片白的。
yhlzxq 2016-01-11
  • 打赏
  • 举报
回复
那这种空洞的
pzx7510716 2016-01-11
  • 打赏
  • 举报
回复
看起来很好的样子,先学习一下了!
qq_23027955 2016-01-11
  • 打赏
  • 举报
回复
看起来很好的样子,先学习一下
meadow 2016-01-11
  • 打赏
  • 举报
回复
引用 29 楼 zhao4zhong1 的回复:
填充外部再取反不就行了。
这样对于空洞内的孔洞就不成立了,譬如上面白色的环套一个白色的环
赵4老师 2016-01-11
  • 打赏
  • 举报
回复
填充外部再取反不就行了。
nettman 2016-01-10
  • 打赏
  • 举报
回复
学习
blueink_200451 2016-01-10
  • 打赏
  • 举报
回复
感谢楼主,万分感谢,O(∩_∩)O哈哈~
qq_33668146 2016-01-10
  • 打赏
  • 举报
回复
感谢分享 不过内容少了点
sinat_32168875 2016-01-10
  • 打赏
  • 举报
回复
CSDN 移动客户端正式发布 微信公众平台开发入门 深入理解计算机网络
cccjz 2016-01-10
  • 打赏
  • 举报
回复
cattpon 2016-01-10
  • 打赏
  • 举报
回复
感谢分享~!!
Kevin-Y 2016-01-08
  • 打赏
  • 举报
回复
感谢楼主,万分感谢,O(∩_∩)O哈哈~
bluesen 2015-08-10
  • 打赏
  • 举报
回复
发散思维一下,我怎么觉得有点像围棋的死子判断算法?各种形状的棋,没气了,要提子。
meadow 2015-08-10
  • 打赏
  • 举报
回复
引用 16 楼 wangyaninglm 的回复:
[quote=引用 15 楼 longvipp 的回复:] 譬如说像这样的: 能够达到很好的效果
yi 莫有啊,楼主能否代码贴出来我看看[/quote]
int main()
{
Mat img=cv::imread("23.jpg");

Mat gray;
cv::cvtColor(img, gray, CV_RGB2GRAY);

Mat bw;
cv::threshold(gray, bw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

Mat bwFill;
fillHole(bw, bwFill);

imshow("填充前", gray);
imshow("填充后", bwFill);
waitKey();
return 0;
}
先把图像二值化了
shiter 2015-08-10
  • 打赏
  • 举报
回复
引用 15 楼 longvipp 的回复:
譬如说像这样的: 能够达到很好的效果
yi 莫有啊,楼主能否代码贴出来我看看
meadow 2015-08-10
  • 打赏
  • 举报
回复
譬如说像这样的:


能够达到很好的效果
meadow 2015-08-10
  • 打赏
  • 举报
回复
引用 8 楼 wangyaninglm 的回复:
[quote=引用 7 楼 longvipp 的回复:] 如果不做任何处理的话,上面的图片在Matlab下应该也是全白的
我的意思是,黑色的轮廓内部不就是孔洞么?[/quote]是的,但是孔洞填充大部分算法是把黑色认为背景色,白色认为前景色,如果真要去做的话,可以先把二值图像取反后再填充,然后取反过来就行了
meadow 2015-08-10
  • 打赏
  • 举报
回复
这个是我对上面截了一下屏测试的结果:



需要强调一点的是,这段程序只会把黑色认为是背景色,如果考虑周全的话,可以把边界相邻的孔洞也考虑进去
加载更多回复(11)

19,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧