最大熵阈值分割法和OTSU算法类似,假设将图像分为背景和前景两个部分。熵代表信息量,图像信息量越大,熵就越大,最大熵算法就是找出一个最佳阈值使得背景与前景两个部分熵之和最大。

基本原理

频率和概率

直方图每个矩形框的数值描述的是图像中相应灰度值的频率。因此,可以说直方图是一种离散的频率分布。给定一个大小为M*N的图像I,直方图中所有矩形框所代表的数值之和,即为图像中的像素数量,即:
相对应的归一化直方图表示为:

0<=i<K 通常被解释为一个随机过程的概率分布或概率密度函数,表示的是图像中像素灰度值为i所出现的概率。i的累积概率值为1,即概率分布p必须满足以下关系:

与累积概率所所对应的累积直方图H是一个离散的分布函数P(),(通常也称为累积分布函数或cdf):

最大熵阈值分割

熵是信息论中一个重要的概念,这种方法常用于数据压缩领域。熵是一种统计测量方法,用以确定随机数据源中所包含的信息数量。例如,包含有N个像素的图像I,可以解释为包含有N个符号的信息,每一个符号的值都独立获取于有限范围K(e.g.,256)中的不同灰度值。
将数字图像建模为一种随机信号处理,意味着必须知道图像灰度中每一个灰度g所发生的概率,即:

因为所有概率应该事先知道,所以这些概率也称为先验概率。对于K个不同灰度值g=0,…,K-1的概率向量可以表示为:

上述概率向量也称为概率分布或称为概率密度函数(pdf)。实际数字图像处理应用当中,先验的概率通常是不知道的,但是这些概率可以通过在一幅图像或多幅图像中观察对应灰度值所发生的频率,从而估算出其概率。图像概率密度函数p(g)可以通过归一化其对应的直方图获得其概率,即:

最大熵

数字图像中给定一个估算的概率密度函数p(g),数字图像中的熵定义为:

用图像熵进行图像分割

利用图像熵为准则进行图像分割有一定历史了,学者们提出了许多以图像熵为基础进行图像分割的方法。我们介绍一种由Kapuret al提出来,现在仍然使用较广的一种图像熵分割方法。
给定一个特定的阈值q(0<=q<K-1),对于该阈值所分割的两个图像区域C0,C1,其估算的概率密度函数可表示为:

为了计算效率,对上面公式进行优化


其中:

示例演示

用OpenCV实现了两个实现方式,MaxEntropyFast是提升了效率的函数。完整代码

