文章目录
- 连通域简介
- 绘图代码
- 函数说明
连通域简介
所谓连通域,即Connected Component,是一组彼此相连的像素点的集合,这些像素点彼此之间可以假设一条互相链接的路径,路径上所有像素的灰度一致,或者符合某个特定的条件。
通过连通域分割,可以将图像中不同的目标区分开来,为进一步的处理打下基础,最常用的连通域滤波流程大致如下:图像灰度化->二值化->形态学处理->标记连通域,每一步的图像如图所示
其中,original是原图;gray是灰度图;binary是二值图像。由于硬币图案的颜色并不完全一致,所以在二值化时可能会出现不一致的情况,为此,需要通过腐蚀或者膨胀等形态学处理,将其内部涂抹均匀,从而得到一张目标与背景完全分割的图像,此即dilate图。
绘图代码
接下来,对完全二值化的图像进行连通域分割,得到labels图像,其中每一枚硬币所在区域,都被分配到了一个编号,即Label,最后的三维图,便是这张图像的标签值。
处理和绘图代码如下
import matplotlib.pyplot as plt
import cv2
path = 'coins.png'
imgs = {}
imgs["original"] = plt.imread(path)
imgs["gray"] = cv2.cvtColor(imgs["original"],cv2.COLOR_RGB2GRAY)
th, imgs["binary"] = cv2.threshold(imgs["gray"],
0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((5,5),np.uint8)
imgs["dilate"] = cv2.dilate(imgs["binary"], kernel)
ret, imgs["labels"] = cv2.connectedComponents(imgs["dilate"])
for i,key in enumerate(imgs,1):
plt.subplot(2,3,i)
plt.imshow(imgs[key])
plt.title(key)
plt.axis('off')
ax = plt.subplot(236, projection='3d')
ys, xs = np.indices(imgs['labels'].shape)
ax.plot_surface(xs, ys, imgs['labels'])
plt.title("labels")
plt.show()
函数说明
【connectedComponents】是opencv提供的连通域分割函数,其必不可少的输入参数是一个二值图像,此外还有两个整型参数,分别用于规定邻域形式和输出的Labels类型。其中,邻域形式主要分为4-邻域和8邻域,前者把当前像素的上下左右四个像素算作邻域,换言之,这四个像素与当前像素是连通的;8-邻域则将一个像素周围的8个像素视作邻域。
【dilate】是形态学膨胀函数。所谓膨胀,和腐蚀一样,是一种形态学操作。二值图像中只有0和1两种元素,故而可将其表示为元素值为 1 1 1的元素位置集合 A = { ( i , j ) ∣ A i j = 1 } A=\{(i,j)\vert A_{ij}=1\} A={(i,j)∣Aij=1},则腐蚀和膨胀可表示为
A ⊖ B = { ( i , j ) ∣ B i j ⊆ A } A ⊕ B = { ( i , j ) ∣ B i j ∪ A ≠ ∅ } \begin{aligned} A\ominus B&=\{(i,j)|B_{ij}\subseteq A\}\\ A\oplus B&=\{(i,j)|B_{ij}\cup A\not=\varnothing\} \end{aligned} A⊖BA⊕B={(i,j)∣Bij⊆A}={(i,j)∣Bij∪A=∅}