opencv 通過對角檢測車牌
阿新 • • 發佈:2018-11-11
//通過對角檢測車牌 440x140 //輸入單通道二值影象 矩形最短邊長(視窗大小) 矩形最大偏轉角度 儲存矩形對角點座標 void serach_chepai_by_opposite_angles(Mat &img, int win, int angle,vector<Vec4i> &rec) { //兩個點橫豎座標差值的和小於juli則認為是一個點 const int juli = 5; //儲存 Vec2i point; vector<Vec2i> zuo,you; //行列 int row = img.rows; int col = img.cols; //判斷視窗大小是否符合實際 if(win >= max(row,col) || win < 1) return; //判斷矩形偏轉角度是否符合實際 最大45度 if(angle < 0 || angle > 45) return; //偏移 int swin = cvRound(sin(angle/180.0*CV_PI)*win); if(swin == 0) swin = 1; /*cout<<"swin = "<<swin<<endl;*/ //遍歷影象 int i,j,x,y; uchar *p,b; for( y = 0; y < row - win; y++) { for ( x = 0; x < col - win; x++) { //win視窗 左上角 for(i = 0; i < win; i++) { //垂直方向 b = 0; p = img.ptr<uchar>(y+i); for(j = 0; j < swin; j++) { b |= p[x+j]; } if(b == 0) { break; } //水平方向 b = 0; for(j = 0; j < swin; j++) { p = img.ptr<uchar>(y+j); b |= p[x+i]; } if(b == 0) { break; } if(i == win - 1) { //記錄左上角 if(zuo.size() == 0) { point[0] = x; point[1] = y; zuo.push_back(point); } for(size_t k = 0; k < zuo.size(); k++) { //排除太近的點 x要加絕對追 有可能為負值 if(abs(x-zuo[k][0])+y-zuo[k][1]<=juli) break; if(k == zuo.size() - 1) { point[0] = x; point[1] = y; zuo.push_back(point); } } } } //右下角 for(i = 0; i < win; i++) { //垂直方向 b = 0; p = img.ptr<uchar>(y+i); for(j = 0; j < swin; j++) { b |= p[x+win-j]; } if(b == 0) break; //水平方向 b = 0; for(j = 0; j < swin; j++) { p = img.ptr<uchar>(y+win-j); b |= p[x+i]; } if(b == 0) break; if(i == win - 1) { //記錄右下角 if(you.size() == 0) { point[0] = x+win; point[1] = y+win; you.push_back(point); } for(size_t k = 0; k < you.size(); k++) { //排除太近的點 x要加絕對追 有可能為負值 if(abs(x+win-you[k][0])+y+win-you[k][1]<=juli) break; if(k == you.size() - 1) { point[0] = x+win; point[1] = y+win; you.push_back(point); } } } } } } /*cout<<zuo.size()<<endl; for(size_t k = 0; k < zuo.size(); k++) { cout<<zuo[k][0]<<" "<<zuo[k][1]<<endl;; } cout<<you.size()<<endl; for(size_t k = 0; k < you.size(); k++) { cout<<you[k][0]<<" "<<you[k][1]<<endl;; }*/ //選出合適的矩形 Vec4i points; for(size_t k = 0; k < zuo.size(); k++) { for(size_t kk = 0; kk < you.size(); kk++) { //對角位置 if(you[kk][1]>zuo[k][1] && you[kk][0]>zuo[k][0]) { //矩形長寬比 440/140 3.14.... if(((you[kk][0]-zuo[k][0])*1.0/(you[kk][1]-zuo[k][1])>3.0) && ((you[kk][0]-zuo[k][0])*1.0/(you[kk][1]-zuo[k][1])<3.4)) { points[0] = zuo[k][0]; points[1] = zuo[k][1]; points[2] = you[kk][0]; points[3] = you[kk][1]; rec.push_back(points); } } } } /*cout<<rec.size();*/ }
imshow("原圖",img); vector<Vec4i> rec; //自己編寫的函式 serach_chepai_by_opposite_angles(img,30,15,rec); //為了畫綠線 單通道轉換為三通道 cvtColor(img, img, CV_GRAY2BGR); //畫出線段 for(size_t i = 0; i < rec.size(); i++ ) { //綠線 畫出矩形 line( img, Point(rec[i][0],rec[i][1]), Point(rec[i][2],rec[i][1]), Scalar(0,255,0), 1, CV_AA); line( img, Point(rec[i][0],rec[i][1]), Point(rec[i][0],rec[i][3]), Scalar(0,255,0), 1, CV_AA); line( img, Point(rec[i][0],rec[i][3]), Point(rec[i][2],rec[i][3]), Scalar(0,255,0), 1, CV_AA); line( img, Point(rec[i][2],rec[i][1]), Point(rec[i][2],rec[i][3]), Scalar(0,255,0), 1, CV_AA); } imshow("檢測",img);