#include <iostream>
#include <opencv2/opencv.hpp>const double g_EPSINON = 0.00001;
int MaxEntropy(const cv::Mat& src, cv::Mat& dst, int thresh, int factor)
{const int k_Grayscale = 256;double hist[k_Grayscale] = { 0.0 };int r = src.rows;int c = src.cols;for (int i = 0; i < r; ++i){const uchar* ptr = src.ptr<uchar>(i);   for (int j = 0; j < c; ++j)hist[ptr[j]]++;}double probability = 0.0; //概率double maxEntropy = DBL_MIN; //最大熵int totalpix = r * c;for (int i = 0; i < k_Grayscale; ++i){ //计算背景像素数double backgroundpix = 0;for (int j = 0; j <= i; ++j)backgroundpix += hist[j];//计算背景熵double H0 = 0.0; //背景熵if (backgroundpix > 0){for (int j = 0; j <= i; ++j){probability = hist[j] / backgroundpix;if(probability > g_EPSINON)H0 += -probability * log(probability);}}//计算前景像素数double frontpix = totalpix - backgroundpix;//计算前景熵double H1 = 0.0; //前景熵if (frontpix > 0){for (int k = i + 1; k < k_Grayscale; ++k){probability = hist[k] / frontpix;if (probability > g_EPSINON)H1 += -probability * log(probability);}}//计算最大熵if(H0 + H1 > maxEntropy){maxEntropy = H0 + H1;thresh = i;}}thresh += factor;//阈值处理src.copyTo(dst);for (int i = 0; i < r; ++i){uchar* ptr = dst.ptr<uchar>(i);for (int j = 0; j < c; ++j){if (ptr[j]> thresh)ptr[j] = 255;elseptr[j] = 0;}}return thresh;
}void MakeTable(double *S0, double *S1, double *normalizeHist, int histSize)
{double s0 = 0.0;for (int i = 0; i < histSize; i++){ if(normalizeHist[i] > g_EPSINON)s0 = s0 + normalizeHist[i] * log(normalizeHist[i]);S0[i] = s0;}double s1 = 0.0;for (int i = histSize - 1; i >= 0; i--){S1[i] = s1;if (normalizeHist[i] > g_EPSINON)s1 = s1 + normalizeHist[i] * log(normalizeHist[i]);}
}int MaxEntropyFast(const cv::Mat& src, cv::Mat& dst, int thresh, int factor)
{const int k_GrayScale = 256;int hist[k_GrayScale] = { 0 };int r = src.rows;int c = src.cols;for (int i = 0; i < r; ++i) {const uchar* ptr = src.ptr<uchar>(i);for (int j = 0; j < c; ++j) hist[ptr[j]]++;}double normalizeHist[256] = { 0.0 }, sum = (double)(r * c);for (int i = 0; i < k_GrayScale; i++)normalizeHist[i] = hist[i] / sum ;double S0[256] = { 0 }, S1[256] = { 0 };   MakeTable(S0, S1, normalizeHist, k_GrayScale);double H01 = 0.0, H0 = 0.0, H1 = 0.0, P1 = 0.0, P0 = 0.0, Hmax = DBL_MIN;for (int q = 0; q < k_GrayScale; q++){P0 += normalizeHist[q];if (P0 > g_EPSINON)H0 = -(1.0 * S0[q]) / P0 + log(P0);elseH0 = 0.0;P1 = 1.0 - P0;if (P1 > g_EPSINON)H1 = -(1.0 * S1[q]) / P1 + log(P1);elseH1 = 0.0;H01 = H0 + H1;if (H01 > Hmax){Hmax = H01;thresh = q;}}thresh += factor;//阈值处理src.copyTo(dst);for (int i = 0; i < r; ++i) {uchar* ptr = dst.ptr<uchar>(i);for (int j = 0; j < c; ++j) {if (ptr[j] > thresh)ptr[j] = 255;elseptr[j] = 0;}}return thresh;
}int main()
{cv::Mat src = cv::imread("cameraman.tif");//cv::Mat src = cv::imread("test120.png");if (src.empty()){return -1;}if (src.channels() > 1)cv::cvtColor(src, src, CV_RGB2GRAY);cv::Mat dst, dstOtsu;int thresh = 0;double t2 = (double)cv::getTickCount();thresh = MaxEntropy(src, dst, thresh, 0); //Max_Entropystd::cout << "MaxEntropyThresh=" << thresh << std::endl;t2 = (double)cv::getTickCount() - t2;double time2 = (t2 *1000.) / ((double)cv::getTickFrequency());std::cout << "MaxEntropyProcess=" << time2 << " ms. " << std::endl << std::endl;cv::Mat dstFast;thresh = 0;t2 = (double)cv::getTickCount();thresh = MaxEntropyFast(src, dstFast, thresh, 0); //Max_Entropystd::cout << "MaxEntropyFastThresh=" << thresh << std::endl;t2 = (double)cv::getTickCount() - t2;time2 = (t2 *1000.) / ((double)cv::getTickFrequency());std::cout << "MaxEntropyFastProcess=" << time2 << " ms. " << std::endl << std::endl;double  Otsu = 0;Otsu = cv::threshold(src, dstOtsu, Otsu, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);std::cout << "OtsuThresh=" << Otsu << std::endl;cv::namedWindow("src", CV_WINDOW_NORMAL);cv::imshow("src", src);cv::namedWindow("dst", CV_WINDOW_NORMAL);cv::imshow("dst", dst);cv::namedWindow("dstOtsu", CV_WINDOW_NORMAL);cv::imshow("dstOtsu", dstOtsu);//cv::imwrite("r.jpg",dst);cv::waitKey(0);
}

运行结果

参考资料

  • 最大熵阈值分割法

