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

高斯混合模型(GMM)分割图像

在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat srcImg = imread("C:\\Users\\tudejiang\\Desktop\\简历\\xiao.jpg");
	imshow("srcImg", srcImg);

	Scalar colorsTab[] = {
		Scalar(255, 0, 0),
		Scalar(0, 255, 0),
		Scalar(0, 0, 255),
		Scalar(255, 255, 0)
	};
	int width = srcImg.cols;
	int height = srcImg.rows;
	int dims = srcImg.channels();
	int numCluster = 4;
	int numSample = width * height;

	Mat points(numSample, dims, CV_64FC1);//在EM中数据是64位的
	Mat labels;

	// 图像RGB像素数据转换为样本数据 
	int index = 0;
	for (int row = 0; row < height; row++) // 这里的步骤与KMeans是一样的
	{
		for (int col = 0; col < width; col++)
		{
			index = row * width + col;
			Vec3b bgr = srcImg.at<Vec3b>(row, col);
			points.at<double>(index, 0) = static_cast<int>(bgr[0]);
			points.at<double>(index, 1) = static_cast<int>(bgr[1]);
			points.at<double>(index, 2) = static_cast<int>(bgr[2]);
		}
	}

	double time0 = getTickCount();
	//EM Cluster Train
	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参数意思一样,速度比KMeans要慢很多
	cout << "train time=" << (getTickCount() - time0) / getTickFrequency() << endl; // train time=10425.8  训练所需的时间很长

	// 对每个像素标记颜色与显示
	Mat result_nopredict = Mat::zeros(srcImg.size(), CV_8UC3);
	Mat result_predict = Mat::zeros(srcImg.size(), CV_8UC3);
	Mat sample(dims, 1, CV_64FC1); // 也只能用 CV_64F
	time0 = getTickCount();
	int r = 0, g = 0, b = 0;
	for (int row = 0; row < height; row++)
	{
		for (int col = 0; col < width; col++)
		{
			// 获取训练的分类结果,放到 result_nopredict 中
			index = row * width + col;
			int label = labels.at<int>(index, 0);
			Scalar c = colorsTab[label];
			result_nopredict.at<Vec3b>(row, col)[0] = c[0];
			result_nopredict.at<Vec3b>(row, col)[1] = c[1];
			result_nopredict.at<Vec3b>(row, col)[2] = c[2];

			// 通过预言获得分类结果,因为EM训练用的是src的颜色数据,所以用src的颜色数据做预言,得到的结果与 result_nopredict 是一模一样的
			b = srcImg.at<Vec3b>(row, col)[0];
			g = srcImg.at<Vec3b>(row, col)[1];
			r = srcImg.at<Vec3b>(row, col)[2];
			sample.at<double>(0) = b;
			sample.at<double>(1) = g;
			sample.at<double>(2) = r;
			Vec2d predict = em_model->predict2(sample, noArray());  // 预言,预言的时间是很短的
			int response = cvRound(predict[1]);						// response 就是目标颜色数据在EM训练中预言的分类
			c = colorsTab[response];
			result_predict.at<Vec3b>(row, col)[0] = c[0];
			result_predict.at<Vec3b>(row, col)[1] = c[1];
			result_predict.at<Vec3b>(row, col)[2] = c[2];

		}
	}
	printf("execution time(ms) : %.2f\n", (getTickCount() - time0) / getTickFrequency()); // execution time(ms) : 1600.31
	imshow("EM-Segmentation nopredict", result_nopredict); // 从效果看,KMeans更好些
	imshow("EM-Segmentation predict", result_predict);
	waitKey(0);
	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值