//通過對角檢測車牌 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);