OpenCV的二值化操做中,有一種「大津閾值處理」的方法,使用函數cvThreshold(image,image2,0,255,CV_THRESH_OTSU) 實現,該函數就會使用大律法OTSU獲得的全局自適應閾值來進行二值化圖片,而參數中的threshold再也不起做用。OTSU算法算法
OTSU算法也稱最大類間差法,有時也稱之爲大津算法,由大津於1979年提出,被認爲是圖像分割中閾值選取的最佳算法,計算簡單,不受圖像亮度和對比度的影響,所以在數字圖像處理上獲得了普遍的應用。它是按圖像的灰度特性,將圖像分紅背景和前景兩部分。因方差是灰度分佈均勻性的一種度量,背景和前景之間的類間方差越大,說明構成圖像的兩部分的差異越大,當部分前景錯分爲背景或部分背景錯分爲前景都會致使兩部分差異變小。所以,使類間方差最大的分割意味着錯分機率最小。數組
設灰度圖像灰度級是L,則灰度範圍爲[0,L-1],利用OTSU算法計算圖像的最佳閾值爲:
t = Max[w0(t) * (u0(t) - u)^2 + w1(t) * (u1(t) - u)^2)]
其中的變量說明:當分割的閾值爲t時,w0爲背景比例,u0爲背景均值,w1爲前景比例,u1爲前景均值,u爲整幅圖像的均值。
使以上表達式值最大的t,即爲分割圖像的最佳閾值。函數
如下是一段在OpenCV中實現的C語言程序,即一個使用OTSU算法提取圖像閾值的函數,輸入參數爲一個圖像指針,返回分割該圖像的最佳閾值。spa
其中的變量說明:當分割的閾值爲t時.net
w0爲背景像素點佔整幅圖像的比例指針
u0爲w0平均灰度blog
w1爲前景像素點佔整幅圖像的比例圖片
u1爲w1平均灰度get
u爲整幅圖像的平均灰度圖像處理
公式:g = w0*pow((u-u0),2) + w1*pow((u-u1),2)
int MyAutoFocusDll::otsuThreshold(IplImage *frame)
{
const int GrayScale = 256;
int width = frame->width;
int height = frame->height;
int pixelCount[GrayScale];
float pixelPro[GrayScale];
int i, j, pixelSum = width * height, threshold = 0;
uchar* data = (uchar*)frame->imageData; //指向像素數據的指針
for(i = 0; i < GrayScale; i++)
{
pixelCount[i] = 0;
pixelPro[i] = 0;
}
//統計灰度級中每一個像素在整幅圖像中的個數
for(i = 0; i < height; i++)
{
for(j = 0;j < width;j++)
{
pixelCount[(int)data[i * width + j]]++; //將像素值做爲計數數組的下標
}
}
//計算每一個像素在整幅圖像中的比例
float maxPro = 0.0;
int kk=0;
for(i = 0; i < GrayScale; i++)
{
pixelPro[i] = (float)pixelCount[i] / pixelSum;
if( pixelPro[i] > maxPro )
{
maxPro = pixelPro[i];
kk = i;
}
}
//遍歷灰度級[0,255]
float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
for(i = 0; i < GrayScale; i++) // i做爲閾值
{
w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;
for(j = 0; j < GrayScale; j++)
{
if(j <= i) //背景部分
{
w0 += pixelPro[j];
u0tmp += j * pixelPro[j];
}
else //前景部分
{
w1 += pixelPro[j];
u1tmp += j * pixelPro[j];
}
}
u0 = u0tmp / w0;
u1 = u1tmp / w1;
u = u0tmp + u1tmp;
deltaTmp = w0 * pow((u0 - u), 2) + w1 * pow((u1 - u), 2);
if(deltaTmp > deltaMax)
{
deltaMax = deltaTmp;
threshold = i;
}
}
return threshold;
}