2010-10-13 65 views
2

我正在使用v2.1与内置的python接口。 我想从文件中加载图像,将其转换为实验室 并从ab平面获取群集。OpenCV的Python接口中的K-means

我有一个工作的matlab代码,但不知道如何在opencv中做同样的事情。 如何重塑jpeg或png图像并将其提供给kmeans?

感谢

我得到的错误:

OpenCV Error: Assertion failed (labels.isContinuous() && labels.type() == CV_32S && (labels.cols == 1 || labels.rows == 1) && labels.cols + labels.rows - 1 == data.rows) in cvKMeans2, file /build/buildd/opencv-2.1.0/src/cxcore/cxmatrix.cpp, line 1202 
Traceback (most recent call last): 
File "main.py", line 24, in <module> 
(cv.CV_TERMCRIT_EPS + cv.CV_TERMCRIT_ITER, 10, 1.0)) 
cv.error: labels.isContinuous() && labels.type() == CV_32S && (labels.cols == 1 || labels.rows == 1) && labels.cols + labels.rows - 1 == data.rows 

感谢

工作MATLAB代码:

im=imread(fName); 
cform = makecform('srgb2lab'); 
lab_im = applycform(im,cform); 
ab = double(lab_im(:,:,2:3)); 
ab = reshape(ab,nrows*ncols,2); 
nColors = 2; 
[cluster_idx cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean','Replicates',3,'start', 'uniform'); 

中的python-OpenCV的(没有工作)

img = cv.LoadImage("test.jpg") 
clusters = cv.CreateImage((img.width*img.height, 1), img.depth, 1) 
lab_img = cv.CreateImage(cv.GetSize(img), img.depth, 3) 
cv.CvtColor(img, lab_img, cv.CV_RGB2Lab) 

ab_img = cv.CreateImage(cv.GetSize(img), img.depth, 2) 
cv.MixChannels([lab_img], [ab_img], [ 
    (1, 0), 
    (2, 1) 
]) 

cv.Reshape(ab_img, ab_img.channels, ab_img.width*ab_img.height) 
cluster_count = 3 
cv.KMeans2(ab_img, cluster_count, clusters, 
    (cv.CV_TERMCRIT_EPS + cv.CV_TERMCRIT_ITER, 10, 1.0)) 
+0

没怎么工作的呢?如果我可以问。我还没有遇到你的问题,但我即将开始一个类似分析的项目,所以我很好奇你可能会遇到什么问题。 – fish2000 2010-10-16 12:49:24

+0

我使用C工作,但是在Reshape和/或Kmeans2的python实现中存在一个错误。只有当我需要显示它时,我才将所有内容转换为矩阵并返回到图像。簇应该是一个cv.CV_8UC1的矩阵。图像矩阵的深度应该是CV_32FC2。如果您有问题,请询问更多。 – pablo 2010-10-16 13:26:34

回答

6

我没有制定出如何处理你的源问题是,但这里是我的实现:

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。

originalK=2K=4K=6K=8