更新时间:2023-12-02 22:00:28
我不需要弄清楚你的源代码的问题是什么,但这是我的实现:
I didn't have to work out what the problem with your source was, but here's my implementation:
import cv
import sys
if len(sys.argv) < 3:
print 'usage: %s image.png K' % __file__
sys.exit(1)
im = cv.LoadImage(sys.argv[1], cv.CV_LOAD_IMAGE_COLOR)
K = int(sys.argv[2])
#
# Prepare the data for K-means. Represent each pixel in the image as a 3D
# vector (each dimension corresponds to one of B,G,R color channel value).
# Create a column of such vectors -- it will be width*height tall, 1 wide
# and have a total 3 channels.
#
col = cv.Reshape(im, 3, im.width*im.height)
samples = cv.CreateMat(col.height, 1, cv.CV_32FC3)
cv.Scale(col, samples)
labels = cv.CreateMat(col.height, 1, cv.CV_32SC1)
#
# Run 10 iterations of the K-means algorithm.
#
crit = (cv.CV_TERMCRIT_EPS + cv.CV_TERMCRIT_ITER, 10, 1.0)
cv.KMeans2(samples, K, labels, crit)
#
# Determine the center of each cluster. The old OpenCV interface (C-style)
# doesn't seem to provide an easy way to get these directly, so we have to
# calculate them ourselves.
#
clusters = {}
for i in range(col.rows):
b,g,r,_ = cv.Get1D(samples, i)
lbl,_,_,_ = cv.Get1D(labels, i)
try:
clusters[lbl].append((b,g,r))
except KeyError:
clusters[lbl] = [ (b,g,r) ]
means = {}
for c in clusters:
b,g,r = zip(*clusters[c])
means[c] = (sum(b)/len(b), sum(g)/len(g), sum(r)/len(r), _)
#
# Reassign each pixel in the original image to the center of its corresponding
# cluster.
#
for i in range(col.rows):
lbl,_,_,_ = cv.Get1D(labels, i)
cv.Set1D(col, i, means[lbl])
interactive = False
if interactive:
cv.ShowImage(__file__, im)
cv.WaitKey(0)
else:
cv.SaveImage('kmeans-%d.png' % K, im)
以下屏幕截图显示了正在运行的脚本.左边的图像是原始的 128x128 像素图像.其右侧的图像分别是 K 分别等于 2、4、6 和 8 的聚类结果.
The following screenshots show the script in action. The image on the left is the original 128x128 pixel image. Images to its right are the result of clustering with K equal to 2, 4, 6 and 8, respectively.