zl程序教程

您现在的位置是:首页 >  其它

当前栏目

形态学 - 细化

形态学
2023-09-11 14:15:38 时间

目录

1. 原理介绍

2. 代码讲解

3. code


1. 原理介绍

形态学的细化主要由 击中-击不中 变换实现,其数学表达式为:

  •  \otimes 定义为 B 对前景像素集合 A 的细化
  •  \circledast 定义为 B 对前景像素集合 A 的 击中-击不中 变换
  •  结构元 B 常用的有八个,如下图所示

细化的步骤为:

1. 用结构元B1 对 A 做 击中-击不中 变换,然后用原图减去变换的结果A1

2. 将上步的结果A1,用B2 做 击中-击不中 变换,然后用A1减去B2变换的结果得到A2

3 . 将八个结构元循环迭代 记作一次细化的迭代

4. 如果两次细化的迭代结果相同,则认为细化完成;否则,重复前面三步骤

循环停止的条件是:所有结构元遍历的结果不再出现变化的时候

 

2. 代码讲解

细化代码的步骤简单介绍:

首先定义八个 击中-击不中 变换的结构元

这里结构元的元素:

  • 1 代表前景像素
  • 0 代表不感兴趣的,对应的图像前景背景都可
  • -1 代表背景像素

把 击中-击不中 变换看成一个模板匹配。和kernel 一样的图像才能输出

 然后根据步骤做迭代操作

这里需要将处理前的图片保存,留着判断两次细化的步骤是否相同

然后,结构元B1 对图像做 击中-击不中 变换,将原图减去变换的结果得到ret1

将新的图像ret1 作为下次处理的图像...

这里只展示了前两次运算

 

最后,如果细化一次完成的话,处理完和处理前的结果相同,则退出循环While

  • .all 可以理解两个矩阵是否元素对应相等

 

如果传入书上的二值图像:

这里将书上的图像进行0填充了,因为试了好多次,击中-击不中变换里面好像没有0填充。

换了好多参数和输入,都没有得到想要的结果,就手动加一层pad,这样库再怎么填充,我们只需要观察内部就行了

 经常算法可以得到:

 观察发现和书上的结果是一致的

注:这里没有转化成m连通的细化集合

3. code

完整代码为:

import numpy as np
import cv2


def thin(img):          # 细化算法

    # 8 个细化 kernel
    B1 = np.array([[-1,-1,-1],[0,1,0],[1,1,1]])
    B2 = np.array([[0,-1,-1],[1,1,-1],[1,1,0]])
    B3 = np.array([[1,0,-1],[1,1,-1],[1,0,-1]])
    B4 = np.array([[1,1,0],[1,1,-1],[0,-1,-1]])
    B5 = np.array([[1,1,1],[0,1,0],[-1,-1,-1]])
    B6 = np.array([[0,1,1],[-1,1,1],[-1,-1,0]])
    B7 = np.array([[-1,0,1],[-1,1,1],[-1,0,1]])
    B8 = np.array([[-1,-1,0],[-1,1,1],[0,1,1]])

    while True:     # 循环迭代

        tmp = img       # 将上一步的操作暂存
        for i in range(8):          # 循环迭代八次
            ret1 = cv2.morphologyEx(img,cv2.MORPH_HITMISS,B1)       # B1 对图像做 击中-击不中变换
            ret1 = img - ret1                                       # 原图 减去 上一步击中-击不中的结果

            ret2 = cv2.morphologyEx(ret1,cv2.MORPH_HITMISS,B2)      # 将上步的结果作为新的输入
            ret2  = ret1 - ret2

            ret3 = cv2.morphologyEx(ret2,cv2.MORPH_HITMISS,B3)
            ret3 = ret2 - ret3

            ret4 = cv2.morphologyEx(ret3,cv2.MORPH_HITMISS,B4)
            ret4 = ret3 - ret4

            ret5 = cv2.morphologyEx(ret4,cv2.MORPH_HITMISS,B5)
            ret5 = ret4 - ret5

            ret6 = cv2.morphologyEx(ret5,cv2.MORPH_HITMISS,B6)
            ret6 = ret5 - ret6

            ret7 = cv2.morphologyEx(ret6,cv2.MORPH_HITMISS,B7)
            ret7 = ret6 - ret7

            ret8 = cv2.morphologyEx(ret7,cv2.MORPH_HITMISS,B8)
            ret8 = ret7 - ret8

            img = ret8                              # 八次迭代完成 保存结果

        if (img==tmp).all():                        # 如果所有结构元遍历的结果不再发生变化,则操作完成
            dst = img                               # 保留细化结果
            break

    return dst.astype(np.uint8)


a = np.array([
    [0,0,0,0,0,0,0,0,0,0,0,0,0],
    [0,1,1,1,1,1,1,1,1,1,1,1,0],
    [0,1,1,1,1,1,1,1,1,1,0,0,0],
    [0,1,1,1,1,1,1,1,1,1,0,0,0],
    [0,1,1,1,1,1,1,1,1,1,0,0,0],
    [0,1,1,1,0,0,1,1,1,1,0,0,0],
    [0,0,0,0,0,0,0,0,0,0,0,0,0]
],dtype=np.uint8) * 255

img = cv2.imread('./char.png',0)
_,img_bin = cv2.threshold(img,120,255,cv2.THRESH_BINARY)        # 二值化处理

ret = thin(img_bin.copy())          # 传入拷贝图像

cv2.imshow('img',np.hstack((img_bin,ret)))
cv2.waitKey()
cv2.destroyAllWindows()

处理的结果为:

图片顺序:原图、细化结果

效果还是理想的