EasyPR--開發詳解(3)高斯模糊、灰度化和Sobel運算元

計算機的潛意識發表於2014-10-14

  上篇文章中我們瞭解了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

相關文章