opencv3中的机器学习算法之:EM算法
不同于其它的机器学习模型,EM算法是一种非监督的学习算法,它的输入数据事先不需要进行标注。相反,该算法从给定的样本集中,能计算出高斯混和参数的最大似然估计。也能得到每个样本对应的标注值,类似于kmeans聚类(输入样本数据,输出样本数据的标注)。实际上,高斯混和模型GMM和kmeans都是EM算法的应用。
在opencv3.0中,EM算法的函数是trainEM,函数原型为:
bool trainEM(InputArray samples, OutputArray logLikelihoods=noArray(),OutputArray labels=noArray(),OutputArray probs=noArray())
四个参数:
samples: 输入的样本,一个单通道的矩阵。从这个样本中,进行高斯混和模型估计。
logLikelihoods: 可选项,输出一个矩阵,里面包含每个样本的似然对数值。
labels: 可选项,输出每个样本对应的标注。
probs: 可选项,输出一个矩阵,里面包含每个隐性变量的后验概率
这个函数没有输入参数的初始化值,是因为它会自动执行kmeans算法,将kmeans算法得到的结果作为参数初始化。
这个trainEM函数实际把E步骤和M步骤都包含进去了,我们也可以对两个步骤分开执行,OPENCV3.0中也提供了分别执行的函数:
bool trainE(InputArray samples, InputArray means0,
InputArray covs0=noArray(),
InputArray weights0=noArray(),
OutputArray logLikelihoods=noArray(),
OutputArray labels=noArray(),
OutputArray probs=noArray())
bool trainM(InputArray samples, InputArray probs0,
OutputArray logLikelihoods=noArray(),
OutputArray labels=noArray(),
OutputArray probs=noArray())
trainEM函数的功能和kmeans差不多,都是实现自动聚类,输出每个样本对应的标注值。但它比kmeans还多出一个功能,就是它还能起到训练分类器的作用,用于后续新样本的预测。 预测函数原型为:
Vec2d predict2(InputArray sample, OutputArray probs) const
sample: 待测样本
probs : 和上面一样,一个可选的输出值,包含每个隐性变量的后验概率
返回一个Vec2d类型的数,包括两个元素的double向量,第一个元素为样本的似然对数值,第二个元素为最大可能混和分量的索引值。
在本文中,我们用两个实例来学习opencv中的EM算法的应用。
一、opencv3.0中自带的例子,既包括聚类trianEM,也包括预测predict2
代码:
#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml; //使用EM算法实现样本的聚类及预测
int main()
{
const int N = ; //分成4类
const int N1 = (int)sqrt((double)N);
//定义四种颜色,每一类用一种颜色表示
const Scalar colors[] =
{
Scalar(, , ), Scalar(, , ),
Scalar(, , ), Scalar(, , )
}; int i, j;
int nsamples = ; //100个样本点
Mat samples(nsamples, , CV_32FC1); //样本矩阵,100行2列,即100个坐标点
Mat img = Mat::zeros(Size(, ), CV_8UC3); //待测数据,每一个坐标点为一个待测数据
samples = samples.reshape(, ); //循环生成四个类别样本数据,共样本100个,每类样本25个
for (i = ; i < N; i++)
{ Mat samples_part = samples.rowRange(i*nsamples / N, (i + )*nsamples / N); //设置均值
Scalar mean(((i%N1) + )*img.rows / (N1 + ),
((i / N1) + )*img.rows / (N1 + ));
//设置标准差
Scalar sigma(, );
randn(samples_part, mean, sigma); //根据均值和标准差,随机生成25个正态分布坐标点作为样本
}
samples = samples.reshape(, );
// 训练分类器
Mat labels; //标注,不需要事先知道
Ptr<EM> em_model = EM::create();
em_model->setClustersNumber(N);
em_model->setCovarianceMatrixType(EM::COV_MAT_SPHERICAL);
em_model->setTermCriteria(TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, , 0.1));
em_model->trainEM(samples, noArray(), labels, noArray()); //对每个坐标点进行分类,并根据类别用不同的颜色画出
Mat sample(, , CV_32FC1);
for (i = ; i < img.rows; i++)
{
for (j = ; j < img.cols; j++)
{
sample.at<float>() = (float)j;
sample.at<float>() = (float)i;
//predict2返回的是double值,用cvRound进行四舍五入得到整型
//此处返回的是两个值Vec2d,取第二个值作为样本标注
int response = cvRound(em_model->predict2(sample, noArray())[]);
Scalar c = colors[response]; //为不同类别设定颜色
circle(img, Point(j, i), , c*0.75, FILLED);
}
} //画出样本点
for (i = ; i < nsamples; i++)
{
Point pt(cvRound(samples.at<float>(i, )), cvRound(samples.at<float>(i, )));
circle(img, pt, , colors[labels.at<int>(i)], FILLED);
} imshow("EM聚类结果", img);
waitKey(); return ;
}
结果:

二、只用trainEM实现自动聚类功能,进行图片中的目标检测
代码:
#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml; int main()
{
const int MAX_CLUSTERS = ;
Vec3b colorTab[] =
{
Vec3b(, , ),
Vec3b(, , ),
Vec3b(, , ),
Vec3b(, , ),
Vec3b(, , )
};
Mat data, labels;
Mat pic = imread("d:/woman.png");
for (int i = ; i < pic.rows; i++)
for (int j = ; j < pic.cols; j++)
{
Vec3b point = pic.at<Vec3b>(i, j);
Mat tmp = (Mat_<float>(, ) << point[], point[], point[]);
data.push_back(tmp);
} int N =; //聚成3类
Ptr<EM> em_model = EM::create();
em_model->setClustersNumber(N);
em_model->setCovarianceMatrixType(EM::COV_MAT_SPHERICAL);
em_model->setTermCriteria(TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, , 0.1));
em_model->trainEM(data, noArray(), labels, noArray()); int n = ;
//显示聚类结果,不同的类别用不同的颜色显示
for (int i = ; i < pic.rows; i++)
for (int j = ; j < pic.cols; j++)
{
int clusterIdx = labels.at<int>(n);
pic.at<Vec3b>(i, j) = colorTab[clusterIdx];
n++;
}
imshow("pic", pic);
waitKey(); return ;
}
测试图片

