形态学 - 击中-击不中变换

目录

1. HMT 介绍

2. 代码实现


1. HMT 介绍

HMT全称是Hit miss transformation --- 击中 击不中变换,这里我们只对二值图像做处理

二值图像是图像的灰度值只有两个值的图像,也就是非黑即白的图像,所以常用0表示黑,255表示白来表示二值图像

HMT 是形状检测的基本工具,其数学公式为:

  • 通过结构元B1 对前景目标(灰度值为1255的点)做腐蚀操作
  • 通过结构元B2 对背景目标(灰度值为0的点)做腐蚀操作。因为我们只对二值图像做处理,只包含了前景+背景,所以背景目标也可以认为是前景目标的补集
  • 最后将前两步骤的图像求公共的集合,即交集

以上均为书上的概念,下面说说自己的理解:

击中-击不中这个词其实包含了两个意思:击中,击不中

击中相当于书上的第一步,击不中相当于书上的第二步,最后取交集就是击中-击不中变换

扫描二维码关注公众号,回复: 16703115 查看本文章
  • 何为击中 ? 我们可以将SE类比成空间滤波器的形式,例如(3,3)的kernel 在图像上进行滑动,如果kernel上面的点和图像上的点对应,即为击中,所以在kernel的中心输出前景点。这个过程也就是腐蚀
  • 何为击不中 ? 同样,通过另一个kernel 对背景进行操作,注意,我们这里是对背景进行操作,如果击中了背景,则输出前景点。因为对背景操作,所以我们对背景击中了,可以等价于前景击不中

但是这里需要两个kernel ,并且kernel 还需要不一样(要不然没有交集了),除此之外还需要计算图像的补集等等,过程很麻烦,我们可以通过一个kernel类似于空间滤波的方式将击中-击不中变换直接实现

因为kernel 需要包含击中、击不中两个部分,所以kernel 需要两个值分别对应击中、击不中。而往往我们kernel上面有些位置是不在乎的,意思就是对应的位置不在乎是前景还是背景,所以又需要一个值。

因此击中-击不中变换的kernel包含了三个值,我们如下定义:

  • 1 代表击中
  • -1 代表击不中
  • 0 代表不感兴趣的点

如图:

 我们通过五个不同的SE去处理图像:这里为了方便观看,二值图像的像素值倒过来了。但是不重要,我们只需要记住黑色为感兴趣的前景,白色为不感兴趣的背景即可

通过观察SE可知,这里没有不感兴趣的点,也就是SE只有两个值

例如第一个,我们感兴趣的地方是(3,3)周围一圈的目标,并且中心点是我们不感兴趣的背景点。所以得出一个结论,当kernel滤波原图的时候,只有原图满足一个背景点被一圈前景点包围的时候,我们才输出前景点。当周围的点满足,我们称为击中;当中心的点也满足,这里的满足其实代表满足原图的补集,也就是补集击中,原图击不中。

所以可以得出一个结论,即 原图需要和SE完全匹配才会输出前景点(这里的完全匹配是-1 和1的点,0代表不感兴趣的点)

2. 代码实现

如图:

我们现在对这个图像提取主要的轮廓。 

代码为:

import cv2
import numpy as np

img = cv2.imread('./img.png',0)
ret , img = cv2.threshold(img,0,255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)   # 阈值处理
img = cv2.resize(img,None,fx = 0.5,fy = 0.5)    # 缩小图像

kernel_horizontal = np.array([[0,-1,0],[0,1,0],[0,0,0]])   # 横着的 kernel
dst_horizontal = cv2.morphologyEx(img,cv2.MORPH_HITMISS,kernel_horizontal)

kernel_vertical = np.array([[0,0,0],[-1,1,0],[0,0,0]])   # 竖着的 kernel
dst_vertical = cv2.morphologyEx(img,cv2.MORPH_HITMISS,kernel_vertical)

dst = cv2.add(dst_horizontal,dst_vertical)
cv2.imshow('img',np.hstack((img,dst_horizontal,dst_vertical,dst)))
cv2.waitKey()
cv2.destroyAllWindows()

处理结果:

  •  观察可知,想要找到水平的线,只需要满足中心点为击中的点 1 ,上面的像素点为击不中的点 -1,也就是原图需要保证白色的像素点上面紧邻的是黑色的像素点才能输出
  • 中间一列没有写成 ([-1,1,-1]的转置),是因为不能保证图像的直线是单个像素点宽的
  • 尤其观察圆形的眼睛可以发现,在经过原点的水平直径的上方圆弧才有输出,是因为水平直径的圆的切线刚好是竖直的

如果kernel里面没有-1,即击不中特性的话,结果其实就是腐蚀了

猜你喜欢

转载自blog.csdn.net/qq_44886601/article/details/127545171#comments_27947686