形态学重建:孔洞填充的python实现

系统 2167 0

质量声明:原创文章,内容质量问题请评论吐槽。如对您产生干扰,可私信删除。
主要参考:(美)拉斐尔·C.冈萨雷斯. 数字图像处理 第3版[M]. 阮秋琦,译. 北京:电子工业出版社, 2017: 633.


形态学重建

形态学重建涉及两幅图像和一个结构元:

  • Marker 图像 :包含变换的起点,将被连续膨胀,直至收敛
  • Mask 图像 :用来约束膨胀结果,即 Mask >= Marker
  • 结构单元 (Structuring Element,SE):定义连通性

数学迭代式:
M a r k e r = ( M a r k e r ⊕ S E ) ∩ M a s k Marker = (Marker \oplus SE) \cap Mask M a r k e r = ( M a r k e r S E ) M a s k
代码示例:

            
              
                def
              
              
                imreconstruct
              
              
                (
              
              marker
              
                ,
              
               mask
              
                ,
              
               SE
              
                =
              
              np
              
                .
              
              ones
              
                (
              
              
                [
              
              
                3
              
              
                ,
              
              
                3
              
              
                ]
              
              
                )
              
              
                )
              
              
                :
              
              
                """
    描述:以mask为约束,连续膨胀marker,实现形态学重建,其中mask >= marker
    
    参数:
        - marker 标记图像,单通道/三通道图像
        - mask   模板图像,与marker同型
        - conn   联通性重建结构元,参照matlab::imreconstruct::conn参数,默认为8联通
    """
              
              
                while
              
              
                True
              
              
                :
              
              
        marker_pre 
              
                =
              
               marker
        dilation 
              
                =
              
               cv
              
                .
              
              dilate
              
                (
              
              marker
              
                ,
              
               kernel
              
                =
              
              SE
              
                )
              
              
        marker 
              
                =
              
               np
              
                .
              
              
                min
              
              
                (
              
              
                (
              
              dilation
              
                ,
              
               mask
              
                )
              
              
                ,
              
               axis
              
                =
              
              
                0
              
              
                )
              
              
                if
              
              
                (
              
              marker_pre 
              
                ==
              
               marker
              
                )
              
              
                .
              
              
                all
              
              
                (
              
              
                )
              
              
                :
              
              
                break
              
              
                return
              
               marker

            
          

孔洞填充

孔洞定义:被前景(白色)连通域包围的封闭的背景(黑色)区域,不限于圆形。如图所示。
形态学重建:孔洞填充的python实现_第1张图片
原理:
以原图像的补集作为Mask,用来限制膨胀结果;以带有白色边框的黑色图像为初始Marker,用SE对其进行连续膨胀,直至收敛;最后对Marker取补即得到最终图像,与原图相减可得到填充图像。

