二值化是圖像分割的一種方法。在二值化圖象的時(shí)候把大于某個(gè)臨界灰度值的像素灰度設(shè)為灰度極大值,把小于這個(gè)值的像素灰度設(shè)為灰度極小值,從而實(shí)現(xiàn)二值化。
根據(jù)閾值選取的不同,二值化的算法分為固定閾值和自適應(yīng)閾值。 比較常用的二值化方法則有:雙峰法、P參數(shù)法、迭代法和OTSU法等。
1、雙峰法
在一些簡(jiǎn)單的圖像中,物體的灰度分布比較有規(guī)律,背景與目標(biāo)在圖像的直方圖各自形成一個(gè)波峰,即區(qū)域與波峰一一對(duì)應(yīng),每?jī)蓚€(gè)波峰之間形成一個(gè)波谷。那么,選擇雙峰之間的波谷所代表的灰度值T作為閾值,即可實(shí)現(xiàn)兩個(gè)區(qū)域的分割。如圖所示

在直方圖中我們可以明顯的看到兩個(gè)山峰狀的圖像分布,山峰的頂點(diǎn)我們記為Hmax1和Hmax2,他們對(duì)應(yīng)的灰度值分別為T1和T2,那么雙峰法圖像分割的思想就是找到圖像兩個(gè)山峰之間的谷地最低值,即在[T1,T2]的灰度范圍內(nèi)尋找閾值T,使其滿足對(duì)應(yīng)的像素?cái)?shù)目最少,表現(xiàn)在圖像上就是高度最低,用T對(duì)圖像進(jìn)行分割或二值化。
2、P參數(shù)法
2.1 原理
所謂P分位法圖像分割,就是在知道圖像中目標(biāo)所占的比率Ratio時(shí),循環(huán)不同的灰度值對(duì)圖像進(jìn)行分割,并計(jì)算對(duì)應(yīng)的目標(biāo)所占的比率,如果該比率與Ratio的差值足夠小,那么該閾值就是所求的最佳分割閾值。
2.2 算法
算法過(guò)程如下:
- 已知目標(biāo)圖像所占比率P;
- 設(shè)定一閾值Th,它將圖像分割為兩部分,目標(biāo)部分A和背景部分B,統(tǒng)計(jì)兩部分所包含的像素?cái)?shù)目分別為Na和Nb;
-
將Th從1-254迭代,每改變一次Th ,計(jì)算一次Na,Nb,根據(jù)Na,Nb計(jì)算目標(biāo)所占的比率P,公式如下:
-
計(jì)算當(dāng)前閾值對(duì)應(yīng)的分割比率與已知比率的差值,若小于某閾值則停止迭代,否則,轉(zhuǎn)至3繼續(xù)進(jìn)行,公式如下:
其中T為某一小數(shù)
3、迭代法
3.1 原理
迭代選擇法是首先猜測(cè)一個(gè)初始閾值,然后再通過(guò)對(duì)圖像的多趟計(jì)算對(duì)閾值進(jìn)行改進(jìn)的過(guò)程。重復(fù)地對(duì)圖像進(jìn)行閾值操作,將圖像分割為對(duì)象類和背景類,然后來(lái)利用每一個(gè)類中的灰階級(jí)別對(duì)閾值進(jìn)行改進(jìn)。
3.2 算法
- 為全局閾值選擇一個(gè)初始估計(jì)值T(圖像的平均灰度)。
- 用T分割圖像。產(chǎn)生兩組像素:G1有灰度值大于T的像素組成,G2有小于等于T像素組成。
- 計(jì)算G1和G2像素的平均灰度值m1和m2;
- 計(jì)算一個(gè)新的閾值:T = (m1 + m2) / 2;
- 重復(fù)步驟2和4,直到連續(xù)迭代中的T值間的差小于一個(gè)預(yù)定義參數(shù)為止。
3.3 代碼
/**
* 迭代法
*
* @param srcImg 灰度圖像
* @param maxIter 最大迭代次數(shù)
*/
+ (int)detechThreshold:(IplImage *)srcImg maxIterat:(int)maxIter{
//圖像信息
int height = srcImg->height;
int width = srcImg->width;
int step = srcImg->widthStep/sizeof(uchar);
uchar *data = (uchar*)srcImg->imageData;
int iDiffRec =0; //使用給定閥值確定的亮區(qū)與暗區(qū)平均灰度差異值, 根據(jù)需要返回
int F[256]={ 0 }; //直方圖數(shù)組
int iTotalGray=0;//灰度值和
int iTotalPixel =0;//像素?cái)?shù)和
Byte bt;//某點(diǎn)的像素值
uchar iThrehold,iNewThrehold;//閥值、新閥值
uchar iMaxGrayValue=0,iMinGrayValue=255;//原圖像中的最大灰度值和最小灰度值
uchar iMeanGrayValue1,iMeanGrayValue2;
//獲取(i,j)的值,存于直方圖數(shù)組F
for(int i=0;i<width;i++){
for(int j=0;j<height;j++){
bt = data[i*step+j];
if(bt<iMinGrayValue)
iMinGrayValue = bt;
if(bt>iMaxGrayValue)
iMaxGrayValue = bt;
F[bt]++;
}
}
iThrehold =0;
iNewThrehold = (iMinGrayValue+iMaxGrayValue)/2;//初始閥值
iDiffRec = iMaxGrayValue - iMinGrayValue;
for(int a=0;(abs(iThrehold-iNewThrehold)>0.5)&&a<maxIter;a++){ //迭代中止條件
iThrehold = iNewThrehold;
//小于當(dāng)前閥值部分的平均灰度值
for(int i=iMinGrayValue;i<iThrehold;i++){
iTotalGray += F[i]*i;//F[]存儲(chǔ)圖像信息
iTotalPixel += F[i];
}
iMeanGrayValue1 = (uchar)(iTotalGray/iTotalPixel);
//大于當(dāng)前閥值部分的平均灰度值
iTotalPixel =0;
iTotalGray =0;
for(int j=iThrehold+1;j<iMaxGrayValue;j++){
iTotalGray += F[j]*j;//F[]存儲(chǔ)圖像信息
iTotalPixel += F[j];
}
iMeanGrayValue2 = (uchar)(iTotalGray/iTotalPixel);
iNewThrehold = (iMeanGrayValue2+iMeanGrayValue1)/2; //新閥值
iDiffRec = abs(iMeanGrayValue2 - iMeanGrayValue1);
}
return iThrehold;
}
4. OTSU法
4.1 原理
最大類間方差法是由日本學(xué)者大津于1979年提出的,是一種自適應(yīng)的閾值確定的方法,又叫大津法,簡(jiǎn)稱OTSU。它是按圖像的灰度特性,將圖像分成背景和目標(biāo)2部分。背景和目標(biāo)之間的類間方差越大,說(shuō)明構(gòu)成圖像的2部分的差別越大,當(dāng)部分目標(biāo)錯(cuò)分為背景或部分背景錯(cuò)分為目標(biāo)都會(huì)導(dǎo)致2部分差別變小。因此,使類間方差最大的分割意味著錯(cuò)分概率最小。對(duì)于圖像I(x,y),前景(即目標(biāo))和背景的分割閾值記作T,屬于前景的像素點(diǎn)數(shù)占整幅圖像的比例記為ω0,其平均灰度μ0;背景像素點(diǎn)數(shù)占整幅圖像的比例為ω1,其平均灰度為μ1。圖像的總平均灰度記為μ,類間方差記為g。
4.2 算法
假設(shè)圖像的背景較暗,并且圖像的大小為M×N,圖像中像素的灰度值小于閾值T的像素個(gè)數(shù)記作N0,像素灰度大于閾值T的像素個(gè)數(shù)記作N1,則有:
ω0=N0/ M×N (1)
ω1=N1/ M×N (2)
N0+N1=M×N (3)
ω0+ω1=1 (4)
μ=ω0μ0+ω1μ1 (5)
g=ω0(μ0-μ)2+ω1(μ1-μ)2 (6)
將式(5)代入式(6),得到等價(jià)公式: g=ω0ω1(μ0-μ1)^2 (7)采用遍歷的方法得到使類間方差最大的閾值T,即為所求。
4.3 代碼實(shí)現(xiàn)
代碼實(shí)現(xiàn)如下:
int OTSU(unsigned char* pGrayImg , int iWidth , int iHeight)
{
if((pGrayImg==0)||(iWidth<=0)||(iHeight<=0))return -1;
int ihist[256];
int thresholdValue=0; // ?–÷μ
int n, n1, n2 ;
double m1, m2, sum, csum, fmax, sb;
int i,j,k;
memset(ihist, 0, sizeof(ihist));
n=iHeight*iWidth;
sum = csum = 0.0;
fmax = -1.0;
n1 = 0;
for(i=0; i < iHeight; i++)
{
for(j=0; j < iWidth; j++)
{
ihist[*pGrayImg]++;
pGrayImg++;
}
}
pGrayImg -= n;
for (k=0; k <= 255; k++)
{
sum += (double) k * (double) ihist[k];
}
for (k=0; k <=255; k++)
{
n1 += ihist[k];
if(n1==0)continue;
n2 = n - n1;
if(n2==0)break;
csum += (double)k *ihist[k];
m1 = csum/n1;
m2 = (sum-csum)/n2;
sb = (double) n1 *(double) n2 *(m1 - m2) * (m1 - m2);
if (sb > fmax)
{
fmax = sb;
thresholdValue = k;
}
}
return(thresholdValue);
}
5、一維最大熵法
5.1 原理
一維最大熵法圖像分割就是利用圖像的灰度分布密度函數(shù)定義圖像的信息熵,通過(guò)優(yōu)化一定的熵準(zhǔn)則得到熵最大時(shí)對(duì)應(yīng)的閾值,從而進(jìn)行圖像分割的方法。
5.2 算法
算法過(guò)程:
- 對(duì)于一幅灰度圖像,灰度范圍為[0,L-1],求取圖像的最小灰度級(jí)min,最大灰度級(jí)max;
-
按照如下熵的公式求取灰度t對(duì)應(yīng)的熵值;
其中,pi表示灰度級(jí)i出現(xiàn)的概率。
- 計(jì)算t從最小灰度min到最大灰度max之間不同灰度級(jí)所對(duì)應(yīng)的熵值E(t),求取E(t)最大時(shí)所對(duì)應(yīng)的灰度級(jí)t,該灰度級(jí)即為所求的閾值Th。
5.3 代碼
代碼實(shí)現(xiàn)如下:
// 計(jì)算當(dāng)前位置的能量熵
#define cvQueryHistValue_1D( hist, idx0 ) \((float)cvGetReal1D( (hist)->bins, (idx0)))
+ (double)caculateCurrentEntropy:(CvHistogram *)histogram currentThreshold:(int)threshold state:(EntropyState)state{
int start,end;
int total =0;
double cur_entropy =0.0;
if(state == Back){
start =0;
end = threshold;
}else{
start = threshold;
end =256;
}
for(int i=start;i<end;i++){
total += (int)cvQueryHistValue_1D(histogram,i);//查詢直方塊的值 P304
}
for(int j=start;j<end;j++)
{
if((int)cvQueryHistValue_1D(histogram,j)==0)
continue;
double percentage = cvQueryHistValue_1D(histogram,j)/total;
/*熵的定義公式*/
cur_entropy +=-percentage*logf(percentage);
/*根據(jù)泰勒展式去掉高次項(xiàng)得到的熵的近似計(jì)算公式
cur_entropy += percentage*percentage;*/
}
return cur_entropy;
}
//尋找最大熵閾值并分割
+ (int)maxEntropy:(IplImage *)srcImg{
/**
* 創(chuàng)建直方圖
*
* @param dims 直方圖維數(shù)的數(shù)目
* @param sizes 直方圖維數(shù)尺寸的組數(shù)
* @param type 直方圖的表示格式: CV_HIST_ARRAY 意味著直方圖數(shù)據(jù)表示為多維密集數(shù)組 CvMatND; CV_HIST_TREE 意味著直方圖數(shù)據(jù)表示為多維稀疏數(shù)組 CvSparseMat.
*/
int hist_size = 256;
CvHistogram *hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY);
cvCalcHist(&srcImg, hist);
double maxentropy = -1.0;
int max_index = -1;
// 循環(huán)測(cè)試每個(gè)分割點(diǎn),尋找到最大的閾值分割點(diǎn)
for (int i=0; i < hist_size; i++) {
double backValue = [[self class] caculateCurrentEntropy:hist currentThreshold:i state:Back];
double frontValue = [[self class] caculateCurrentEntropy:hist currentThreshold:i state:Object];
double cur_entropy = backValue + frontValue;
if(cur_entropy>maxentropy){
maxentropy = cur_entropy;
max_index = i;
}
}
return max_index;
}
參考文章:
圖像二值化----otsu(最大類間方差法、大津算法)
圖像基本變換---圖像二值化(包含OSTU/迭代法/統(tǒng)計(jì)法/雙峰法/P分位法/最大熵法)
七種常見閾值分割代碼(Otsu、最大熵、迭代法、自適應(yīng)閥值、手動(dòng)、迭代法、基本全局閾值法)


