基于聚类的“图像分割”

时间:2022-09-30 16:06:52

  先介绍图像分割的一点知识。所谓图像分割就是利用图像的灰度、颜色、纹理、形状等特征,把图像分成若 干个互不重叠的区域,并使这些特征在同一区域内呈现相似性,在不同的区 域之间存在明显的差异性。然后就可以将分割的图像中具有独特性质的区域 提取出来用于不同的研究。传统的图像分割方法有基于边缘检测;基于阈值分割,比如图,颜色,灰度等;水平集方法等。现在比较新的就是利用深度学习的图像分割,比如FCN的语义分割,还有许多改进的方法,比如目标检测与图像分割结合的Mask-RCNN,有兴趣的可以查阅相关资料。下面介绍的是一种比较有趣的分割方法~


基于Kmeans的“图像分割”

  原理很简单:通过将RGB图片展开成一维的数组,对每个像素基于几何距离进行聚类,我们可以指定中心点,每个像素关联一个标签0,1,2…那么这个标签”图片”就是我们”分割”后的效果了呢~

    import numpy as np
import cv2
from sklearn.cluster import KMeans
img_data=cv2.imread('D:\jjnbl.jpg')/255.0
plt.subplot(121),plt.imshow(img_data,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
#kernel=np.ones((4,4,),np.float32)/16
#img_data = cv2.filter2D(img_data, -1, kernel)
#对图片进行一下滤波平滑可能会更好看一点
row,col= img_data.shape[0],img_data.shape[1]
img_data=img_data.reshape((row*col,3))
label = KMeans(n_clusters=2).fit_predict(img_data) # 聚类中心的个数为3
label = label.reshape([row, col]) *50+50 # 聚类获得每个像素所属的类别
plt.subplot(122),plt.imshow(label,cmap='gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()

下面是大帅比吉诺比利的效果图,怎么样,是不是有点分割的意思呢~其中,簇类的个数不同,效果图也会不同,这个要自己去试了,一般2到5个就差不多了,我这里是2个,3个的话好难看我就不放了~为了衬托聚类分割效果还可以,我试了一波基于边缘分割的算法。
基于聚类的“图像分割”


基于边缘检测的分割

Canny 边缘检测是一种非常流行的边缘检测算法,主要是求图像的梯度,再限定图像的阈值。 直接上代码吧,原理我就不写了。

    import cv2

import numpy as np

from matplotlib import pyplot as plt

img = cv2.imread(r'D:\jjnbl.jpg')

kernel = np.ones((3, 3), np.float32) / 9

edges = cv2.Canny(img,100,200)

edges2= cv2.dilate(edges, kernel, iterations=1)

plt.subplot(131),plt.imshow(img,cmap = 'gray')

plt.title('Original Image'), plt.xticks([]), plt.yticks([])

plt.subplot(132),plt.imshow(edges,cmap = 'gray')

plt.title('Edge Image'), plt.xticks([]), plt.yticks([])

plt.subplot(133),plt.imshow(edges2,cmap = 'gray')

plt.title('Edge Image with dilate'), plt.xticks([]), plt.yticks([])

plt.show()

基于聚类的“图像分割”

可以看到结果不忍直视啊,基于边缘检测的分割效果是很差的,其中第三张是为了效果更明显一点加了膨胀的效果……


 当然了,这里并不是要用kmeans干什么事情,只是呢,我觉得这个想法真的是挺新的,告诉我们在学习过程中,应该学以致用,学会开阔思路,才能进步,成为一名里厉害的攻城狮啊~