图像分割之最大熵阈值分割相关推荐

  1. 3.6.1最大熵阈值分割寻找阈值实现图像二值化

    1 #include <opencv2/imgproc/imgproc.hpp> 2 #include <opencv2/core/core.hpp> 3 #include & ...

  2. 【MATLAB教程案例23】基于MATLAB图像分割算法仿真——阈值分割法、Otsu阈值分割法、K均值聚类分割法等

    FPGA教程目录 MATLAB教程目录 目录 1.软件版本 2.通过二值图实现图像分割 3.通过Otsu阈值分割实现图像分割

  3. 图像分割——迭代式阈值分割

    1.算法步骤: (1)预定义两阈值之差dt (2)选定初始阈值T0(一般为图像的平均灰度) (3)用T分割图像为G1.G2两组,G1由灰度值大于T的所有像素组成,G2由灰度值小于等于T的所有像素组成. ...

  4. 【图像算法】七种常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法)...

    图像算法:图像阈值分割 SkySeraph Dec 21st 2010  HQU Email:zgzhaobo@gmail.com    QQ:452728574 Latest Modified Da ...

  5. 图像阈值分割:最大熵法

    图像最大熵阈值分割的原理:使选择的阈值分割图像目标区域.背景区域两部分灰度统计的信息量为最大. 具体描述: 1. 根据信息熵定义,计算原始图像的信息熵H0,选择最大.最小灰度灰度的均值为初始阈值T0: ...

  6. 利用最大熵进行阈值分割从而实现灰度图像的二值化的原理概要及OpenCV代码

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 详细的数学原理目前我也没搞明白,所以只说下原理概 ...

  7. 七种图像阈值分割技术

    一.工具:VC+OpenCV 二.语言:C++ 三.原理 otsu法(最大类间方差法,有时也称之为大津算法)使用的是聚类的思想,把图像的灰度数按灰度级分成2个部分,使得两个部分之间的灰度值差异最大,每 ...

  8. opencv中几种阈值分割

    七种常见阈值分割代码(Otsu.最大熵.迭代法.自适应阀值.手动.迭代法.基本全局阈值法) 一.工具:VC+OpenCV 二.语言:C++ 三.原理 otsu法(最大类间方差法,有时也称之为大津算法) ...

  9. 红外目标图像中阈值分割方法的比较与研究

    红外目标图像中阈值分割方法的比较与研究   摘要:本文主要以红外图像目标检测技术为背景,在图像阈值分割中以最大熵准则及遗传算法为基础,研究了一维最大熵值法(KSW法)及基于遗传算法的KSW熵法单阈值. ...

最新文章

  1. (POST请求中的三种数据请求格式.application/x-www-form-urlencoded和multipart/form-data和application/json)
  2. DMG MORI AKTIENGESELLSCHAFT
  3. MongoDB限制与阈值
  4. 在C 语言中,请一定记得初始化局部变量!
  5. django-元选项
  6. 程序员项目_您如何让程序员加入您的项目?
  7. 多层神经网络中的正则化代价函数解析
  8. 如何使用iMazing将iPhone的数据迁移到iPad
  9. newInstance() 和 new 有什么区别
  10. 面向电缆行业的高级计划与排程(商简SPS)解决方案
  11. edge浏览器,无法继续下载,提示检测到病毒的问题
  12. 山西藏家捐献44幅明清寺观壁画在山西博物院展出(图)
  13. VM ware安装Cent OS系统并配置静态IP
  14. 同为120Hz LTPO屏,OPPO Find X3高性价比更吸睛
  15. 获取两个向量中间位置的点
  16. 计算机内存不足16g内存,win10 16g内存显示内存不足怎么办_win10 16g内存显示可用7.95g如何恢复...
  17. 计算机与化学相关论文,计算机化学化工学论文
  18. ArcGIS教程 - 附录 - ArcGIS快捷键
  19. ubuntu 环境搭建问题归纳
  20. 蓝桥杯十届年号字串 JAVA暴解

热门文章

  1. 矩阵之矩阵乘法(转载)
  2. 基于布谷鸟算法优化的Elman神经网络数据预测-附代码
  3. COMSOL初学2——几何操作
  4. XXL-Job和Elastic-job的区别
  5. elasticjob shutdown 及remove job和server
  6. Python项目(Django框架)天天生鲜在CentOS7.9搭建运行
  7. 使用C# 开发报价系统
  8. winXP2002dns辅服务器未响应,两个方法教你解决DNS服务器无法解析的问题
  9. win10系统下Eplan使用过程中卡死现象
  10. JSP实习实训管理系统myeclipse开发mysql数据库WEB结构java编程