//通过对角检测车牌 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);