任何一组数据(直方图),都可用多个线性叠加的高斯函数进行逼近拟合。
GMM整体的概率密度函数是由若干个高斯分量的概率密度函数线性叠加而成的,而每一个高斯分量的概率密度函数的积分必然也是1,所以,要想GMM整体的概率密度积分为1,就必须对每一个高斯分量赋予一个其值不大于1的权重,并且权重之和为1。
步骤:
- 先计算所有数据对每个分模型的响应度
- 根据响应度计算每个分模型的参数
- 迭代
#include<opencv2\opencv.hpp>
using namespace cv;
using namespace ml;
int main(int arc, char** argv) {
Mat src = imread("1.jpg");
namedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("input", src);
int width = src.cols;
int height = src.rows;
int dims = src.channels();
int pointsCount = width * height;
Mat points(pointsCount, dims, CV_64FC1);
Mat labels;
Scalar color[] = { Scalar(0,0,255), Scalar(0,255,0), Scalar(255,0,0) };
//将图像转换为数据点
int index = 0;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
index = i * width + j;
points.at<double>(index, 0) = src.at<Vec3b>(i, j)[0];
points.at<double>(index, 1) = src.at<Vec3b>(i, j)[1];
points.at<double>(index, 2) = src.at<Vec3b>(i, j)[2];
}
}
//GMM分割(基于高斯混合模型的期望最大值)
Ptr<EM> em = EM::create();
em->setClustersNumber(3);
em->setCovarianceMatrixType(EM::COV_MAT_SPHERICAL);
em->setTermCriteria(TermCriteria( TermCriteria::COUNT+TermCriteria::EPS, 100, 0.1));
em->trainEM(points, noArray(),labels,noArray());
//将数据点转换为图像并显示
Mat result = Mat::zeros(src.size(), CV_8UC3);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
index = i * width + j;
int label = labels.at<int>(index, 0);
result.at<Vec3b>(i, j)[0] = color[label][0];
result.at<Vec3b>(i, j)[1] = color[label][1];
result.at<Vec3b>(i, j)[2] = color[label][2];
}
}
imshow("output", result);
waitKey(0);
return 0;
}