博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一文详解高斯混合模型(GMM)在图像处理中的应用(附代码)
阅读量:5936 次
发布时间:2019-06-19

本文共 5188 字,大约阅读时间需要 17 分钟。

  一. 概述

高斯混合模型(GMM)在图像分割、对象识别、视频分析等方面均有应用,对于任意给定的数据样本集合,根据其分布概率, 可以计算每个样本数据向量的概率分布,从而根据概率分布对其进行分类,但是这些概率分布是混合在一起的,要从中分离出单个样本的概率分布就实现了样本数据聚类,而概率分布描述我们可以使用高斯函数实现,这个就是高斯混合模型-GMM。

一文详解高斯混合模型(GMM)在图像处理中的应用(附代码)

这种方法也称为D-EM即基于距离的期望最大化。

  二. 算法步骤

    1. 初始化变量定义-指定的聚类数目K与数据维度D

    2. 初始化均值、协方差、先验概率分布

    3. 迭代E-M步骤

         - E步计算期望

         - M步更新均值、协方差、先验概率分布

         -检测是否达到停止条件(最大迭代次数与最小误差满足),达到则退出迭代,否则继续E-M步骤

    4. 打印最终分类结果

  三. 代码实现

package com.gloomyfish.image.gmm;    import java.util.ArrayList;  import java.util.Arrays;  import java.util.List;    /**  *   * @author gloomy fish  *  */  public class GMMProcessor {      public final static double MIN_VAR = 1E-10;      public static double[] samples = new double[]{10, 9, 4, 23, 13, 16, 5, 90, 100, 80, 55, 67, 8, 93, 47, 86, 3};      private int dimNum;      private int mixNum;      private double[] weights;      private double[][] m_means;      private double[][] m_vars;      private double[] m_minVars;        /***      *       * @param m_dimNum - 每个样本数据的维度, 对于图像每个像素点来说是RGB三个向量      * @param m_mixNum - 需要分割为几个部分,即高斯混合模型中高斯模型的个数      */      public GMMProcessor(int m_dimNum, int m_mixNum) {          dimNum = m_dimNum;          mixNum = m_mixNum;          weights = new double[mixNum];          m_means = new double[mixNum][dimNum];          m_vars = new double[mixNum][dimNum];          m_minVars = new double[dimNum];      }            /***      * data - 需要处理的数据      * @param data      */      public void process(double[] data) {          int m_maxIterNum = 100;          double err = 0.001;                    boolean loop = true;          double iterNum = 0;          double lastL = 0;          double currL = 0;          int unchanged = 0;                    initParameters(data);                    int size = data.length;          double[] x = new double[dimNum];          double[][] next_means = new double[mixNum][dimNum];          double[] next_weights = new double[mixNum];          double[][] next_vars = new double[mixNum][dimNum];          List
cList = new ArrayList
(); while(loop) { Arrays.fill(next_weights, 0); cList.clear(); for(int i=0; i
1E-20) ? Math.log10(p) : -20; } currL /= size; // Re-estimation: generate new weight, means and variances. for (int j = 0; j < mixNum; j++) { weights[j] = next_weights[j] / size; if (weights[j] > 0) { for (int d = 0; d < dimNum; d++) { m_means[j][d] = next_means[j][d] / next_weights[j]; m_vars[j][d] = next_vars[j][d] / next_weights[j] - m_means[j][d] * m_means[j][d]; if (m_vars[j][d] < m_minVars[d]) { m_vars[j][d] = m_minVars[d]; } } } } // Terminal conditions iterNum++; if (Math.abs(currL - lastL) < err * Math.abs(lastL)) { unchanged++; } if (iterNum >= m_maxIterNum || unchanged >= 3) { loop = false; } } // print result System.out.println("=================最终结果================="); for(int i=0; i
max) { max = v; types[k] = i; } } } double[] counts = new double[mixNum]; for(int i=0; i
0) { for (int d = 0; d < dimNum; d++) { m_vars[i][d] = m_vars[i][d] / counts[i]; // A minimum variance for each dimension is required. if (m_vars[i][d] < m_minVars[d]) { m_vars[i][d] = m_minVars[d]; } } } } System.out.println("=================初始化================="); for(int i=0; i
PDF * @param x - 表示采样数据点向量 * @param j - 表示对对应的第J个分类的概率密度分布 * @return - 返回概率密度分布可能性值 */ public double getProbability(double[] x, int j) { double p = 1; for (int d = 0; d < dimNum; d++) { p *= 1 / Math.sqrt(2 * 3.14159 * m_vars[j][d]); p *= Math.exp(-0.5 * (x[d] - m_means[j][d]) * (x[d] - m_means[j][d]) / m_vars[j][d]); } return p; } public static void main(String[] args) { GMMProcessor filter = new GMMProcessor(1, 2); filter.process(samples); } }

结构类DataNode

package com.gloomyfish.image.gmm;    public class DataNode {      public int cindex; // cluster      public int index;      public double[] value;            public DataNode(double[] v) {          this.value = v;          cindex = -1;          index = -1;      }  }

  四. 结果

一文详解高斯混合模型(GMM)在图像处理中的应用(附代码)

这里初始中心均值的方法我是通过随机数来实现,GMM算法运行结果跟初始化有很大关系,常见初始化中心点的方法是通过K-Means来计算出中心点。大家可以尝试修改代码基于K-Means初始化参数,我之所以选择随机参数初始,主要是为了省事!

====================================分割线================================
本文作者:AI研习社
本文转自雷锋网禁止二次转载,
你可能感兴趣的文章
这么说吧,Lucene很简单,其实就是个框架,用于全文检索用的
查看>>
聊聊storm trident的state
查看>>
JB的Python之旅-爬虫篇-新浪微博内容爬取
查看>>
如何把 Java Web 应用放在 docker 容器中运行
查看>>
Xcode的Refactor使用
查看>>
webpack配置historyApiFallback的坑
查看>>
浅谈Javascript中的作用域链
查看>>
PopupMenu
查看>>
自己动手做一个IM框架(二)
查看>>
Javascript 模块化指北
查看>>
MarkDown 的常用高阶教程
查看>>
利用File,Drop&Drag,XHR2实现图片拖拽上传
查看>>
如何用 SpringBoot 优雅的写代码
查看>>
Jerry 2017年的五一小长假:8种经典排序算法的ABAP实现
查看>>
Aapt.exe finished with non-zero exit value 1
查看>>
关于vuex购物车实现的原理
查看>>
Android 自定义 View 实战之 PuzzleView
查看>>
js 数组排序
查看>>
从零开始学前端动画 —— 简单的特效登录
查看>>
如何更愉快地使用rem —— 别说你懂CSS相对单位
查看>>