圖像分割系列的博客陸陸續續寫了好幾篇了,這次繼續寫寫利用最大熵模型來進行圖像的閾值分割。如果對其他相關博客感興趣可進入下面的鏈接查看:
1. OpenCV - 區域生長算法
2. OpenCV - 均值迭代分割
3. OpenCV - 最大間方差(OTUS)分割
4. OpenCV - 最大熵分割
1. 最大熵是什麼?
這裏所說的熵是指信息熵,信息熵是來自於信息論的一個詞,它是對系統所含信息的一種度量。通俗的講,系統的不確定性越大,那麼系統的信息熵就越大。反之,一個系統如果確定性高(系統越有序),那麼整個系統的信息熵就越小。其數學定義表述如下:
上式中,p(x) 表示灰度 x 出現的頻率。H 則表示信息熵。
2. 最大熵圖像分割
算法描述如下:
1. 選取一個閾值T,使用該閾值將圖像中的所有像素點分成兩類,低於閾值T的所有像素記爲背景B,高於閾值T的所有像素記爲物體O。
2. 計算每個灰度級在B或者O類中所佔的概率。
背景:
物體:
其中
3. 分別計算背景和物體的信息熵
4. 對圖像中的每一個灰度級進行步驟1-3運算,得到使max(HO+HB)時的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();
}
原文地址:http://blog.csdn.net/robin__chou/article/details/53931442