Kmeans聚类




#include "opencv2/opencv.hpp"
#include <iostream>
#include <string>
using namespace cv;
using namespace std;

//这是Kmeans算法的一个缺点,在聚类之前需要指定类别个数
const int nClusters = 20;

int _tmain(int argc, _TCHAR* argv[])
{
    Mat src;    //相当于IplImage

//     src = imread("fruit.jpg");        //只是另一张图
    src = imread("zombie.jpg");        //cvLoadImage
    imshow("original", src);        //cvShowImage

    blur(src, src, Size(11,11));
    imshow("blurred", src);

    //p是特征矩阵,每行表示一个特征,每个特征对应src中每个像素点的(x,y,r,g,b共5维)
    Mat p = Mat::zeros(src.cols*src.rows, 5, CV_32F);    //初始化全0矩阵
    Mat bestLabels, centers, clustered;
    vector<Mat> bgr;
    cv::split(src, bgr);    //分隔出src的三个通道

    for(int i=0; i<src.cols*src.rows; i++) 
    {
        p.at<float>(i,0) = (i/src.cols) / src.rows;        // p.at<uchar>(y,x) 相当于 p->Imagedata[y *p->widthstep + x], p是8位uchar
        p.at<float>(i,1) = (i%src.cols) / src.cols;        // p.at<float>(y,x) 相当于 p->Imagedata[y *p->widthstep + x], p是32位float
        p.at<float>(i,2) = bgr[0].data[i] / 255.0;
        p.at<float>(i,3) = bgr[1].data[i] / 255.0;
        p.at<float>(i,4) = bgr[2].data[i] / 255.0;
    }

    //计算时间
    double t = (double)cvGetTickCount();

    //kmeans聚类,每个样本的标签保存在bestLabels中
    cv::kmeans(p, nClusters, bestLabels,
        TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0),
        3, KMEANS_PP_CENTERS, centers);

    t = (double)cvGetTickCount() - t;
    float timecost = t/(cvGetTickFrequency()*1000); 

    //给每个类别赋颜色,其值等于每个类第一个元素的值
    Vec3b    colors[nClusters];
    bool    colormask[nClusters]; memset(colormask, 0, nClusters*sizeof(bool));
    int        count = 0;
    for(int i=0; i<src.cols*src.rows; i++) 
    {
        int clusterindex = bestLabels.at<int>(i,0);
        for (int j=0; j<nClusters; j++)
        {
            if(j == clusterindex && colormask[j] == 0)
            {
                int y = i/src.cols;
                int x = i%src.cols;
                colors[j] = src.at<Vec3b>(y,x);
                colormask[j] = 1;
                count++;
                break;
            }
        }
        if(nClusters == count)break;
    }

    //显示聚类结果
    clustered = Mat(src.rows, src.cols, CV_8UC3);
    for(int i=0; i<src.cols*src.rows; i++) {
        int y = i/src.cols;
        int x = i%src.cols;
        int clusterindex = bestLabels.at<int>(i,0);
        clustered.at<Vec3b>(y, x) = colors[clusterindex];
    }

    imshow("clustered", clustered);

    cout<< "time cost = %gms\n"<<timecost ;

    //保存图像
    stringstream s1,s2;
    s1<<timecost;
    s2<<nClusters;
    string name = "n=" + s2.str() + "_timecost=" + s1.str() + ".png";
    imwrite(name, clustered);
    waitKey();
    return 0;
}

你可能感兴趣的:(kmean)