使用Kmeans的OpenCV颜色分割

时间:2018-10-14 12:59:13

标签: python-2.7 opencv

我正在尝试使用阈值进行细分颜色。但这不是行不通的。我如何在这张照片中分割红色和绿色。

谢谢

this image after using Kmeans

使用Kmeans后的这张图片

enter image description here

使用阈值分割后的这张图片

我的代码

import numpy as np
import cv2

img = cv2.imread('watermelon.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 = 4
ret,label,center=cv2.kmeans(Z,K, 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))
gray = cv2.cvtColor(res2,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

#segmentation
gray = cv2.cvtColor(res2,cv2.COLOR_BGR2GRAY)
ret, threshseg = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

cv2.imwrite('img_CV2_95.jpg',threshseg)
cv2.imwrite('img_CV2_94.jpg',res2)


cv2.imshow('threshseg',threshseg)
cv2.imshow('thresh',thresh)
cv2.imshow('res2',res2)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

2 个答案:

答案 0 :(得分:2)

如果我理解正确,您想将绿色和红色分开吗?如果是这种情况,您可以将图像转换为HSV颜色空间,并使用*a=20 *b=10 cv2.inRange()提取颜色。请注意,代码是使用OpenCV 3和Python 3.5编写的。希望能有所帮助。干杯!

示例代码:

cv2.bitwise_and()

结果:

enter image description here

enter image description here

enter image description here

答案 1 :(得分:1)

我会利用标签数组的优势并将其用于细分。

首先将其调整为与输入图像相同的宽度/高度。

labels = labels.reshape((img.shape[:-1]))

现在,假设您要获取标签为2的所有像素。

mask = cv2.inRange(labels, 2, 2)

只需将其与cv2.bitwise_and配合使用即可遮盖图像的其余部分。

mask = np.dstack([mask]*3) # Make it 3 channel
ex_img = cv2.bitwise_and(img, mask)

这种方法的好处是您不需要对任何颜色范围进行硬编码,因此相同的算法可以在许多不同的图像上工作。


示例代码:

注意:为OpenCV 3.x写。 OpenCV 2.4.x的用户需要适当地更改cv2.kmeans的调用(有关差异,请参阅docs)。

import numpy as np
import cv2

img = cv2.imread('watermelon.jpg')
Z = np.float32(img.reshape((-1,3)))

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 4
_,labels,centers = cv2.kmeans(Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
labels = labels.reshape((img.shape[:-1]))
reduced = np.uint8(centers)[labels]

result = [np.hstack([img, reduced])]
for i, c in enumerate(centers):
    mask = cv2.inRange(labels, i, i)
    mask = np.dstack([mask]*3) # Make it 3 channel
    ex_img = cv2.bitwise_and(img, mask)
    ex_reduced = cv2.bitwise_and(reduced, mask)
    result.append(np.hstack([ex_img, ex_reduced]))

cv2.imwrite('watermelon_out.jpg', np.vstack(result))

示例输出:

Sample Output

不同颜色的示例输出:

Another Sample Output