【图像处理】简单的车牌识别

    xiaoxiao2023-10-21  37

    前段时间刚刚把毛星云的OpenCV大体上过完了一遍,所以找了个图像处理的小项目练练手。

    研一的时候做过车牌识别的小demo,当时对图像处理的一些方法的理解还不是很深刻。

    在网上浏览学习了以后,参考学习了图像处理基本算法 车牌识别与定位这篇博客的思路,然后自己编程实现,具体的思路函数大概和前面的物资识别差不多:

    1、车牌识别只能针对部分蓝色车牌识别成功,其他颜色的车牌会陆续优化整理的

    由于蓝色车牌的RGB的值为R=28 G=63 B=138,第一步就是利用蓝色车牌的RGB来大体找到整幅图片中,车牌的位置

     由于车牌特定的颜色,在效果图中,车牌的位置已经很明显了。

    2、为了更加突出车牌的位置,利用形态学滤波的闭运算。

    3、为了去除图中其他较小的噪声点,框出车牌位置,使用查找轮廓,计算每一个查找到的轮廓的最小外接矩形,利用矩形的像素面积进行筛选,最终得到车牌具体位置,使用矩形函数将其框出

    注:这个地方我遇到了一个小坑,因为原图像是三通道的彩色图,使用颜色判别后的二值图,并不是真正的二值图,通道数仍是三,所以当进行轮廓查找时候,会出现通道错误

    解决方法:针对第一个步骤得到的“二值图”,我对结果图进行了一次灰度化和二值化的一个转换,最后把二值图的通道转变为1,这样就可以使用查找轮廓函数而不会报错了

    具体代码如下:

    #include<opencv2/opencv.hpp> #include<iostream> using namespace std; using namespace cv; int main() { Mat src = imread("demo.jpg",1); Mat srcImg = src.clone(); for (int i = 0; i < srcImg.rows; i++) { for (int j = 0; j < srcImg.cols; j++) { if (abs(srcImg.at<Vec3b>(i, j)[0] - 138) < 50 && abs(srcImg.at<Vec3b>(i, j)[1] - 63) < 50 && abs(srcImg.at<Vec3b>(i, j)[2] - 28) < 50) { srcImg.at<Vec3b>(i, j)[0] = srcImg.at<Vec3b>(i, j)[1] = srcImg.at<Vec3b>(i, j)[2] = 255; } else srcImg.at<Vec3b>(i, j)[0] = srcImg.at<Vec3b>(i, j)[1] = srcImg.at<Vec3b>(i, j)[2] = 0; } } Mat matGray; //灰度化 cvtColor(srcImg, matGray, CV_BGR2GRAY); Mat Bin; threshold(matGray,Bin,100,255,CV_THRESH_BINARY); imshow("二值化",Bin); //二值化后的图像应为单通道图像 Mat ele = getStructuringElement(MORPH_RECT,Size(15,15)); Mat Mor; morphologyEx(Bin, Mor,MORPH_CLOSE,ele); //闭运算效果图 srcImg1 imshow("闭运算",Mor); //查找轮廓 Mat srcImg2 = Mor.clone(); vector<vector<Point>> contours; vector<Vec4i> hierarchy; findContours(srcImg2,contours,hierarchy,RETR_CCOMP,CHAIN_APPROX_SIMPLE,Point()); vector<Rect> boundRect(contours.size());//定义外接矩形集合 vector<RotatedRect> box(contours.size());//定义最小外接矩形集合 Point2f rect[4]; //获取整个图像的最大块面积,即视作车牌面积 double maxArea = 0; for (int x = 0; x < contours.size(); x++) { if(maxArea<contourArea(contours[x])) maxArea = contourArea(contours[x]); } for (size_t i = 0; i < contours.size(); i++) { Mat contour(contours[i]); double area = contourArea(contour); if(area<maxArea) continue; box[i] = minAreaRect(contour);//计算每个轮廓最小外接矩形 boundRect[i] = boundingRect(contour); // boundingRect计算轮廓的垂直边界最小矩形,矩形是与图像上下界平行的 box[i].points(rect); //把最小外接矩形的四个端点复制给rect数组 rectangle(src, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(0, 0, 255), 4, 8); } imshow("结果图", src); waitKey(0); return 0; }

    结果图:

     图中,车牌已经被圈出来了,

    总结不足:(针对不足,后面学习之余,会陆续完善的,慢慢完善这个车牌识别的程序)

    1、这个代码似乎是为这种相同类型的车牌图所编写的,并不具有较好的普适性

    2、由于颜色的原因,图片中可能会有大比车牌大的面积,会出现错误的情况(这个已经有了具体思路,有待完善)

    3、只能识别一幅图中的一张车牌,出现多张车牌,则识别错误

    4、只能识别蓝色车牌

    下面是其他一些车牌的识别,以后的学习中,会慢慢改进:

     

     

     

     

    最新回复(0)