测试结果:

opencv3中的机器学习算法之:EM算法的更多相关文章
- 在opencv3中的机器学习算法
		
在opencv3.0中,提供了一个ml.cpp的文件,这里面全是机器学习的算法,共提供了这么几种: 1.正态贝叶斯:normal Bayessian classifier 我已在另外一篇博文中介 ...
 - 机器学习优化算法之EM算法
		
EM算法简介 EM算法其实是一类算法的总称.EM算法分为E-Step和M-Step两步.EM算法的应用范围很广,基本机器学习需要迭代优化参数的模型在优化时都可以使用EM算法. EM算法的思想和过程 E ...
 - MM 算法与 EM算法概述
		
1.MM 算法: MM算法是一种迭代优化方法,利用函数的凸性来寻找它们的最大值或最小值. MM表示 “majorize-minimize MM 算法” 或“minorize maximize MM 算 ...
 - 在opencv3中实现机器学习算法之:利用最近邻算法(knn)实现手写数字分类
		
手写数字digits分类,这可是深度学习算法的入门练习.而且还有专门的手写数字MINIST库.opencv提供了一张手写数字图片给我们,先来看看 这是一张密密麻麻的手写数字图:图片大小为1000*20 ...
 - python机器学习笔记:EM算法
		
EM算法也称期望最大化(Expectation-Maximum,简称EM)算法,它是一个基础算法,是很多机器学习领域的基础,比如隐式马尔科夫算法(HMM),LDA主题模型的变分推断算法等等.本文对于E ...
 - Python实现机器学习算法:EM算法
		
''' 数据集:伪造数据集(两个高斯分布混合) 数据集长度:1000 ------------------------------ 运行结果: ---------------------------- ...
 - 【机器学习】K-means聚类算法与EM算法
		
初始目的 将样本分成K个类,其实说白了就是求一个样本例的隐含类别y,然后利用隐含类别将x归类.由于我们事先不知道类别y,那么我们首先可以对每个样例假定一个y吧,但是怎么知道假定的对不对呢?怎样评价假定 ...
 - 【机器学习笔记】EM算法及其应用
		
极大似然估计 考虑一个高斯分布\(p(\mathbf{x}\mid{\theta})\),其中\(\theta=(\mu,\Sigma)\).样本集\(X=\{x_1,...,x_N\}\)中每个样本 ...
 - python大战机器学习——聚类和EM算法
		
注:本文中涉及到的公式一律省略(公式不好敲出来),若想了解公式的具体实现,请参考原著. 1.基本概念 (1)聚类的思想: 将数据集划分为若干个不想交的子集(称为一个簇cluster),每个簇潜在地对应 ...
 
随机推荐
- VMware虚拟机网络环境类型
			
0x01. VMware Ubuntu虚拟机网络环境 ① Bridge桥接模式:虚拟机与物理机的IP同在一个网段:虚拟机独立且地位与物理机相同:虚拟机可直接访问物理机以及物理机相连的外部网络的主机或网 ...
 - WP开发-Toolkit组件 列表采集器(ListPicker)的使用
			
列表采集器ListPicker在作用上与html中的<select/>标签一样 都是提供多选一功能,区别在于ListPicker可以自定义下拉状态和非下拉状态的样式. 1.模板设置 Lis ...
 - 写过的一些Oracle相关的博客
			
Oracle体系结构:http://blog.chinaunix.net/uid/25909722/cid-164523-list-1.html Oracle优化:http://blog.chinau ...
 - 【mysql】关于checkpoint机制
			
一.简介 思考一下这个场景:如果重做日志可以无限地增大,同时缓冲池也足够大,那么是不需要将缓冲池中页的新版本刷新回磁盘.因为当发生宕机时,完全可以通过重做日志来恢复整个数据库系统中的数据到宕机发生的时 ...
 - 基础总结篇之一:Activity生命周期
			
子曰:溫故而知新,可以為師矣.<論語> 学习技术也一样,对于技术文档或者经典的技术书籍来说,指望看一遍就完全掌握,那基本不大可能,所以我们需要经常回过头再仔细研读几遍,以领悟到作者的思想精 ...
 - ASN.1(抽象语法标记)
			
一.简介 ASN.1是一种对分布式计算机系统间交换的数据消息进行抽象描述的规范化语言. 二.教程 http://www.epubit.com.cn/book/onlinechapter/14877
 - volatile 关键字
			
就象大家更熟悉的const一样,volatile是一个类型修饰符(type specifier).它是被设计用来修饰被不同线程访问和修改的变量.如果没有volatile,基本上会导致这样的结果:要么无 ...
 - Rotate Array
			
Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the array ...
 - linux alarm函数解除read write等函数的阻塞
			
看到apue的第十章,说到alarm,pause可以实现sleep,可以让某些一直阻塞的函数超时,例如read,write.代码如下: static void sig_alrm(int signo) ...
 - Sql 随机更新一条数据返回更新数据的ID编号
			
DECLARE @parimaryTable(临时表) Table(prizecode varchar(50)); update top (1) 数据表 set 字段a='数值' ,字段b=‘数值 ...