码迷,mamicode.com
首页 > 其他好文 > 详细

opencv实现车牌识别之车牌号定位_2

时间:2015-02-07 17:25:43      阅读:281      评论:0      收藏:0      [点我收藏+]

标签:opencv   图像处理   

简介

  前一篇讲解到了将用蓝色筛选后的图片,再一次灰阶/二值化。现在从这里继续讲解。


矩形检测

  因为车牌是一个矩形。所以接着将又一次二值化之后的图片,进行膨胀,之后在进行矩形检测。框选出可能是车牌号的矩形区域。
代码如下:
int** car_License_box(Mat& mat1, Mat& mat2, int* number){
	Mat threshold_output;
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	Point s1, s2;
	int width_1, height_1;
	int width = mat1.rows;
	int height = mat1.cols;
	int sum = 0;
 
	int morph_elem = 3;
	int morph_size = 3;
 
	int** a = (int**)malloc(width * sizeof(int*));
 
	//腐蚀
	Mat element = getStructuringElement(MORPH_RECT, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( -1, -1));
	dilate(mat1, mat1, element);
 
	/// 找到轮廓
	findContours(mat1, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
 
	/// 多边形逼近轮廓 + 获取矩形和圆形边界框
	vector<vector<Point> > contours_poly( contours.size() );
	vector<Rect> boundRect( contours.size() );
	vector<Point2f>center( contours.size() );
	vector<float>radius( contours.size() );
 
	for( int i = 0; i < contours.size(); i++ )
	{ approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
		boundRect[i] = boundingRect( Mat(contours_poly[i]) );
		minEnclosingCircle( contours_poly[i], center[i], radius[i] );
	}
 
	/// 画多边形轮廓 + 包围的矩形框 + 圆形框
	mat2 = Mat::zeros(mat1.size(), CV_8UC3 );
	for( int i = 0; i< contours.size(); i++ )
	{
		s1 = boundRect[i].tl();
		s2 = boundRect[i].br();
		height_1 = s2.x - s1.x;
		width_1 =  s2.y - s1.y;
 
		if((height_1 > (3 * width_1)) && (width_1 > (width / 2))){
			a[sum] = (int* )malloc(4 * sizeof(int));
			a[sum][0] = s1.x;
			a[sum][1] = s1.y;
			a[sum][2] = s2.x;
			a[sum][3] = s2.y;
			sum += 1;
		}
	}
	*number = sum;
	return a;
}
 
int main(int argc, char **argv){
     .............
            pic_gray(img_3, img_3);
            threshold = histogram_Calculate(img_3, 3); 
            pic_Thresholding(img_3, threshold);
 
            address_1 = car_License_box(img_3, img_4, &address_Number_1);
 
            sprintf(str, "%d", i); 
            namedWindow(str);
            imshow(str, img_3);
        }   
    }   
    waitKey(0);
    return 0;
}
  在函数car_License_box中,img_3为传入的源图像,然后检测出合适矩形,将矩形左上和右下那个角点保存在二维数组address_1中,检测到的矩形数量保存在
address_Number_1中。
  该函数的具体流程如下:1、使用dilate来进行图像的膨胀。
                          2、使用opencv教程中讲解过的轮廓寻找,并将检测到的矩形角点保存在boundRect中。
                          3、根据矩形左上和右下的角点,可以计算出矩形的宽与高。车牌所在的矩形应该长至少是宽的三倍。
                             同时在之前分割的图片中,车牌的宽度至少应该是这个分割图片的一半以上才正常。
                          4、将满足了要求的矩形角点保存在二维数组a中,并将矩形探测计数+1,最后返回对应保存的二维数组。



矩形分割

  上面矩形分割,已经将可能是车牌的矩形位置角点保存在了address_1中,这里我们根据address_1中的角点坐标,将对应的矩形从原图像中复制到新图像中显示:
void pic_cutting_1(Mat& mat1, Mat& mat2, Point s1, Point s2){
    int i, j;
    IplImage pI_1;
    IplImage pI_2;
    CvScalar s;
 
    mat2 = cv::Mat(s2.y - s1.y, s2.x - s1.x, CV_8UC3, 1);
    pI_1 = mat1;
    pI_2 = mat2;
 
    for(i = s1.y; i < s2.y; i++){
        for(j=s1.x; j<s2.x; j++){
            s = cvGet2D(&pI_1, i, j);
            cvSet2D(&pI_2, i-s1.y, j-s1.x, s);
        }
    }
}
 
