在上篇文章中我們了解了PlateLocate的過程中的所有步驟。在本篇文章中我們對前3個步驟,分別是高斯模糊、灰度化和Sobel算子進行分析。
一、高斯模糊
1.目標
對圖像去噪,為邊緣檢測算法做准備。
2.效果
在我們的車牌定位中的第一步就是高斯模糊處理。
圖1 高斯模糊效果
3.理論
詳細說明可以看這篇:阮一峰講高斯模糊。
高斯模糊是非常有名的一種圖像處理技術。顧名思義,其一般應用是將圖像變得模糊,但同時高斯模糊也應用在圖像的預處理階段。理解高斯模糊前,先看一下平均模糊算法。平均模糊的算法非常簡單。見下圖,每一個像素的值都取周圍所有像素(共8個)的平均值。
圖2 平均模糊示意圖
在上圖中,左邊紅色點的像素值本來是2,經過模糊后,就成了1(取周圍所有像素的均值)。在平均模糊中,周圍像素的權值都是一樣的,都是1。如果周圍像素的權值不一樣,並且與二維的高斯分布的值一樣,那么就叫做高斯模糊。
在上面的模糊過程中,每個像素取的是周圍一圈的平均值,也稱為模糊半徑為1。如果取周圍三圈,則稱之為半徑為3。半徑增大的話,會更加深模糊的效果。
4.實踐
在PlateLocate中是這樣調用高斯模糊的。
//高斯模糊。Size中的數字影響車牌定位的效果。 GaussianBlur( src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize), 0, 0, BORDER_DEFAULT );
其中Size字段的參數指定了高斯模糊的半徑。值是CPlateLocate類的m_GaussianBlurSize變量。由於opencv的高斯模糊僅接收奇數的半徑,因此變量為偶數值會拋出異常。
這里給出了opencv的高斯模糊的API(英文,2.48以上版本)。
高斯模糊這個過程一定是必要的么。筆者的回答是必要的,倘若我們將這句代碼注釋並稍作修改,重新運行一下。你會發現plateLocate過程在閉操作時就和原來發生了變化。最后結果如下。
圖3 不采用高斯模糊后的結果
可以看出,車牌所在的矩形產生了偏斜。最后得到的候選“車牌”圖塊如下:
圖4 不采用高斯模糊后的“車牌”圖塊
如果不使用高斯模糊而直接用邊緣檢測算法,我們得到的候選“車牌”達到了8個!這樣不僅會增加車牌判斷的處理時間,還增加了判斷出錯的概率。由於得到的車牌圖塊中車牌是斜着的,如果我們的字符識別算法需要一個水平的車牌圖塊,那么幾乎肯定我們會無法得到正確的字符識別效果。
高斯模糊中的半徑也會給結果帶來明顯的變化。有的圖片,高斯模糊半徑過高了,車牌就定位不出來。有的圖片,高斯模糊半徑偏低了,車牌也定位不出來。因 此、高斯模糊的半徑既不宜過高,也不能過低。CPlateLocate類中的值為5的靜態常量DEFAULT_GAUSSIANBLUR_SIZE,標示 着推薦的高斯模糊的半徑。這個值是對於近千張圖片經過測試后得出的綜合定位率最高的一個值。在CPlateLocate類的構造函數 中,m_GaussianBlurSize被賦予了DEFAULT_GAUSSIANBLUR_SIZE的值,因此,默認的高斯模糊的半徑就是5。如果不 是特殊情況,不需要修改它。
在數次的實驗以后,必須承認,保留高斯模糊過程與半徑值為5是最佳的實踐。為應對特殊需求,在CPlateLocate類中也應該提供了方法修改高斯半徑的值,調用代碼(假設需要一個為3的高斯模糊半徑)如下:
CPlateLocate plate;
plate.setGaussianBlurSize(3);
目前EasyPR的處理步驟是先進行高斯模糊,再進行灰度化。從目前的實驗結果來看,基於色彩的高斯模糊過程比灰度后的高斯模糊過程更容易檢測到邊緣點。
二、灰度化處理
1.目標
為邊緣檢測算法准備灰度化環境。
2.效果
灰度化的效果如下。
圖5 灰度化效果
3.理論
在灰度化處理步驟中,爭議最大的就是信息的損失。無疑的,原先plateLocate過程面對的圖片是彩色圖片,而從這一步以后,就會面對的是灰度圖片。在前面,已經說過這步驟是利是弊是需要討論的。
無疑,對於計算機而言,色彩圖像相對於灰度圖像難處理多了,很多圖像處理算法僅僅只適用於灰度圖像,例如后面提到的Sobel算子。在這種情況下,你除 了把圖片轉成灰度圖像再進行處理別無它法,除非重新設計算法。但另一方面,轉化成灰度圖像后恰恰失去了最豐富的細節。要知道,真實世界是彩色的,人類對於 事物的辨別是基於彩色的框架。甚至可以這樣說,因為我們的肉眼能夠區別彩色,所以我們對於事物的區分,辨別,記憶的能力就非常的強。
車牌定位環節中去掉彩色的利弊也是同理。轉換成灰度圖像雖然利於使用各種專用的算法,但失去了真實世界中辨別的最重要工具---色彩的區分。舉個簡單的例 子,人怎么在一張圖片中找到車牌?非常簡單,一眼望去,一個合適大小的矩形,藍色的、或者黃色的、或者其他顏色的在另一個黑色,或者白色的大的跟車形類似 的矩形中。這個過程非常直觀,明顯,而且可以排除模糊,色澤,不清楚等很多影響。如果使用灰度圖像,就必須借助水平,垂直求導等方法。
未來如果PlateLocate過程可以使用顏色來判斷,可能會比現在的定位更清楚、准確。但這需要研究與實驗過程,在EasyPR的未來版本中可能會 實現。但無疑,使用色彩判斷是一種趨勢,因為它不僅符合人眼識別的規律,更趨近於人工智能的本質,而且它更准確,速度更快。
4.實踐
在PlateLocate過程中是這樣調用灰度化的。
cvtColor( src_blur, src_gray, CV_RGB2GRAY );
這里給出了opencv的灰度化的API(英文,2.48以上版本)。
三.Sobel算子
1.目標
檢測圖像中的垂直邊緣,便於區分車牌。
2.效果
下圖是Sobel算子的效果。
圖6 Sobel效果
3.理論
如果要說哪個步驟是plateLocate中的核心與靈魂,毫無疑問是Sobel算子。沒有Sobel算子,也就沒有垂直邊緣的檢測,也就無法得到車牌 的可能位置,也就沒有后面的一系列的車牌判斷、字符識別過程。通過Sobel算子,可以很方便的得到車牌的一個相對准確的位置,為我們的后續處理打好堅實 的基礎。在上面的plateLocate的執行過程中可以看到,正是通過Sobel算子,將車牌中的字符與車的背景明顯區分開來,為后面的二值化與閉操作 打下了基礎。那么Sobel算子是如何運作的呢?
Soble算子原理是對圖像求一階的水平與垂直方向導數,根據導數值的大小來判斷是否是邊緣。請詳見CSDN小魏的博客(小心她博客里把Gx和Gy弄反了)。
為了計算方便,Soble算子並沒有真正去求導,而是使用了周邊值的加權和的方法,學術上稱作“卷積”。權值稱為“卷積模板”。例如下圖左邊就是Sobel的Gx卷積模板(計算垂直邊緣),中間是原圖像,右邊是經過卷積模板后的新圖像。
圖7 Sobel算子Gx示意圖
在這里演示了通過卷積模板,原始圖像紅色的像素點原本是5的值,經過卷積計算(- 1 * 3 - 2 * 3 - 1 * 4 + 1 * 5 + 2 * 7 + 1 * 6 = 12)后紅色像素的值變成了12。
4.實踐
在代碼中調用Soble算子需要較多的步驟。
/// Generate grad_x and grad_y Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y; /// Gradient X //Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT ); Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); convertScaleAbs( grad_x, abs_grad_x ); /// Gradient Y //Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT ); Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT ); convertScaleAbs( grad_y, abs_grad_y ); /// Total Gradient (approximate) addWeighted( abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad );
這里給出了opencv的Sobel的API(英文,2.48以上版本)
在調用參數中有兩個常量SOBEL_X_WEIGHT與SOBEL_Y_WEIGHT代表水平方向和垂直方向的權值,默認前者是1,后者是0,代表僅僅做水平方向求導,而不做垂直方向求導。這樣做的意義是,如果我們做了垂直方向求導,會檢測出很多水平邊緣。水平邊緣多也許有利於生成更精確的輪廓,但是由於有些車子前端太多的水平邊緣了,例如車頭排氣孔,標志等等,很多的水平邊緣會誤導我們的連接結果,導致我們得不到一個恰好的車牌位置。例如,我們對於測試的圖做如下實驗,將SOBEL_X_WEIGHT與SOBEL_Y_WEIGHT都設置為0.5(代表兩者的權值相等),那么最后得到的閉操作后的結果圖為
由於Sobel算子如此重要,可以將車牌與其他區域明顯區分出來,那么問題就來了,有沒有與Sobel功能類似的算子可以達到一致的效果,或者有沒有比Sobel效果更好的算子?
Sobel算子求圖像的一階導數,Laplace算子則是求圖像的二階導數,在通常情況下,也能檢測出邊緣,不過Laplace算子的檢測不分水平和垂直。下圖是Laplace算子與Sobel算子的一個對比。
圖8 Sobel與Laplace示意圖
可以看出,通過Laplace算子的圖像包含了水平邊緣和垂直邊緣,根據我們剛才的描述。水平邊緣對於車牌的檢測一般無利反而有害。經過對近百幅圖像的測試,Sobel算子的效果優於Laplace算子,因此不適宜采用Laplace算子替代Sobel算子。
除了Sobel算子,還有一個算子,Shcarr算子。但這個算子其實只是Sobel算子的一個變種,由於Sobel算子在3*3的卷積模板上計算往往不太精確,因此有一個特殊的Sobel算子,其權值按照下圖來表達,稱之為Scharr算子。下圖是Sobel算子與Scharr算子的一個對比。
圖9 Sobel與Scharr示意圖
一般來說,Scharr算子能夠比Sobel算子檢測邊緣的效果更好,從上圖也可以看出。但是,這個“更好”是一把雙刃劍。我們的目的並不是畫出圖像的邊緣,而是確定車牌的一個區域,越精細的邊緣越會干擾后面的閉運算。因此,針對大量的圖片的測試,Sobel算子一般都優於Scharr算子。
關於Sobel算子更詳細的解釋和Scharr算子與Sobel算子的同異,可以參看官網的介紹:Sobel與Scharr。
綜上所述,在求圖像邊緣的過程中,Sobel算子是一個最佳的契合車牌定位需求的算子,Laplace算子與Scharr算子的效果都不如它。
有一點要說明的:Sobel算子僅能對灰度圖像有效果,不能將色彩圖像作為輸入。因此在進行Soble算子前必須進行前面的灰度化工作。
版權說明:
本文中的所有文字,圖片,代碼的版權都是屬於作者和博客園共同所有。歡迎轉載,但是務必注明作者與出處。任何未經允許的剽竊以及爬蟲抓取都屬於侵權,作者和博客園保留所有權利。
參考文獻:
1.http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html
2.http://blog.csdn.net/xiaowei_cqu/article/details/7829481
3.http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html