如何使用Python或OpenCV根据局部特征或全局特征自动将数据集图像聚类成不同的组?

3
我有一组图像数据,想要根据内容将它们分成不同的组。目前为止,我尝试找到图像的中位数,并尝试基于中位数值将它们分成不同的聚类。但是,我该如何做才能将我的图像聚类分组呢?我在谷歌上搜索了很多聚类相关的内容,但是大多数结果都是基于颜色而不是图像内容进行聚类。请问是否有人可以提供我有关这方面信息的答案?我是否可以自动地使用中位数或其他技术来对数据集进行聚类分组呢?
from PIL import Image
import numpy as np
import os
Median=[]
k=[]
def get_imlist(path):       
    return [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]

path='D:/Images/dataset'
imlist= get_imlist(path)
for file in imlist:
    head,tail=os.path.split(file)
    im=np.array(Image.open(file).convert('L'))
    m=np.median(im)
    M=[m,tail]
    print '.'
    Median.append(M)
Results=sorted(Median, key=lambda median: median[0])
print Results

一个相关的搜索词是“基于内容的图像检索”。这基本上就是你要做的事情,而且它太广泛了,不适合在StackOverflow上提问。 - Aurelius
1个回答

1

k-means是一种常见的聚类方法,可在OpenCV http://docs.opencv.org/modules/core/doc/clustering.html中使用。

在进行聚类之前,建议使用比完整的n*m像素集更少维数的表示。这有两个主要原因:对噪声的鲁棒性和聚类过程计算成本的降低。所选择的表示法可能对聚类的质量产生重要影响,这将在很大程度上取决于应用程序。我目前最喜欢的是GIST描述符(c++:http://lear.inrialpes.fr/software, matlab: http://people.csail.mit.edu/torralba/code/spatialenvelope/),但这不在OpenCV中。因此,在这里我将使用灰度直方图,从而将维数从m*n减少到b = bin的数量。

假设一个名为frames的灰度级输入图像向量。

    //set up histogram 
int histSize = 128;
float range[] = { 0, histSize } ;
const float* histRange = { range };
bool uniform = true; bool accumulate = false;
Mat_<float> dataHists;


cv::Mat grayImg;
Mat hist_i;
for(int i=0; i <frames.size(); i++)
{
    grayImg =frames[i];

    //histogram gray image
    calcHist( &grayImg, 1, 0, Mat(), hist_i, 1, &histSize, &histRange, uniform, accumulate );
    normalize(hist_i, hist_i, 0, hist_i.rows, NORM_MINMAX, -1, Mat() );

    //transpose for feature vector
    hist_i = hist_i.t();

    //add to feature vectors for k-means
    dataHists.push_back(cv::Mat(hist_i));

}

//k-means
int k = 100;
cv::Mat bestLabels;
cv::kmeans(dataHists,k,bestLabels,TermCriteria(),3,KMEANS_PP_CENTERS);

//have a look
vector<cv::Mat> clusterViz(bestLabels.rows);
for(int i=0;i<bestLabels.rows; i++)
{
    clusterViz[bestLabels.at<int>(i)].push_back(cv::Mat(frames[bestLabels.at<int>(i)]));
}

namedWindow("clusters", WINDOW_NORMAL );
for(int i=0;i<clusterViz.size(); i++)
{
    cv::imshow("clusters",clusterViz[i]);
    cv::waitKey();
}

希望这能帮到你。

@Aurelius- 我已经完成了CBIR,现在我需要通过聚类算法自动将我的数据集分成不同的组,以便我可以将其用于分类过程。 - Jonas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接