前段时间刚刚把毛星云的OpenCV大体上过完了一遍,所以找了个图像处理的小项目练练手。
研一的时候做过车牌识别的小demo,当时对图像处理的一些方法的理解还不是很深刻。
在网上浏览学习了以后,参考学习了图像处理基本算法 车牌识别与定位这篇博客的思路,然后自己编程实现,具体的思路函数大概和前面的物资识别差不多:
1、车牌识别只能针对部分蓝色车牌识别成功,其他颜色的车牌会陆续优化整理的
由于蓝色车牌的RGB的值为R=28 G=63 B=138,第一步就是利用蓝色车牌的RGB来大体找到整幅图片中,车牌的位置
由于车牌特定的颜色,在效果图中,车牌的位置已经很明显了。
2、为了更加突出车牌的位置,利用形态学滤波的闭运算。
3、为了去除图中其他较小的噪声点,框出车牌位置,使用查找轮廓,计算每一个查找到的轮廓的最小外接矩形,利用矩形的像素面积进行筛选,最终得到车牌具体位置,使用矩形函数将其框出
注:这个地方我遇到了一个小坑,因为原图像是三通道的彩色图,使用颜色判别后的二值图,并不是真正的二值图,通道数仍是三,所以当进行轮廓查找时候,会出现通道错误
解决方法:针对第一个步骤得到的“二值图”,我对结果图进行了一次灰度化和二值化的一个转换,最后把二值图的通道转变为1,这样就可以使用查找轮廓函数而不会报错了
具体代码如下:
#include
#include
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(i, j)[0] - 138) < 50
&& abs(srcImg.at(i, j)[1] - 63) < 50
&& abs(srcImg.at(i, j)[2] - 28) < 50)
{
srcImg.at(i, j)[0] = srcImg.at(i, j)[1] = srcImg.at(i, j)[2] = 255;
}
else
srcImg.at(i, j)[0] = srcImg.at(i, j)[1] = srcImg.at(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> contours;
vector hierarchy;
findContours(srcImg2,contours,hierarchy,RETR_CCOMP,CHAIN_APPROX_SIMPLE,Point());
vector boundRect(contours.size());//定义外接矩形集合
vector box(contours.size());//定义最小外接矩形集合
Point2f rect[4];
//获取整个图像的最大块面积,即视作车牌面积
double maxArea = 0;
for (int x = 0; x < contours.size(); x++)
{
if(maxArea
结果图:
图中,车牌已经被圈出来了,
总结不足:(针对不足,后面学习之余,会陆续完善的,慢慢完善这个车牌识别的程序)
1、这个代码似乎是为这种相同类型的车牌图所编写的,并不具有较好的普适性
2、由于颜色的原因,图片中可能会有大比车牌大的面积,会出现错误的情况(这个已经有了具体思路,有待完善)
3、只能识别一幅图中的一张车牌,出现多张车牌,则识别错误
4、只能识别蓝色车牌
下面是其他一些车牌的识别,以后的学习中,会慢慢改进: