如何从图像中移除背景以有效应用 k-means 聚类

How to remove background from the image to efficently apply k-means clustering

我正在开展一个项目,对叶子中的疾病进行分类。我正在尝试应用 k 均值聚类,以便可以将患病区域聚类在一起,然后我可以从该聚类区域中提取特征。但是,由于背景的原因,我无法正确聚类,因为病变区域与背景聚类。

我的目标是对病变区域进行聚类,然后从病变区域提取特征来训练分类器。

方法 1 - 我尝试在叶子周围画一个轮廓,然后使用 OpenCV 的最小面积矩形函数绘制一个矩形,随后,我可以裁剪但轮廓不够精细,无法去除背景。

代码如下:

lower_green = np.array((60-s,100,50))
upper_green = np.array((60+s,255,255))
name = "Apple_healthy/image_85.jpg"
bgr = cv2.imread(name)
hsv = cv2.cvtColor(bgr, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower_green, upper_green)
mask = cv2.dilate(mask, None, iterations=50)
_, contours, hier =   cv2.findContours(mask.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
mask = cv2.bitwise_not(mask)
cnt = contours[-1]
cv2.drawContours(bgr,[cnt],0,(0,0,255), 2)
cv2.imshow('image', bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()

rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(bgr,[box],0,(0,0,255),2)
cv2.imshow('sad',bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()

方法 2 - 直接对图像应用k表示聚类。但是在这种方法中,我无法将患病区域聚集在一起,因为患病区域与背景聚集在一起。下面是代码:

img = cv2.imread('Apple_black_rot/image_85.jpg')

Z = img.reshape((-1,3))

# convert to np.float32
Z = np.float32(Z)

# define criteria, number of clusters(K) and apply kmeans()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 16
ret,label,center=cv2.kmeans(Z,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)

# Now convert back into uint8, and make original image
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img.shape))

cv2.imshow('res2',res2)
cv2.waitKey(0)
cv2.destroyAllWindows()

原图

病变部位有明显的色调。您可以提取色调分量(来自 HSV 系统)并获得灰度图像,从中分割应该不是问题,除了可能沿着阴影边缘(见图片)。但是阴影也很容易被检测到,你可以中和这个区域。