#include
#include
using namespace std;
using namespace cv;
using namespace cv::ml;
int main(int argc, char** argv)
{
Mat src(500, 500, CV_8UC3);
RNG rng;//随机数产生器
const int MAX_CLUSTERS = 5; //最大聚类数目
Scalar color[] =
{
Scalar(0,0,255),
Scalar(0,255,0),
Scalar(255,0,0),
Scalar(0,255,255),
Scalar(255,0,255),
};
//分类
int clusterCount = rng.uniform(2, MAX_CLUSTERS);
cout << "number of clusters聚类数目 :" << clusterCount << endl;
int sampleCount = rng.uniform(5, 1001);
cout << "number of sampleCount采样点数目 :" << sampleCount << endl;
Mat points(sampleCount, 2, CV_32FC1);//存放样本点//2维
//Mat centers(clusterCount, 1, points.type());//用来存储聚类后的中心点
Mat labels;//标注
// 生成随机数
for (int i = 0; i < clusterCount; i++)
{
Point center;//均匀随机产生初始化聚类中心
center.x = rng.uniform(0, src.cols);
center.y = rng.uniform(0, src.rows);
Mat pointChunk = points.rowRange(i * sampleCount / clusterCount,
i == clusterCount - 1 ? sampleCount : (i + 1)*sampleCount / clusterCount);
rng.fill(pointChunk, RNG::NORMAL, Scalar(center.x, center.y), Scalar(src.cols*0.05, src.rows*0.05));
}
randShuffle(points, 1, &rng);//随机打乱points里面的样本点
//GMM高斯混合模型
Ptr em_model = EM::create(); //ml库中机器学习算法
em_model->setClustersNumber(clusterCount);//聚成clusterCount类
em_model->setCovarianceMatrixType(EM::COV_MAT_SPHERICAL);//设置协方差矩阵类型
em_model->setTermCriteria(TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 100, 0.1));//指定要运行算法的最大迭代次数
//训练分类器
em_model->trainEM(points, //samples输入的样本,一个单通道的矩阵。从这个样本中,进行高斯混和模型估计。
noArray(), //可选项,输出一个矩阵,里面包含每个样本的似然对数值。
labels,//可选项,输出每个样本对应的标注。
noArray());//可选项,输出一个矩阵,里面包含每个隐性变量的后验概率
//对每个坐标点进行分类,并根据类别用不同的颜色画出
Mat sample(1, 2, CV_32FC1);
for (int row = 0; row < src.rows; row++)
{
for (int col = 0; col < src.cols; col++)
{
sample.at(0) = (float)col;
sample.at(1) = (float)row;
//predict2返回的是double值,用cvRound进行四舍五入得到整型
//此处返回的是两个值Vec2d,取第二个值作为样本标注
//https://blog.csdn.net/qq_30815237/article/details/86353405
int response = cvRound(em_model->predict2(sample, noArray())[1]);
Scalar c = color[response];//为不同类别设定颜色
circle(src, Point(col, row), 1, c*0.75, -1);
}
}
//画出样本点
for (int i = 0; i < sampleCount; i++)
{
Point p(cvRound(points.at(i, 0)), points.at(i, 1));
circle(src, p, 1, color[labels.at(i)], -1);
}
imshow("高斯混合模型EM", src);
waitKey(0);
return 0;
}