我有一个带有字母和不同颜色形状的图像。我需要在它们上执行kmeans聚类,然后提供两个不同的图像,一个只重新生成的形状,另一个只重新生成Letter颜色。 这是一个原始图像示例以及我需要实现的目标。 Original Image
Shape color regenerated 而另外一个只有白色R。
我已经成功执行了kmeans聚类算法,如何访问标签和聚类idx以重新生成所需的结果?有人可以用示例代码说明。这是代码。提前谢谢。
import numpy as np
import cv2
img = cv2.imread("/home/manohar/Outputs/Targets/m-0.PNG",1)
cv2.imshow("original",img)
Z = img.reshape((-1,3))
# convert to np.float32
Z = np.float32(Z)
# Here we are applying k-means clustering so that the pixels around a colour are consistent and gave same BGR/HSV values
# define criteria, number of clusters(K) and apply kmeans()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
# We are going to cluster with k = 2, because the image will have just two colours ,a white background and the colour of the patch
K = 3
attempts=10
ret,label,center=cv2.kmeans(Z,K,None,criteria,attempts,cv2.KMEANS_PP_CENTERS)
# Now convert back into uint8
#now we have to access the labels to regenerate the clustered image
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img.shape))
#res2 is the result of the frame which has undergone k-means clustering
cv2.imshow("res2",res2)
cv2.waitKey()
cv2.destroyAllWindows()
答案 0 :(得分:1)
好的,所以如果你想把所有分类为" white"的像素改为黑色。通过K-Means
您需要先看到哪个标签对应于" white"类别。您可以通过查看center
(包含生成的k中心)中的白色(255,255,255
)所属的索引来实现此目的,如下所示:
white_index = 0
for b,g,r in center:
#check if it is white
if b == g == r == 255:
#then this is the white category
break
white_index = white_index + 1
请注意,由于k-means
是一种未经过调整的方法,因此您的类别可能不一定完全白色(可能类似于250,249,254
)。所以你在搜索索引时应该考虑这个,也就是你应该寻找更接近白色的颜色。您可以通过应用color distance公式比较颜色来实现此目的。
但是根据我的经验,我相信center
已经以某种方式对得到的中心进行排序(更大的像素值往往首先出现),我注意到更靠近白色的中心有更低的索引(因此白色< strong>可能索引0)。但最好还是检查一下。
现在您知道哪个索引对应于白色,您可以看到哪些像素被归类为label
变量中的像素。为此,有几种方法可以做到这一点,肯定比其他方法更有效,一种方法可能是:
#Copy image to modify it
img_copy = img[:]
#Reshape label to match the original image
new_label = label.reshape(img.shape)
#iterate over new_label, and if the category is white
#paint pixel corresponding to row,col black
row = 0
for i in new_label:
column = 0
for category in i:
if category == white_index:
#paint that pixel black
img_copy[row,column] = [0, 0, 0]
column = column + 1
row = row + 1
#now show edited image
cv2.imshow("Object Removed",img_copy)
cv2.waitKey()
cv2.destroyAllWindows()
编辑:上面的代码获取了检测到的颜色被删除(变黑)的图像。为了获得它的补充,即只有检测到的物体可见的图像,你可以做几件事。一种方法可能是获取img
的副本并使不属于该颜色的像素变黑(不包括category == white_index
),如:
#Obtain another copy of image to modify it
extract = img[:]
#Now do the opposite, iterate over new_label, and if the category is Not white
#paint pixel corresponding to row,col black
row = 0
for i in new_label:
column = 0
for category in i:
if category != white_index:
#paint that pixel black
extract[row,column] = [0, 0, 0]
column = column + 1
row = row + 1
#show or do whatever you want...
获取提取对象的另一种更复杂的方法是获取对象的contour(通过阈值处理并使用cv2.findContours()
),然后应用cv2.boundingRect()
以便获得带有对象的较小剪辑(通过剪切img
与给定的矩形)。您可以检查详细说明的链接。