M a r k e r ( x , y ) = { 255 , ( x , y ) ∈ B o u n d a r y 0 , o t h e r s Marker(x, y) = \left\{\begin{matrix} 255 & , & (x,y) \in Boundary\\ 0 & , & others \end{matrix}\right. M a r k e r ( x , y ) = { 2 5 5 0 , , ( x , y ) B o u n d a r y o t h e r s

代码示例:

            
              
                import
              
               numpy 
              
                as
              
               np

              
                import
              
               cv2 
              
                as
              
               cv

              
                from
              
               matplotlib 
              
                import
              
               pyplot 
              
                as
              
               plt

img 
              
                =
              
               cv
              
                .
              
              imread
              
                (
              
              
                "text.jpg"
              
              
                )
              
              
                # 二值化
              
              
imgray 
              
                =
              
               cv
              
                .
              
              cvtColor
              
                (
              
              img
              
                ,
              
               cv
              
                .
              
              COLOR_BGR2GRAY
              
                )
              
              
imgray
              
                [
              
              imgray 
              
                <
              
              
                100
              
              
                ]
              
              
                =
              
              
                0
              
              
imgray
              
                [
              
              imgray 
              
                >=
              
              
                100
              
              
                ]
              
              
                =
              
              
                255
              
              
                # 原图取补得到MASK图像
              
              
mask 
              
                =
              
              
                255
              
              
                -
              
               imgray


              
                # 构造Marker图像
              
              
marker 
              
                =
              
               np
              
                .
              
              zeros_like
              
                (
              
              imgray
              
                )
              
              
marker
              
                [
              
              
                0
              
              
                ,
              
              
                :
              
              
                ]
              
              
                =
              
              
                255
              
              
marker
              
                [
              
              
                -
              
              
                1
              
              
                ,
              
              
                :
              
              
                ]
              
              
                =
              
              
                255
              
              
marker
              
                [
              
              
                :
              
              
                ,
              
              
                0
              
              
                ]
              
              
                =
              
              
                255
              
              
marker
              
                [
              
              
                :
              
              
                ,
              
              
                -
              
              
                1
              
              
                ]
              
              
                =
              
              
                255
              
              
marker_0 
              
                =
              
               marker
              
                .
              
              copy
              
                (
              
              
                )
              
              
                # 形态学重建
              
              
SE 
              
                =
              
               cv
              
                .
              
              getStructuringElement
              
                (
              
              shape
              
                =
              
              cv
              
                .
              
              MORPH_CROSS
              
                ,
              
               ksize
              
                =
              
              
                (
              
              
                3
              
              
                ,
              
              
                3
              
              
                )
              
              
                )
              
              
                while
              
              
                True
              
              
                :
              
              
    marker_pre 
              
                =
              
               marker
    dilation 
              
                =
              
               cv
              
                .
              
              dilate
              
                (
              
              marker
              
                ,
              
               kernel
              
                =
              
              SE
              
                )
              
              
    marker 
              
                =
              
               np
              
                .
              
              
                min
              
              
                (
              
              
                (
              
              dilation
              
                ,
              
               mask
              
                )
              
              
                ,
              
               axis
              
                =
              
              
                0
              
              
                )
              
              
                if
              
              
                (
              
              marker_pre 
              
                ==
              
               marker
              
                )
              
              
                .
              
              
                all
              
              
                (
              
              
                )
              
              
                :
              
              
                break
              
              
dst 
              
                =
              
              
                255
              
              
                -
              
               marker
filling 
              
                =
              
               dst 
              
                -
              
               imgray


              
                # 显示
              
              
plt
              
                .
              
              figure
              
                (
              
              figsize
              
                =
              
              
                (
              
              
                12
              
              
                ,
              
              
                6
              
              
                )
              
              
                )
              
              
                # width * height
              
              
plt
              
                .
              
              subplot
              
                (
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                1
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              imshow
              
                (
              
              imgray
              
                ,
              
               cmap
              
                =
              
              
                'gray'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              title
              
                (
              
              
                'src'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              axis
              
                (
              
              
                "off"
              
              
                )
              
              
plt
              
                .
              
              subplot
              
                (
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                2
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              imshow
              
                (
              
              mask
              
                ,
              
               cmap
              
                =
              
              
                'gray'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              title
              
                (
              
              
                'Mask'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              axis
              
                (
              
              
                "off"
              
              
                )
              
              
plt
              
                .
              
              subplot
              
                (
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                3
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              imshow
              
                (
              
              marker_0
              
                ,
              
               cmap
              
                =
              
              
                'gray'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              title
              
                (
              
              
                'Marker 0'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              axis
              
                (
              
              
                "off"
              
              
                )
              
              
plt
              
                .
              
              subplot
              
                (
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                4
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              imshow
              
                (
              
              marker
              
                ,
              
               cmap
              
                =
              
              
                'gray'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              title
              
                (
              
              
                'Marker'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              axis
              
                (
              
              
                "off"
              
              
                )
              
              
plt
              
                .
              
              subplot
              
                (
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                5
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              imshow
              
                (
              
              dst
              
                ,
              
               cmap
              
                =
              
              
                'gray'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              title
              
                (
              
              
                'dst'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              axis
              
                (
              
              
                "off"
              
              
                )
              
              
plt
              
                .
              
              subplot
              
                (
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                6
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              imshow
              
                (
              
              filling
              
                ,
              
               cmap
              
                =
              
              
                'gray'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              title
              
                (
              
              
                'Holes'
              
              
                )
              
              
                ,
              
               plt
              
                .
              
              axis
              
                (
              
              
                "off"
              
              
                )
              
              
plt
              
                .
              
              show
              
                (
              
              
                )
              
            
          

结果展示:
形态学重建:孔洞填充的python实现_第2张图片

原图 text.jpg
形态学重建:孔洞填充的python实现_第3张图片

选用不同尺寸的SE,进行填充对比:ksize=3x3(左),ksize=7x7(右)
形态学重建:孔洞填充的python实现_第4张图片
由此可见, 如果选择的结构单元过大,膨胀操作会越过边界,膨胀到孔洞中,导致部分孔洞填充失败。就本例来看3x3的SE可以做到准确填充。

并且,对于大小不一的孔洞,3x3的SE同样可以做到准确填充。如图所示:
形态学重建:孔洞填充的python实现_第5张图片

注: 关于孔洞填充的其他问题,可以参考博文 形态学填充孔洞的几个问题


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论