OpenCVKmeans算法默认使用了Kmeans++选取种子点
//效果:根据半径聚类,并不一定能得到好的结果。 float CBlotGlint::ClusterByR( ) { //根据半径大小聚类,找出合适的类别个数和每一类的个数 std::vector<float> radiuses(this->blobs.size() ); std::vector<std::pair<float,int> > radiusesIdx(this->blobs.size() ); for ( int i=0; i< this->blobs.size(); ++i ){ radiuses[i] =this->blobs[i].diaGlint; radiusesIdx[i].first = radiuses[i]; radiusesIdx[i].second = i; } { using namespace cv; this->blobs[0].diaGlint; const int MAX_CLUSTERS = 5; Scalar colorTab[] = { Scalar(0, 0, 255), Scalar(0,255,0), Scalar(255,100,100), Scalar(255,0,255), Scalar(0,255,255) }; Mat img( 500, 500, CV_8UC3 ); RNG rng( 12345 ); std::vector<std::vector<float> > outC; std::vector<std::vector<std::pair<float,int> > > outCidx; { outC.clear(); int k; int clusterCount = rng.uniform(2, MAX_CLUSTERS+1); int i; int sampleCount =radiuses.size();// rng.uniform(1, 1001); Mat points(sampleCount, 1, CV_32FC1), labels; for ( int i=0; i< sampleCount; ++i ){ points.at<float>(i) = radiuses[i]; } clusterCount = MIN(clusterCount, sampleCount); clusterCount = std::max(clusterCount,3); clusterCount = 3; Mat centers; kmeans(points, clusterCount, labels, TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0), 3, KMEANS_PP_CENTERS, centers); outC.resize( clusterCount ); outCidx.resize( clusterCount ); img = Scalar::all(0); for( i = 0; i < sampleCount; i++ ) { int clusterIdx = labels.at<int>( i ); outC[clusterIdx].push_back( points.at<float>( i ) ); outCidx[clusterIdx].push_back( std::make_pair ( points.at<float>( i ) ,radiusesIdx[i].second ) ); Point ipt = this->blobs[i].centerOfGlint; circle( img, ipt, 2, colorTab[clusterIdx], CV_FILLED, CV_AA ); } cv::imshow("clusters", img); char key = (char)cv::waitKey(1); } return 0; } return 1.0; }
即使如此,每次聚类的效果仍然不一定相同,显示一定的随机性。