影象二值化中閾值演算法淺析
技術標籤:智慧車學習
目錄
什麼是二值化
所謂影象二值化,就是將256個亮度等級的灰度影象,通過適當的閾值選取而獲得仍然可以反映影象整體和區域性特徵的二值化影象。
由於我們用攝像頭拍到的影象為灰度影象,若直接處理會加大很多不必要的工作量,而將影象二值化,則可以使目標影象變得簡單且資料量小,同時又不丟失影象中的重要資訊。由此可見,在影象處理中,二值化步驟顯得尤為重要。
我們知道,二值化的步驟無非是將獲得的影象資料中大於閾值的畫素點用255表示,而小於閾值的畫素點用0表示。
常見的求閾值演算法
OSTU大津法
概念及原理
OTSU演算法又稱為最大類間方差法。這是我們很常見的一種求閾值的方法,它的思路就是通過統計整個影象的直方圖特性來實現全域性閾值T的自動選取。
該演算法進行前先設一個i作為分類閾值,通過歸一化的直方圖,統計影象中各個灰度級的畫素佔整幅影象的比例w0,並統計前景畫素和背景畫素的平均灰度u0和u1,和背景畫素所佔比例w1;通過公式g = w0w1(u0-u1) (u0-u1)計算前景畫素和背景畫素的方差 ,每進行完一次迴圈i值加一,直道i=256時停止迴圈,並將最大的g值作為影象閾值。
大津法二值化的程式碼實現在網上比較多,這裡不做詳細介紹。
iteration迭代法
概念及原理
迭代法也叫最小概率誤判法,它使用逐次逼近的思想,通過不斷更新迭代,求出滿足整幅影象偏差等級error的閾值。
具體步驟為:首先設定初始閾值T0和偏差等級,此閾值將影象分割為前景和背景,此時可以算出前景和背景的平均灰度值T1和T2,則新的最佳閾值為T_center=(T1+T2),將新閾值與上一個閾值比較。若兩者之差在偏差等級之內,則將標誌位置為0,結束運算,得到的閾值極為當前閾值;若大於此偏差,則標誌位置為1,繼續下一次迴圈運算,由此逐漸逼近真實閾值。
程式碼實現
do{
for(i=0;i<MT9V03X_H;i++)
{
for (j=0;j<MT9V03X_W;j++)
{
if(Im[i][j] < T2)
{
S0 += Im[i][j];
N0++; //畫素點數統計
}
else
{
S1 += Im[i][j];
N1++; //畫素點數統計
}
}
}
T1 = S0/N0; //平均灰度值
T2 = S1/N1; //平均灰度值
T_center = (T1+T2)/2;
if(abs(T_center - T0)> ERROR) flag = 1;
else flag = 0;
T0 =T_center;
BlackThres = T0;
} while(flag);
}
迭代法的空間複雜度較高,且光照越強受到的影響越強。
Sobel運算元影象邊緣提取
概念及原理
索貝爾運算元是計算機視覺領域的一種重要處理方法。主要用作邊緣檢測。索貝爾運算元是把影象中每個畫素的上下左右四領域的灰度值加權差,在邊緣處達到極值從而檢測邊緣。
運算時我們對影象中每一點使用此運算元,將會產生對應的梯度向量或是其法向量。
索貝爾運算元包含兩組3*3矩陣(橫向與縱向),具體如下:(圖源百度百科)
運算時將影象上每一點與其做平面卷積,即可分別得出橫向及縱向的亮度差分近似值,公式如下:
再將Gx與Gy相加,即為該畫素點的近似灰度大小。
最後我們可以使用畫素點之和的一定比例,作為該影象閾值 。
程式碼實現
for (i = yStart; i < yEnd; i++)
{
for (j = xStart; j < xEnd; j++)
TempX=(- mt9v03x_image[i-1][j-1])
+(-2*mt9v03x_image[i ][j-1])
+(- mt9v03x_image[i+1][j-1])
+( mt9v03x_image[i-1][j+1])
+( 2*mt9v03x_image[i ][j+1])
+( mt9v03x_image[i+1][j+1]);
TempY=( mt9v03x_image[i+1][j-1])
+( 2*mt9v03x_image[i+1][j ])
+( mt9v03x_image[i+1][j+1])
+(- mt9v03x_image[i-1][j-1])
+(-2*mt9v03x_image[i-1][j ])
+(- mt9v03x_image[i-1][j+1]);
temp=abs(tempx)+abs(tempy);
if(temp>255) temp=255;
Image_Sobel[i][j]=temp;
}
}
這種方法對陽光的適應性較好,空間複雜度也不大,是目前一種比較好的閾值演算法。
噪點過濾
索貝爾運算元有著較好的檢測效果,並且對噪聲具有平滑抑制的作用,但其得到的邊緣較粗,且可能出現偽邊緣。所以我們需要對其噪點進行過濾。
for (nr = 1; nr < LCDH - 1; nr++)
{
for (nc = 1; nc < LCDW - 1; nc = nc + 1)
{
if(WhitePixle(i,j) && mt9v03x_image[i][j]>threshold)
Image_Sobel[i][j] = 0xFE;
if( BlackPixle(i-1,j-1)&&BlackPixle(i-1,j)&&BlackPixle(i-1,j+1)&&
BlackPixle(i,j-1)&&BlackPixle(i,j+1)&&WhitePixle(i,j)&&
BlackPixle(i+1,j-1)&&BlackPixle(i+1,j)&&BlackPixle(i+1,j+1))
Image_Sobel[i][j] = 0xFE;
}
}
總結到這裡就告一段落了,自我小結的同時,也希望或多或少可以對大家有所幫助
如有疑問或錯誤,歡迎和我私信交流指正。
W.By Xyq