kmeans.cpp
Go to the documentation of this file.
00001 // Software License Agreement (BSD License)
00002 // 
00003 //   Copyright (c) 2011, Shulei Zhu <schuleichu@gmail.com>
00004 //   All rights reserved.
00005 // 
00006 //   Redistribution and use in source and binary forms, with or without
00007 //   modification, are permitted provided that the following conditions
00008 //   are met:
00009 // 
00010 //    * Redistributions of source code must retain the above copyright
00011 //      notice, this list of conditions and the following disclaimer.
00012 //    * Redistributions in binary form must reproduce the above
00013 //      copyright notice, this list of conditions and the following
00014 //      disclaimer in the documentation and/or other materials provided
00015 //      with the distribution.
00016 //    * Neither the name of Shulei Zhu nor the names of its
00017 //      contributors may be used to endorse or promote products derived
00018 //      from this software without specific prior written permission.
00019 // 
00020 //   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 //   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 //   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 //   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 //   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 //   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 //   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 //   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 //   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 //   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 //   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 //   POSSIBILITY OF SUCH DAMAGE.
00032 // 
00033 // 
00034 // kmeans.cpp --- 
00035 // File            : kmeans.cpp
00036 // Created: Sa Jun 18 14:05:25 2011 (+0200)
00037 // Author: Shulei Zhu
00038 
00039 // Code:
00040 
00041 #include "opencv/ml.h"
00042 #include "opencv/highgui.h"
00043 using namespace std;
00044 using namespace cv;
00045 
00046 int main( int argc, char** argv )
00047 {
00048   cv::Mat image = cv::imread(argv[1]);
00049   const int MAX_CLUSTERS = 10;
00050   Scalar colorTab[] =
00051       {
00052         Scalar(0, 0, 255),
00053         Scalar(0,255,0),
00054         Scalar(255,100,100),
00055         Scalar(255,0,255),
00056         Scalar(0,255,255),
00057         Scalar(1,55,25),
00058         Scalar(0,255,100),
00059         Scalar(5,9,199),
00060         Scalar(55,255,55),
00061         Scalar(4,25,55)
00062       };      
00063 
00064   Mat imageShow= Mat::zeros(image.rows, image.cols, CV_8UC3);
00065   int sampleCount = image.rows*image.cols;
00066   int clusterCount = MIN(atoi(argv[2]), MAX_CLUSTERS);
00067 
00068   Mat points(sampleCount, 1, CV_32FC3), labelsKmeans;
00069   cv::Mat_<cv::Vec3b>& img = (cv::Mat_<cv::Vec3b>&)image;
00070   cv::Mat_<cv::Vec3b>& imgS = (cv::Mat_<cv::Vec3b>&)imageShow;
00071   
00072   double *pPtr;
00073   for (int i = 0 ; i < image.rows; ++i)
00074   {
00075     for (int j = 0; j < image.cols; ++j)
00076     {
00077       pPtr = points.ptr<double>(i*image.cols + j);
00078       pPtr[0] = img(i,j)[0];
00079       pPtr[1] = img(i,j)[1];
00080       pPtr[2] = img(i,j)[2];
00081     }
00082   }
00083   
00084   clusterCount = MIN(clusterCount, sampleCount);
00085   Mat centers(clusterCount, 1, points.type());
00086         
00087   kmeans(points, clusterCount, labelsKmeans, TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0), 3, KMEANS_PP_CENTERS, &centers);
00088 
00089   CvEM em_model;
00090   CvEMParams params;
00091   CvMat *samples = cvCreateMat( sampleCount, 3, CV_32FC1 );
00092 
00093   int step = samples->step/sizeof(CV_32F);
00094 
00095   float *ptr = samples->data.fl;
00096   for (int i = 0; i < sampleCount; ++i)
00097   {
00098     (ptr+i*step)[0] = points.ptr<double>(i)[0];
00099     (ptr+i*step)[1] = points.ptr<double>(i)[1];
00100     (ptr+i*step)[2] = points.ptr<double>(i)[2];
00101   }
00102 
00103   
00104   CvMat labelsMat = labelsKmeans;
00105   CvMat *labels = &labelsMat;
00106   
00107   CvMat *initMeans = cvCreateMat(clusterCount,3, CV_64FC1);
00108   cvZero(initMeans);
00109   double *mptr = initMeans->data.db;
00110   int dstep = initMeans->step/sizeof(CV_64F);
00111 
00112   std::vector<int> clusterPoints(clusterCount,0);
00113   for (int i = 0 ; i < sampleCount; ++i)
00114   {
00115     clusterPoints[labelsKmeans.at<int>(i)] += 1;
00116     (mptr+labelsKmeans.at<int>(i)*dstep)[0] += (ptr+i*step)[0];
00117     (mptr+labelsKmeans.at<int>(i)*dstep)[1] += (ptr+i*step)[1];
00118     (mptr+labelsKmeans.at<int>(i)*dstep)[2] += (ptr+i*step)[2];
00119   }
00120   
00121   for (int i = 0; i < clusterCount; ++i)
00122   {
00123     (mptr+i*dstep)[0] /= clusterPoints[i];
00124     (mptr+i*dstep)[1] /= clusterPoints[i];
00125     (mptr+i*dstep)[2] /= clusterPoints[i];
00126   }
00127 
00128   CvMat **clusters = (CvMat**)cvAlloc( clusterCount * sizeof(*clusters));
00129   for (int i ; i < clusterCount; ++i)
00130   {
00131     clusters[i] = cvCreateMat(clusterPoints[i], 3, CV_64FC1);
00132   }
00133 
00134 
00135   CvMat **initCovs = (CvMat**)cvAlloc( clusterCount * sizeof(*initCovs));
00136   for (int i = 0; i < clusterCount; ++i)
00137   {
00138     cvCalcCovarMatrix( , clusterPoints[i], initCovs[i], mptr+i*dstep, CV_COVAR_NORMAL | CV_COVAR_SCALE );
00139   }
00140 
00141   
00142   CvMat *initWeights = cvCreateMat(1, clusterCount, CV_64FC1);
00143   mptr = initWeights->data.db;
00144   for (int i = 0; i < clusterCount; ++i)
00145   {
00146     (mptr+i*dstep)[0] = clusterPoints[i]/sampleCount;
00147   }
00148 
00149   CvMat *initProbs = cvCreateMat(sampleCount, clusterCount, CV_64FC1);
00150   cvZero(initProbs);
00151   mptr = initProbs->data.db;
00152   
00153   for (int i = 0; i < sampleCount; ++i)
00154   {
00155     (mptr + i*dstep)[labelsKmeans.at<int>(i)] = 1;
00156   }
00157 
00158   params.covs      = NULL;
00159   params.means     = initMeans;
00160   params.weights   = initWeights;
00161   params.probs     = initProbs;
00162   params.nclusters = clusterCount;
00163   params.cov_mat_type       = CvEM::COV_MAT_SPHERICAL;
00164   params.start_step         = CvEM::START_AUTO_STEP;
00165   params.term_crit.max_iter = 10;
00166   params.term_crit.epsilon  = 0.1;
00167   params.term_crit.type     = CV_TERMCRIT_ITER|CV_TERMCRIT_EPS;
00168 
00169   // cluster the data
00170   em_model.train( samples, 0, params, labels);
00171 
00172 #if 0
00173   // the piece of code shows how to repeatedly optimize the model
00174   // with less-constrained parameters
00175   //(COV_MAT_DIAGONAL instead of COV_MAT_SPHERICAL)
00176   // when the output of the first stage is used as input for the second.
00177   CvEM em_model2;
00178   params.cov_mat_type = CvEM::COV_MAT_DIAGONAL;
00179   params.start_step = CvEM::START_E_STEP;
00180   params.means = em_model.get_means();
00181   params.covs = (const CvMat**)em_model.get_covs();
00182   params.weights = em_model.get_weights();
00183 
00184   em_model2.train( samples, 0, params, labels );
00185   // to use em_model2, replace em_model.predict()
00186   // with em_model2.predict() below
00187 #endif
00188 
00189   for (int i = 0 ; i < image.rows; ++i)
00190   {
00191     for (int j = 0; j < image.cols; ++j)
00192     {
00193       int imgRow = i*image.cols+j;
00194       imgS(i,j)[0] = colorTab[labelsKmeans.at<int>(imgRow)][0];
00195       imgS(i,j)[1] = colorTab[labelsKmeans.at<int>(imgRow)][1];
00196       imgS(i,j)[2] = colorTab[labelsKmeans.at<int>(imgRow)][2];
00197     }
00198   }  
00199   imshow("clusters", imageShow);
00200   imwrite("flowers_kmeans.png", imageShow);
00201   waitKey(0);
00202 
00203   cvReleaseMat( &samples);
00204   cvReleaseMat( &labels );  
00205   return 0;
00206 }


contracting_curve_density_algorithm
Author(s): Shulei Zhu, Dejan Pangercic
autogenerated on Mon Oct 6 2014 10:42:03