opencv 通过对角检测车牌

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大米粥哥哥

感谢认可!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值