码迷,mamicode.com
首页 > 其他好文 > 详细

利用cvKMeans2()实现图像聚类(位置+颜色)

时间:2014-07-13 16:35:15      阅读:463      评论:0      收藏:0      [点我收藏+]

标签:kmeans图像聚类图像分割

///利用opencv提供的函数cvKMeans2()实现图像聚类

///////运行环境:VC6.0+opencv1.0

///////////////使用的时候,改变flag的初始值,即可实现对灰度图、彩色图基于色彩的聚类,以及根据位置和色彩对彩色图像聚类。

////////////////最后结果显示的时候请注意pResult 和pResult3

#include "cv.h"

#include "cxcore.h"
#include "highgui.h"
#include "cvaux.h"
#define nClusters 6


int main( )
{
    IplImage* img = cvLoadImage("lena.jpg", 1);//
    IplImage* pResult = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_8U, 1 );
    IplImage* pResult3 = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_8U, 3 );
    if(img==NULL)
        return 0;

    CvScalar color_tab[6];
    color_tab[0] = CV_RGB(255,0,0);///给5中颜色分别赋值
    color_tab[1] = CV_RGB(0,255,0);
    color_tab[2] = CV_RGB(0,0,255);
    color_tab[3] = CV_RGB(255,0,255);
    color_tab[4] = CV_RGB(255,255,0);
    color_tab[5] = CV_RGB(255,0,255);

    CvMat* samples;
    CvMat* clusters;
    int flag=2;///0——灰度   1——彩色  2——位置+彩色
    switch(flag)
    {
    case 0:///Gray
        {
            IplImage* pImg=cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_8U, 1 );
            cvCvtColor(img, pImg, CV_BGR2GRAY);
            assert(pImg != NULL&& pImg->nChannels== 1);
            //创建样本矩阵,CV_32FC1代表位浮点通道(灰度图像)
            samples = cvCreateMat((pImg->width)* (pImg->height),1, CV_32FC1);
            //创建类别标记矩阵,CV_32SF1代表位整型通道
            clusters = cvCreateMat((pImg->width)* (pImg->height),1, CV_32SC1);
            //创建类别中心矩阵
//            CvMat*centers = cvCreateMat(nClusters, 1, CV_32FC1);
            // 将原始图像转换到样本矩阵
            {
                int k = 0;
                CvScalar s;
                for(int i = 0; i < pImg->width; i++)
                {
                    for(int j=0;j < pImg->height; j++)
                    {
                        s.val[0] = (float)cvGet2D(pImg, j, i).val[0];
                        cvSet2D(samples,k++, 0, s);
                    }
                }
            }
            //开始聚类,迭代次,终止误差1.0
            cvKMeans2(samples, nClusters,clusters, cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS,100, 1.0));
            // 无需排序直接输出时
            int sortFlag = 0;
            if (sortFlag == 0)
            {
                int k = 0;
                int val = 0;
                float step = 255 / ((float)nClusters - 1);
                CvScalar s;
                for(int i = 0; i < pImg->width; i++)
                {
                    for(int j = 0;j < pImg->height; j++)
                    {
                        val = (int)clusters->data.i[k++];
                        s.val[0] = 255- val * step;//这个是将不同类别取不同的像素值
                        cvSet2D(pResult,j, i, s);  //将每个像素点赋值
                    }
                }
            }
            printf( "Gray Image\n");
            cvNamedWindow( "src", 1 );
            cvShowImage( "src", pImg );
            //释放图像内存资源
            cvReleaseImage(&pImg);
            break;
        }//case0
    case 1:///RGB
        {
            assert(img != NULL&& pResult != NULL);
            assert(img->nChannels== 3 && pResult->nChannels == 1);
            samples=cvCreateMat((img->width)*(img->height),1,CV_32FC3);//创建样本矩阵,CV_32FC3代表位浮点通道(彩色图像)
            clusters=cvCreateMat((img->width)*(img->height),1,CV_32SC1);//创建类别标记矩阵,CV_32SF1代表位整型通道
            int i,j,k=0;
            for (i=0;i<img->width;i++)
            {
                for(j=0;j<img->height;j++)
                {
                    CvScalar s;
                    //获取图像各个像素点的三通道值(RGB)
                    s.val[0]=(float)cvGet2D(img,j,i).val[0];
                    s.val[1]=(float)cvGet2D(img,j,i).val[1];
                    s.val[2]=(float)cvGet2D(img,j,i).val[2];
                    cvSet2D(samples,k++,0,s);//将像素点三通道的值按顺序排入样本矩阵
                }
            }
            //cvTermCriteria(CV_TERMCRIT_ITER,100,1.0)
            cvKMeans2(samples,nClusters,clusters,cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 100, 1.0 ));//开始聚类,迭代次,终止误差1.0
            k=0;
            int val=0;
            float step=255/(nClusters-1);
            for (i=0;i<img->width;i++)
            {
                for(j=0;j<img->height;j++)
                {
                    val=(int)clusters->data.i[k++];
                    CvScalar s;
                    s.val[0]=255-val*step;//这个是将不同类别取不同的像素值
                    cvSet2D(pResult3,j,i,color_tab[val]);        //将每个像素点赋值
                }
            }
            printf( "RGB Image\n");
            cvNamedWindow( "src", 1 );
            cvShowImage( "src", img );
            break;
        }//case1
        case 2:///Position+RGB
        {
            assert(img != NULL&& pResult != NULL);
            assert(img->nChannels== 3 && pResult->nChannels == 1);
            samples=cvCreateMat((img->width)*(img->height),5,CV_32FC1);//创建样本矩阵,CV_32FC3代表位浮点通道(彩色图像)
            clusters=cvCreateMat((img->width)*(img->height),1,CV_32SC1);//创建类别标记矩阵,CV_32SF1代表位整型通道
            int i=0,j,k=0;
            
            int x,y;
            float *data = samples->data.fl;
            int matcol  = samples->cols;
            int step1    = samples->step/sizeof(float);

            for (x=0;x<img->width;x++)
            {
                for(y=0;y<img->height;y++)
                {
//                    CvScalar s;
                    //获取图像各个像素点的三通道值(RGB)
//                    s.val[0]=(float)cvGet2D(img,y,x).val[0];
//                    s.val[1]=(float)cvGet2D(img,y,x).val[1];
//                    s.val[2]=(float)cvGet2D(img,y,x).val[2];
//                    cvSet2D(samples,k++,0,s);//将像素点三通道的值按顺序排入样本矩阵
                    data[i*matcol+0] = (float)x;
                    data[i*matcol+1] = (float)y;
                    data[i*matcol+2] = (float)cvGet2D(img,y,x).val[0];///cvGet2D(img,j,i).val[0];
                    data[i*matcol+3] = (float)cvGet2D(img,y,x).val[1];
                    data[i*matcol+4] = (float)cvGet2D(img,y,x).val[2];
                    i++;
                }
            }
            //cvTermCriteria(CV_TERMCRIT_ITER,100,1.0)
            cvKMeans2(samples,nClusters,clusters,cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 100, 1.0 ));//开始聚类,迭代次,终止误差1.0
            k=0;
            int val=0;
            float step=255/(nClusters-1);
            for (i=0;i<img->width;i++)
            {
                for(j=0;j<img->height;j++)
                {
                    val=(int)clusters->data.i[k++];
                    CvScalar s;
                    s.val[0]=255-val*step;//这个是将不同类别取不同的像素值
                    cvSet2D(pResult,j,i,s);        //将每个像素点赋值
                }
            }
            printf( "Positon+RGB Result\n");
            cvNamedWindow( "src", 1 );
            cvShowImage( "src", img );
            break;
        }//case2
    }//switch
    cvSaveImage("kmeansResult.jpg",pResult); //存储结果
    cvNamedWindow( "result", 1 );cvMoveWindow("result",600,50);
    cvShowImage( "result", pResult );
    cvWaitKey(0);

    //释放矩阵内存资源
    cvReleaseMat(&samples);
    cvReleaseMat(&clusters);
    //释放图像内存资源
    cvReleaseImage( &img);
    cvReleaseImage( &pResult);
    cvReleaseImage( &pResult3);
    //释放窗口内存资源
    cvDestroyWindow("src");
    cvDestroyWindow("result");

    return 1;

}

【致谢】http://blog.csdn.net/xidianzhimeng/article/details/10391603

利用cvKMeans2()实现图像聚类(位置+颜色),布布扣,bubuko.com

利用cvKMeans2()实现图像聚类(位置+颜色)

标签:kmeans图像聚类图像分割

原文地址:http://blog.csdn.net/zhengtu009/article/details/37727439

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!