OpenCv-C++-03-高斯混合模型GMM

1、与KMeans相比,属于软分类;
2、实现方法--------期望最大化(E-M);
3、停止条件--------收敛或规定次数达到。

OpenCV代码实现:

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace cv;
using namespace cv::ml;
using namespace std;

int main(int argc, char** argv)
{
	Mat img = Mat::zeros(500, 500, CV_8UC3);  //定义一张500*500的8位3通道图片

	RNG rng(12345);
	Scalar colorTab[] = {    //定义颜色数组
		Scalar(0,0,255),
		Scalar(255,0,255),
		Scalar(0,255,0),
		Scalar(255,0,0),
		Scalar(0,255,255),
	};
	int numCluster = rng.uniform(2, 5);  //4个分类
	printf("number of cluster:%d\n", numCluster);  //打印4个分类
	cout << "----------------------------------------" << endl;
	int sampleCount = rng.uniform(1, 1000); //1000个随机点
	Mat points(sampleCount, 2, CV_32FC1);

	Mat labels;
	Mat centers;

	//产生多高斯部分的随机采样点
	for (int k = 0; k < numCluster; k++)
	{
		Point center;
		center.x = rng.uniform(0, img.cols);
		center.y = rng.uniform(0, img.rows);

		cout << "x=" << center.x << "  " << "y=" << center.y << endl;
		Mat pointChunk = points.rowRange(k*sampleCount / numCluster,
			k == numCluster - 1 ?
			sampleCount : (k + 1)*sampleCount / numCluster); //定义随机散点
		//rng.fill函数,会以center点为中心,产生高斯分布的随机点(位置点),并把位置点保存在矩阵pointChunk中。
		rng.fill(pointChunk, RNG::NORMAL, Scalar(center.x, center.y), Scalar(img.cols*0.05, img.rows*0.05));
	}
	randShuffle(points, 1, &rng);//打乱points中值,第二个参数表示随机交换元素的数量的缩放因子,总的交换次数dst.rows*dst.cols*iterFactor,第三个参数是个随机发生器,决定选哪两个元素交换。
	Ptr<EM>em_model = EM::create();
	em_model->setClustersNumber(numCluster);
	em_model->setCovarianceMatrixType(EM::COV_MAT_SPHERICAL);
	em_model->setTermCriteria(TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 100, 0.1));
	em_model->trainEM(points, noArray(), labels, noArray());

	//--------------------------
	//分类
	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;
			int response = cvRound(em_model->predict2(sample, noArray())[1]); //cvRound 返回跟参数最接近的整数值
			Scalar c = colorTab[response];
			circle(img, Point(col, row), 1, c*0.75, -1);
		}

	}
	//绘制分类的点
	for (int i = 0; i < sampleCount; 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);
	}
	imshow("final result", img);
	waitKey(0);
	return 0;
}


运行结果:
在这里插入图片描述

基于图像分割的GMM:

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace cv;
using namespace cv::ml;
using namespace std;

int main(int argc, char* argv)
{
	Mat src = imread("F:/test/toux.jpg",1);
	if (src.empty())
	{
		cout << "图像文件未找到!" << endl;
		return -1;
	}
	imshow("input image", src);
	const Scalar colors[] = {
	Scalar(255, 0, 0),
	Scalar(0, 255, 0),
	Scalar(0, 0, 255),
	Scalar(255, 255, 0)
	};
	int clustersNumber = 3;
	int width = src.cols;
	int height = src.rows;
	int channel = src.channels();
	int all_samples = width * height; //所有的样本点总数
	Mat points(all_samples,channel, CV_64FC1);
	Mat labels;
	Mat result = Mat::zeros(src.size(), CV_8UC3);
	// 图像RGB像素数据转换为样本数据 
	int index = 0;
	for (int row = 0; row < src.rows; row++)
	{
		for (int col = 0; col < src.cols; col++)
		{
			index = row * width + col;
			Vec3b bgr = src.at<Vec3b>(row, col);
			points.at<double>(index, 0) = bgr[0];
			points.at<double>(index, 1) = bgr[1];
			points.at<double>(index, 2) = bgr[2];
		}
	}
	//EM 训练
	Ptr<EM>em_model = EM::create();
	em_model->setClustersNumber(clustersNumber);
	em_model->setCovarianceMatrixType(EM::COV_MAT_SPHERICAL);
	em_model->setTermCriteria(TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 100, 0.1));
	em_model->trainEM(points, noArray(), labels, noArray());

	// 对每个像素标记颜色与显示
	Mat sample(channel,1,CV_64FC1);
	int r=0, g=0, b = 0;
	for (int row = 0; row < src.rows; row++)
	{
		for (int col = 0; col < src.cols; col++)
		{
			index = row * width + col;
			b = src.at<Vec3b>(row, col)[0];
			g = src.at<Vec3b>(row, col)[1];
			r = src.at<Vec3b>(row, col)[2];
			sample.at<double>(0) = b;
			sample.at<double>(1) = g;
			sample.at<double>(2) = r;
			int response = cvRound(em_model->predict2(sample, noArray())[1]);

			Scalar c = colors[response];
			result.at<Vec3b>(row, col)[0] = c[0];
			result.at<Vec3b>(row, col)[1] = c[1];
			result.at<Vec3b>(row, col)[2] = c[2];
		
		}
	
	}
	imshow("GMM Result",result);
	waitKey(0);
	return 0;
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值