// Hand01.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp> // Gaussian Blur
#include <opencv2/ml/ml.hpp>
#include <opencv2/contrib/contrib.hpp>
using namespace cv;
using namespace std;
int main()
{
const int MAX_CLUSTERS = 5;
Scalar colorTab[] = //因为最多只有5类,所以最多也就给5个颜色
{
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); //随机数产生器
for (;;)
{
int k, clusterCount = rng.uniform(2, MAX_CLUSTERS + 1);
int i, sampleCount = rng.uniform(1, 1001);
Mat points(sampleCount, 1, CV_32FC2), labels; //产生的样本数,实际上为2通道的列向量,元素类型为Point2f
clusterCount = MIN(clusterCount, sampleCount);
Mat centers(clusterCount, 1, points.type()); //用来存储聚类后的中心点
/* generate random sample from multigaussian distribution */
for (k = 0; k < clusterCount; k++) //产生随机数
{
Point center;
center.x = rng.uniform(0, img.cols);
center.y = rng.uniform(0, img.rows);
Mat pointChunk = points.rowRange(k*sampleCount / clusterCount,
k == clusterCount - 1 ? sampleCount :
(k + 1)*sampleCount / clusterCount); //最后一个类的样本数不一定是平分的,
//剩下的一份都给最后一类
//每一类都是同样的方差,只是均值不同而已
rng.fill(pointChunk, CV_RAND_NORMAL, Scalar(center.x, center.y), Scalar(img.cols*0.05, img.rows*0.05));
}
randShuffle(points, 1, &rng); //因为要聚类,所以先随机打乱points里面的点,注意points和pointChunk是共用数据的。
kmeans(points, clusterCount, labels,
TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0),
10, KMEANS_PP_CENTERS, centers); //聚类3次,取结果最好的那次,聚类的初始化采用PP特定的随机算法。
img = Scalar::all(0);
for (i = 0; i < sampleCount; i++)
{
int clusterIdx = labels.at<int>(i);
Point ipt = points.at<Point2f>(i);
circle(img, ipt, 2, colorTab[clusterIdx], CV_FILLED, CV_AA);
}
imshow("clusters", img);
char key = (char)waitKey(); //无限等待
if (key == 27 || key == 'q' || key == 'Q') // 'ESC'
break;
}
return 0;
}
const int MAX_CLUSTERS = 10;
Vec3b colorTab[] =
{
Vec3b(0, 0, 255),
Vec3b(0, 255, 0),
Vec3b(255, 100, 100),
Vec3b(255, 0, 255),
Vec3b(0, 255, 255),
Vec3b(0, 150, 255),
Vec3b(0, 100, 150),
Vec3b(50, 50, 50)
};
Mat data, labels;
Mat pic = imread("02.jpg");
for (int i = 0; i < pic.rows; i++)
for (int j = 0; j < pic.cols; j++)
{
Vec3b point = pic.at<Vec3b>(i, j);
Mat tmp = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
data.push_back(tmp);
}
//根据浏览图片,确定k=3
kmeans(data, 2, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0),
3, KMEANS_RANDOM_CENTERS);
int n = 0;
//显示聚类结果,不同的类别用不同的颜色显示
for (int i = 0; i < pic.rows; i++)
for (int j = 0; j < pic.cols; j++)
{
int clusterIdx = labels.at<int>(n);
pic.at<Vec3b>(i, j) = colorTab[clusterIdx];
n++;
}
imshow("pic", pic);
waitKey(0);
return 0;