int main(int argc, char** argv){
      .....................
            address_1 = car_License_box(img_3, img_4, &address_Number_1);
 
            for(j=0; j< address_Number_1; j++){
 
                DE("address_0:%d, %d, %d, %d\n", address_1[j][0], address_1[j][1], address_1[j][2], address_1[j][3]);
                s1.y = address_1[j][1] + selection_1[i][0];
                s1.x = address_1[j][0];
                s2.y = address_1[j][1] + selection_1[i][1];
                s2.x = address_1[j][2];
                DE("address:%d, %d, %d, %d\n", s1.x, s1.y, s2.x, s2.y);
 
                pic_cutting_1(img, img_5, s1, s2);
 
                sprintf(str, "%d", j);
                namedWindow(str);
                imshow(str, img_5);
            }
        }
    }
    namedWindow("img");                                                                                                              
    imshow("img",img);
    waitKey(0);
    return 0;
}
  这一步很简单,效果显示如下:
                              技术分享


最后定位

  在上面的效果图片中,我们看到现在探测出了两个可能是车牌的矩形位置。继续做一次筛选判断来确定车牌真正所在的位置。
int box_selection(Mat& mat1){
    int width_1, height_1;
    int width = mat1.rows;
    int height = mat1.cols;
    int i, j;
 
    IplImage pI_1 = mat1;
 
    CvScalar s;
    int find_blue = 0;
    int blueToWhite = 0;
    int sum =0;
 
    for(i=0; i<width; i++){
        find_blue = 0;
        blueToWhite = 0;
        for(j=0; j<height; j++){
            s = cvGet2D(&pI_1, i, j); 
            if((s.val[0] - s.val[1] > 10) && (s.val[0] - s.val[2] > 10) && (s.val[1] < 150) && (s.val[2] < 150)){
                find_blue = 1;
            }   
            else if((s.val[1] > 150) && (s.val[2] > 150) && (s.val[0] > 150) && (find_blue == 1)){
                blueToWhite += 1;
                find_blue = 0;
            }
        }
        if(blueToWhite > 5){
            sum += 1;   
        }  
    }
    return sum;
}
 
int main(int argc, char **argv){
  ............
   for(j=0; j< address_Number_1; j++){
 
                DE("address_0:%d, %d, %d, %d\n", address_1[j][0], address_1[j][1], address_1[j][2], address_1[j][3]);
                s1.y = address_1[j][1] + selection_1[i][0];
                s1.x = address_1[j][0];
                s2.y = address_1[j][1] + selection_1[i][1];
                s2.x = address_1[j][2];
                DE("address:%d, %d, %d, %d\n", s1.x, s1.y, s2.x, s2.y);
 
                pic_cutting_1(img, img_5, s1, s2);
                box_flag = box_selection(img_5);
                DE("box_flag:%d\n", box_flag);
 
                if(box_flag > 5){
                    rectangle(img, s1, s2, color, 2, 8, 0 );
                    sprintf(str, "%d", j);
                    namedWindow(str);
                    imshow(str, img_5);
                }
            }
        }
    }
    namedWindow("img");
    imshow("img",img);
    waitKey(0);
    return 0;
}
  因为车牌号是蓝底白字,同时会交替出现7次。所以在box_selection,我们在蓝色之后,跳变到白色的次数至少大于五次,表示该矩形位置是框选了车牌。
来排除掉其他的矩形,最后将确定的车牌位置新图像显示出来,同时在原图像车牌的位置画上黄色方框。
  进而最后的效果演示如下:
                                技术分享


注意

  该方法的准确率并不太高。如可能出现如下情况:
                                技术分享
   代码下载如下:http://download.csdn.net/detail/u011630458/8431445

opencv实现车牌识别之车牌号定位_2

标签:opencv   图像处理   

原文地址:http://blog.csdn.net/u011630458/article/details/43604737

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!