形态学填充孔洞的几个问题

形态学填充孔洞的几个问题

最近做文字和数字方面的图像处理,由于字符存在很多孔洞,提取轮廓时需要加上许多条件才能将字符提取出来,而且像“0”这种字符,内外轮廓差不了多少,虽然可以用在OpenCV的findcontours函数中的hierarchy[i][3]来判定父轮廓或子轮廓,但过多的条件容易使轮廓提取不准确不说,也会造成字符提取的适应性不强;使用了教材上形态学重建中的填充算法,但怎么也实现不了,不知道是不是自己的实现上有问题,而网上千篇一律的不是只说明了原理和结果,就是用Matlab中的imfill()函数完事(严重鄙视那些不经验证、没有独立思考精神、只会拿来主义的人),没办法,只能自己琢磨下,特此记录下结果,如果有更好办法的高能,愿意指教的话,本人不胜感激。

一、教材理解

这是关键的一步,也是被书上(冈萨雷斯第三版)一笔带过的一步,书上说的,标记图像是这样的:

形态学填充孔洞的几个问题_第1张图片

反正这个公式我是看了半天没看懂(他只说 I 是一幅二值图像,没说I(x,y)是如何标定的,我简单的大脑实在想不出来 1 - I(x,y) 所表达的数学模型是怎么样的。)而从配备的插图上来看,F 应该是一幅包围原图像外轮廓的一幅标记图像。

形态学填充孔洞的几个问题_第2张图片

别人我不知道,但对于我提取字符来说,如果知道了外轮廓直接就开干下一步了,还填充就没意义了,而如果进行复杂的条件进行筛选外轮廓的意义也不是很大,所以难点就在于如何找标记图像。

二、教材实验结果的看法

形态学填充孔洞的几个问题_第3张图片

这幅图是教材上处理成功的原图,看了这些细节,除了不能理解实验结果之外,对于为什么标记图图像是一幅纯黑色的,我也是疑惑了好久(一脸懵逼状)。(注:我看的是中文电子版的书籍,不知道原书情况,如果有错误的地方,感谢指正)
这里写图片描述

而我处理不了(准确说应该是生成标记图像的问题,而不是处理不了)的图长这个样子,直到后来处理完了,我才发现处理不了的一个很大的可能是我的图像的孔太大了(至于为什么,下文会解释)。

三、孔洞填充(个人观点)

孔洞填充其实就是一个形态学膨胀重建的过程,具体重建理论,请移步教材,或网上搜,一大把,下面进入正题,一步步讲解形态学膨胀重建来填充孔洞的各个方面:

1、标记图像

原打算用形态学提取边界,然后想办法保留下外围轮廓(父轮廓),而不管是腐蚀、膨胀,与操作、或操作,两个轮廓的变化方向是相反的(内的向内,外的向外),意思就是说,两个轮廓要不就同时存在,要不就同时不存在,没办法,使它们保持不一致的变化。

所以其实书上说的,标记图像只包含边界位置是错误的,它可以是不包含孔洞的任意图像,比如下样:
形态学填充孔洞的几个问题_第4张图片

以上这两幅图像都可以作为标记图像(原图以上文为例)不会存在任何区别,唯一的区别可能就在于重建时膨胀的次数的问题。所以只要图像孔洞内部不存在像素点,即使外面只有一个像素点,你也可以把整张图的孔洞填充上,现在你可以大声说:给我一个像素,我要填充所有孔洞。
下面看一个反例,下面这样的:
这里写图片描述
这一副图像不可以作为标记图像的原因是它孔洞内部有像素点。

2、模版图像长什么样?

模版图像还是用待处理图像取反得到,就像这样:
这里写图片描述
好了,东西都准备齐了,我们开始填充孔洞了。

3、为什么这样可以填充孔洞

孔洞填充实际就是一个重建膨胀操作(实质就是迭代的条件膨胀而已),每次的膨胀操作都会使图像的黑色部分慢慢减少,而白色像素慢慢增加(快慢取决于结构元SE),然后每次和模版图像做与运算,当标记图像继续膨胀,当想要越过模版黑色边界时,每次的与运算会使膨胀进去的多余部分消除掉,所以,当标记图像达到稳定时,标记图像就膨胀填满了所有外部,而内部却没有一个像素。就像下面这样:
这里写图片描述

此时直接取反,就能得到全部孔洞被填充满的图像,就像下面这样:
这里写图片描述

同时你也可以将得到的标记图像去补,然后和模版图像相与,得到,孔洞图像, 就像这样:
这里写图片描述

好了,具体的过程就这些:

Tips:

1、选取标记图像时,可以通过膨胀或腐蚀操作来选取标记图像,但结构元SE要足够大,需要把孔洞内的内容全部覆盖掉,不然就处理不出来(这也就是前文说的,由于书上例子的孔洞较小,一次小模版腐蚀就能把空洞内部点处理掉,而我的孔洞过大,导致处理不掉的原因,例子中标记图像内部只有两个像素宽度,处理起来所以容易)。

2、选取标记图像时,你甚至可以在不属于孔洞的区域随机设置一个白色像素点也可以达到膨胀重建的操作,只是迭代的次数不一样,所以,这里选取腐蚀图像作为标记图像的目的是为了让迭代的次数少一些而已。

3、选取重建结构元时,要根据边界像素宽度来选取,如果结构元过大,会导致重建膨胀时,越过边界,膨胀到孔洞中,导致处理失败;选取过小的话,会导致膨胀次数多,速度慢,当然,现在的计算机采用3*3的结构元处理也是很快的。

4、由于边界像素过于狭窄,字符过小,也可能导致失败,就像这样:

这里写图片描述

当时这张图就填充不了,仔细观察,才发现膨胀时直接越过了边界,把孔洞内部也重建了,这种情况,可以将图像放大到一定尺寸再进行填充。

你可能感兴趣的:(Opencv形态学)