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);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章