
1 int test_plate_locate() { 2 cout << "test_plate_locate" << endl; 3 const string file = "resources/image/plate_locate.jpg"; 4 cv::Mat src = imread(file); 5 vector<cv::Mat> resultVec; 6 CPlateLocate plate; 7 8 int result = plate.plateLocate(src, resultVec); 9 if (result == 0) { 10 size_t num = resultVec.size(); 11 for (size_t j = 0; j < num; j++) { 12 cv::Mat resultMat = resultVec[j]; 13 imshow("plate_locate", resultMat); 14 waitKey(0); 15 } 16 destroyWindow("plate_locate"); 17 } 18 return result; 19 }
CPlateLocate 是實現車牌定位的主要功能類, 其構造函數比較簡單,主函數是 plateLocate,用於定位車牌區域,具體代碼如下:

1 //主處理函數 2 int CPlateLocate::plateLocate(Mat src, vector<Mat> &resultVec, int index) { 3 vector<CPlate> all_result_Plates; 4 5 plateColorLocate(src, all_result_Plates, index); 6 plateSobelLocate(src, all_result_Plates, index); 7 plateMserLocate(src, all_result_Plates, index); 8 9 for (size_t i = 0; i < all_result_Plates.size(); i++) { 10 CPlate plate = all_result_Plates[i]; 11 resultVec.push_back(plate.getPlateMat()); 12 } 13 14 return 0; 15 }
從代碼中可以看到,CPlateLocate 此處主要使用了以下三種方法,三種方法混合使用,互為補充。
1、顏色定位 plateColorLocate();
2、sobel算子定位 plateSobelLocate() ;
3、MSER方法,即最大極值穩定區域方法 plateMserLocate()。
為什么要設計三種方法對車牌進行定位,這里有其使用場景的特殊性。最開始的車牌識別系統都是用sobel算子查找垂直邊緣的方法進行車牌識別,但是該方法最大的問題在於面對垂直邊緣交錯的情況下,無法准確地定位車牌。 如下圖所示:
但是顏色定位也並非萬能的,例如在色彩充足,光照足夠的情況下,顏色定位的效果很好,但是在面對光線不足的情況,或者藍色車身的情況時,顏色定位的效果很糟糕。 如下圖所示:
所以新版本的EasyPR中使用了顏色定位與 Sobel 定位結合的方式。首先進行顏色定位,然后根據條件使用Sobel 進行再次定位,增加整個系統的適應能力。但是有沒有可能出現顏色定位和Sobel定位都無法識別車牌的情況呢,當然這種情況是有的,比如對分辨率較大的圖片處理仍然不好。再加上顏色定位在面對低光照,低對比度的圖像時處理效果大幅度下降,顏色本身也是一個不穩定的特征。因此EasyPR的車牌定位的整體魯棒性仍然不足。如下圖所示:
因此在前面兩種方法的基礎上又增加了MSER 最大極值穩定區域方法。最大極值穩定區域是由Matas等人提出的一種仿射特征區域提取算法。其提取的區域內部灰度幾乎不變但是和背景的對比十分強烈,並且該區域能夠在多重閾值下保持形狀不變。它是基於分水嶺的概念。MSER的基本原理是對一幅灰度圖像(灰度值為0~255)取閾值進行二值化處理,閾值從0到255依次遞增。閾值的遞增類似於分水嶺算法中的水面的上升,隨着水面的上升,有一些較矮的丘陵會被淹沒,類似於二值圖像。在得到的所有二值圖像中,圖像中的某些連通區域變化很小,甚至沒有變化,則該區域就被稱為最大穩定極值區域。MSER算法的具體描述和實現我們會在后面做詳細的介紹。
后續章節我們會分別對這三種車牌定位方法進行詳細的介紹。