OpenCV最大熵分割
1. 最大熵是什么?
这里所说的熵是指信息熵,信息熵是来自于信息论的一个词,它是对系统所含信息的一种度量。通俗的讲,系统的不确定性越大,那么系统的信息熵就越大。反之,一个系统如果确定性高(系统越有序),那么整个系统的信息熵就越小。其数学定义表述如下: $$ H = -\int_{\-\infty}^{+\infty}p(x)log[p(x)]dx $$ 上式中,$p(x)$ 表示灰度 $x$ 出现的频率。$H$ 则表示信息熵。
2. 最大熵图像分割
算法描述如下:
- 选取一个阈值$T$,使用该阈值将图像中的所有像素点分成两类,低于阈值$T$的所有像素记为背景B,高于阈值$T$的所有像素记为物体O。
- 计算每个灰度级在B或者O类中所占的概率。 背景:$$\frac{p_{i}}{p_{T}}, i=1,2,…,T$$ 物体: $$\frac{p_{i}}{1 - p_{T}}, i=T+1,T+2,…,L$$ 其中$$p_{T} = \sum_{i=0}^{T}{p(i)}$$。
- 分别计算背景和物体的信息熵 $$H_{B} = -\sum_{i}{\frac{p_{i}}{p_{t}}*log[\frac{p_{i}}{p_{t}}]}, i=1,2,…,T$$ $$H_{O} = -\sum_{i}{\frac{p_{i}}{1-p_{t}}*log[\frac{p_{i}}{1-p_{t}}]}, i=T+1,T+2,…,L$$
- 对图像中的每一个灰度级进行步骤1-3运算,得到使$max{(H_{O}+H_{B})}$时的T值,该值即为最大熵的分割点。
3.在OpenCV平台进行实现
/***************************************************************************************
Function: 最大熵分割算法
Input: Mat 待分割的原图像
Output: 分割后图像
***************************************************************************************/
Mat EntropySeg(Mat src)
{
int tbHist[256] = {0}; //每个像素值个数
int index = 0; //最大熵对应的灰度
double Property = 0.0; //像素所占概率
double maxEntropy = -1.0; //最大熵
double frontEntropy = 0.0; //前景熵
double backEntropy = 0.0; //背景熵
//纳入计算的总像素数
int TotalPixel = 0;
int nCol = src.cols * src.channels(); //每行的像素个数
for (int i = 0; i < src.rows; i++)
{
uchar* pData = src.ptr<uchar>(i);
for (int j = 0; j < nCol; ++j)
{
++TotalPixel;
tbHist[pData[j]] += 1;
}
}
for (int i = 0; i < 256; i++)
{
//计算背景像素数
double backTotal = 0;
for (int j = 0; j < i; j++)
{
backTotal += tbHist[j];
}
//背景熵
for (int j = 0; j < i; j++)
{
if (tbHist[j] != 0)
{
Property = tbHist[j] / backTotal;
backEntropy += -Property * logf((float)Property);
}
}
//前景熵
for (int k = i; k < 256; k++)
{
if (tbHist[k] != 0)
{
Property = tbHist[k] / (TotalPixel - backTotal);
frontEntropy += -Property * logf((float)Property);
}
}
if (frontEntropy + backEntropy > maxEntropy) //得到最大熵
{
maxEntropy = frontEntropy + backEntropy;
index = i;
}
//清空本次计算熵值
frontEntropy = 0.0;
backEntropy = 0.0;
}
Mat dst;
//index += 20;
cv::threshold(src, dst, index, 255, 0); //进行阈值分割
return dst.clone();
}
- 原文作者:Binean
- 原文链接:https://bzhou830.github.io/post/20151130OpenCV%E6%9C%80%E5%A4%A7%E7%86%B5%E5%88%86%E5%89%B2/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。