c++和opencv小知识:高斯混合模型(GMM)分割数据

高斯混合模型(GMM)分割数据

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
using namespace cv::ml;

int main()
{
	
	Mat img = Mat::zeros(500, 500, CV_8UC3);
	RNG rng(1234);
	Scalar colorTab[] = {
		Scalar(0, 0, 255), // 红
		Scalar(0, 255, 0), // 绿
		Scalar(255, 0, 0), // 蓝
		Scalar(0, 255, 255), // 黄
		Scalar(255, 0, 255) // 品红
	};
	//随机定义聚类个数
	int numCluster = 4;
	//数据点数
	int numSample = rng.uniform(5, 1000);
	Mat points(numSample, 2, CV_32FC1); //两列,单通道,因为EM算法输入是单通道的

	//生成随机数
	for (int k = 0; k < numCluster; k++)
	{
		Point center;
		center.x = rng.uniform(0, img.cols);
		center.y = rng.uniform(0, img.rows);
		Mat pointChunk = points.rowRange(k * numSample / numCluster,
			k == numCluster - 1 ? numSample:(k + 1) * numSample / numCluster );
		rng.fill(pointChunk, RNG::NORMAL, Scalar(center.x, center.y), Scalar(img.cols * 0.05, img.rows * 0.05));
	}
	randShuffle(points, 1, &rng);
	//以上可k-means流程一样
	//分割后的标签
	Mat labels;
	Ptr<ml::EM> em_model = ml::EM::create();// 生成 EM 期望最大化模型
	em_model->setClustersNumber(numCluster);		// 设置分类数
	em_model->setCovarianceMatrixType(ml::EM::COV_MAT_SPHERICAL); // 协方差矩阵类型
	em_model->setTermCriteria(TermCriteria(TermCriteria::EPS +
		TermCriteria::COUNT, 100, 0.1));		// 迭代条件,EM训练比KMeans耗时,可能会不收敛,所以迭代次数设大点,
	em_model->trainEM(points, noArray(), labels, noArray());
	// EM训练,获得分类结果,参数labels与KMeans的labels参数意思一样
/*
bool trainEM(InputArray samples, //输入的样本,一个单通道的矩阵。从这个样本中,进行高斯混和模型估计
			OutputArray logLikelihoods=noArray(),//可选项,输出一个矩阵,里面包含每个样本的似然对数值
			OutputArray labels=noArray(),	// 可选项,输出每个样本对应的标注
			OutputArray probs=noArray()		//可选项,输出一个矩阵,里面包含每个隐性变量的后验概率
			);
*/
	//这个函数没有输入参数的初始化值,是因为它会自动执行kmeans算法,将kmeans算法得到的结果作为参数初始化。
	//但它比kmeans还多出一个功能,就是它还能起到训练分类器的作用,用于后续新样本的预测。
	
	//对未知数据做预测
	Mat sample(1, 2, CV_32FC1);
	for (int row = 0; row < img.rows; row++)
	{
		for (int col = 0; col < img.cols; col++)
		{
			sample.at<float>(0) = (float)col;
			sample.at<float>(1) = (float)row;
			Vec2d predict = em_model->predict2(sample, noArray());// 预言,生成64位预测值
			int response = cvRound(predict[1]);// response 就是给出的当前的分类
			circle(img, Point(col, row), 1, colorTab[response] * 0.5, -1);// 以EM预言的分类结果,将img当前点用不同颜色绘制出来
			/*
			Vec2d predict2(InputArray sample,//待测样本
						OutputArray probs		//返回一个Vec2d类型的数,包括两个元素的double向量,
						//第一个元素为样本的似然对数值,第二个元素为最大可能混和分量的索引值。
						)
			*/
		}
	}

	for (int i = 0; i < numSample; i++)//绘制出样本中的数据点属于哪种分类
	{
		Point p(cvRound(points.at<float>(i, 0)), cvRound(points.at<float>(i, 1)));
		circle(img, p, 1, colorTab[labels.at<int>(i)], -1);// 用不同颜色在img上绘制上面随机产生的分类点
	}

	imshow("GMM-EM", img);
	waitKey(0);
	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值