1. 程式人生 > >新能源車車牌識別c++

新能源車車牌識別c++

EasyPR中主要涉及到藍色底牌與黃色底牌、白色底牌的車牌識別,隨著新能源車輛的發展,目前有很多綠色底牌的車牌,因此增加綠色車牌的識別。

  EasyPR中關於車牌的識別,已經比較完善,這裡主要涉及到三個地方的修改。

1.新增顏色

include/easypr/config.h

在自定義Color的列舉類中,新增 綠色,修改之後為:

enum Color { BLUE, YELLOW, WHITE, GREEN, UNKNOWN };

新增綠色識別

  在OpenCV或其他軟體中,識別顏色主要通過RGB對映到HSV空間,通過判斷H、S、V的相關值來判斷顏色的,主要原理可以參考:OpenCV顏色識別。修改之後的部分程式碼如下:

src/core/core_func.cpp

 Mat colorMatch(const Mat &src, Mat &match, const Color r,
     const bool adaptive_minsv) {
                
     // if use adaptive_minsv
     // min value of s and v is adaptive to h
     const float max_sv = 255;
     const float minref_sv = 64;
                
     const float minabs_sv = 95; //95;
                
     // H range of blue 
                
     const int min_blue = 100;  // 100
     const int max_blue = 140;  // 140
                
     // H range of yellow
                
     const int min_yellow = 15;  // 15
     const int max_yellow = 40;  // 40
                
     // H range of white
                                                                                                                                                                                                     
     const int min_white = 0;   // 15
     const int max_white = 30;  // 40
                
     //Louis add,green  
     // H range of green
                
     const int min_green = 35;   // 35
     const int max_green = 80;   // 80
                
     Mat src_hsv;

	 // convert to HSV space
     cvtColor(src, src_hsv, CV_BGR2HSV);
                 
     std::vector<cv::Mat> hsvSplit;
     split(src_hsv, hsvSplit);
     equalizeHist(hsvSplit[2], hsvSplit[2]);
     merge(hsvSplit, src_hsv);
                 
     // match to find the color
                 
     int min_h = 0;
     int max_h = 0;
     switch (r) {
     case BLUE:  
       min_h = min_blue;
       max_h = max_blue;
       break;    
     case YELLOW:
       min_h = min_yellow;
       max_h = max_yellow;
       break;    
     case WHITE: 
       min_h = min_white;
       max_h = max_white;
       break;    
     //Louis add,green  
     case GREEN: 
       min_h = min_green;
       max_h = max_green;
       break;    
     default:    
       // Color::UNKNOWN
       break;    
     }           
                 
     float diff_h = float((max_h - min_h) / 2);
     float avg_h = min_h + diff_h;                                                                                                                                                                   
                 
     int channels = src_hsv.channels();
     int nRows = src_hsv.rows;
           
	 // consider multi channel image
     int nCols = src_hsv.cols * channels;
     if (src_hsv.isContinuous()) {
       nCols *= nRows;
       nRows = 1;
     }           
                 
     int i, j;   
     uchar* p;   
     float s_all = 0;
     float v_all = 0;
     float count = 0;
     for (i = 0; i < nRows; ++i) {
       p = src_hsv.ptr<uchar>(i);
       for (j = 0; j < nCols; j += 3) {
         int H = int(p[j]);      // 0-180
         int S = int(p[j + 1]);  // 0-255
         int V = int(p[j + 2]);  // 0-255
                 
         s_all += S;
         v_all += V;
         count++;
                 
         bool colorMatched = false;
                 
         if (H > min_h && H < max_h) {
           float Hdiff = 0;
           if (H > avg_h)
             Hdiff = H - avg_h;
           else  
             Hdiff = avg_h - H;                                                                                                                                                                      
                 
           float Hdiff_p = float(Hdiff) / diff_h;
                 
     float min_sv = 0;
           if (true == adaptive_minsv)
             min_sv =
             minref_sv -
             minref_sv / 2 *
             (1 
             - Hdiff_p);  // inref_sv - minref_sv / 2 * (1 - Hdiff_p)
           else 
             min_sv = minabs_sv;  // add
     
           if ((S > min_sv && S < max_sv) && (V > min_sv && V < max_sv))
             colorMatched = true;
         }      
     
         if (colorMatched == true) {
           p[j] = 0;
           p[j + 1] = 0;
           p[j + 2] = 255;
         }      
         else { 
           p[j] = 0;
           p[j + 1] = 0;
           p[j + 2] = 0;
         }
       }
     }
                
     // cout << "avg_s:" << s_all / count << endl;
     // cout << "avg_v:" << v_all / count << endl;
                
     // get the final binary
                
     Mat src_grey;
     std::vector<cv::Mat> hsvSplit_done;
     split(src_hsv, hsvSplit_done);
     src_grey = hsvSplit_done[2];
                                                                                                                                                                                                     
     match = src_grey;
     
     return src_grey;
   }

其中RGB與HSV顏色識別對應的關係,可以參考:OpenCV中HSV顏色模型及顏色分量範圍

增加字元限制

  以前的車牌主要是7位字元,包括省 [A-Z].[5位字元] 的方式。但新能源車牌,後面5為字元變為6位字元,因此之前的判斷方法不能夠獲取全部車牌,最好的情況也只能獲得前面的7位字元。因此需要修改為:

src/core/chars_segment.cpp

int CCharsSegment::RebuildRect(const vector<Rect>& vecRect,
                               vector<Rect>& outRect, int specIndex) {   
  int count = 7;//Louis changed 6->7, for green plate car
  for (size_t i = specIndex; i < vecRect.size() && count; ++i, --count) {
    outRect.push_back(vecRect[i]);                       
  }                                                      
                                                         
  return 0;                                              
}                

至此,可以識別綠色車牌。