OPENCV EM算法详解和JAVA实现
来源:互联网 发布:淘宝网什么东西最火 编辑:程序博客网 时间:2024/06/03 23:44
1EM算法是一种迭代算法,主要用于计算后验分布的众数或极大似然估计,广泛地应用于缺损数据、截尾数据、成群数据、带有讨厌参数的数据等所谓不完全数据的统计推断问题。
2EM算法是一种非监督的学习算法,它的输入数据事先不需要进行标注。相反,该算法从给定的样本集中,能计算出高斯混和参数的最大似然估计。也能得到每个样本对应的标注值,类似于kmeans聚类(输入样本数据,输出样本数据的标注)。
3优点:EM算法简单且稳定,迭代能保证观察数据对数后验似然是单调不减的。
缺点:对于大规模数据和多维高斯分布,其总的迭代过程,计算量大,迭代速度易受影响;EM算法的收敛速度,非常依赖初始值的设置,设置不当,计算时的代价是相当大的;EM算法中的M-Step依然是采用求导函数的方法,所以它找到的是极值点,即局部最优解,而不一定是全局最优解。
4EM算法的函数是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算法的应用。
EM算法在CPP里有示例代码,位于,如果安装了.net 或者按我前一篇文章配置了GCC就可以自己编译运行研究,代码位于/openc/\sources/samples/cpp/em.cpp
5这里使用一个哥们写的C++,实现对一个图片颜色分类,图片路径要改一下,下面JAVA和实现与CPP功能一样:
#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 = 5; Vec3b colorTab[] = { Vec3b(0, 0, 255), Vec3b(0, 255, 0), Vec3b(255, 100, 100), Vec3b(255, 0, 255), Vec3b(0, 255, 255) }; Mat data, labels; Mat pic = imread("f:/aa.jpg"); for (int i = 0; i < pic.rows; i++) for (int j = 0; j < pic.cols; j++) { Vec3b point = pic.at<Vec3b>(i, j); Mat tmp = (Mat_<float>(1, 3) << point[0], point[1], point[2]); data.push_back(tmp); } int N =3; //聚成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, 300, 0.1)); em_model->trainEM(data, noArray(), labels, noArray()); int n = 0; //显示聚类结果,不同的类别用不同的颜色显示 for (int i = 0; i < pic.rows; i++) for (int j = 0; j < pic.cols; j++) { int clusterIdx = labels.at<int>(n); pic.at<Vec3b>(i, j) = colorTab[clusterIdx]; n++; } imshow("pic", pic); waitKey(0); return 0;}
同样效果的JAVA代码如下,JAVA的代码比较少,随着opencv在ANDROID平台大放光彩,相信这方面资源会越来越多。
import org.opencv.core.Core;import org.opencv.core.CvType;import org.opencv.core.Mat;import org.opencv.core.Scalar;import org.opencv.core.TermCriteria;import org.opencv.imgcodecs.Imgcodecs;import org.opencv.ml.EM;public class MyMl {public static void main(String[] args) {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);int MAX_CLUSTERS = 6;Scalar colorTab[] = { new Scalar(0, 0, 255), new Scalar(0, 255, 0), new Scalar(255, 100, 100),new Scalar(255, 0, 255), new Scalar(0, 255, 255), new Scalar(0, 0, 0) };Mat data = new Mat(), labels = new Mat();Mat pic = Imgcodecs.imread("F:/aa.jpg");for (int i = 0; i < pic.rows(); i++)for (int j = 0; j < pic.cols(); j++) {double[] point = pic.get(i, j);Mat tmp = new Mat(1, 3, CvType.CV_32FC1);tmp.put(0, 0, point);data.push_back(tmp);}int N = 3;EM em_model = EM.create();em_model.setClustersNumber(N);em_model.setCovarianceMatrixType(EM.COV_MAT_SPHERICAL);em_model.setTermCriteria(new TermCriteria(TermCriteria.COUNT + TermCriteria.EPS, 300, 0.1));em_model.trainEM(data, new Mat(), labels, new Mat());int n = 0;// 显示聚类结果,不同的类别用不同的颜色显示for (int i = 0; i < pic.rows(); i++)for (int j = 0; j < pic.cols(); j++) {int clusterIdx = (int) labels.get(n, 0)[0];pic.put(i, j, new double[] { colorTab[clusterIdx].val[0], colorTab[clusterIdx].val[1],colorTab[clusterIdx].val[2] });n++;}Imgcodecs.imwrite("F:/a1.png", pic);}}
运行效果,修改int N = 3;可以使用更多的颜色自动标注分类
参考:
http://www.cnblogs.com/denny402/p/5036288.html
http://blog.csdn.net/fennvde007/article/details/17734597
- OPENCV EM算法详解和JAVA实现
- EM算法原理和python简单实现
- OPENCV之EM算法篇
- opencv EM算法 源码解读
- EM算法详解
- EM算法详解
- EM算法原理详解
- EM算法详解
- EM算法原理详解
- EM算法和FA
- k-means和EM算法的Matlab实现
- EM算法和MM算法
- EM算法及OpenCV源码分析
- opencv实现camshift算法,以及代码详解
- GMM的EM算法实现
- GMM的EM算法实现
- EM 算法的 Python 实现
- GMM的EM算法实现
- Quartz基础篇(一)
- 为什么我varchar(20) 可以存放20个汉字
- Activiti之《调试单元测试》
- spark学习-19-Spark的mapPartitions与MapPartitionsWithIndex理解
- shell find 之笔记
- OPENCV EM算法详解和JAVA实现
- Activiti之《BPMN2分析》
- HashMap 和 HashTable 源码学习和面试总结
- 存储过程 SET NOCOUNT { ON | OFF }实用讲解
- Mysql的索引以及使用索引可能失效的场景
- python爬虫学习第三十天
- PCB设计的基本步骤
- 51Nod 1791 合法括号子段(栈+乱搞)
- 【JZOJ5317】【清华集训模拟】func(辗转相除法、找规律)