基于opencv的车牌识别系统

2022-12-07,,

前言

学习了很长一段时间了,需要沉淀下,而最好的办法就是做一个东西来应用学习的东西,同时也是一个学习的过程。

PS:这篇小文是毕业之前和同学做的一个小项目,所以写的比较匆忙,代码也是直接粘贴的,基于qt开发的C++代码,不能保证没有错误,请慎重。不希望对你产生误导,有任何问题可以联系我,一起探讨下。最后,我现在已经没有搞嵌入式方面的开发了。

概述    

OpenCV的全称是:Open Source Computer Vision Library。OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

来自百度的解释,之所以选择opencv是因为:首先向学习一个新的东西来看看自己的学习接受能力,然后是感觉opencv很酷,处理图片真实说一不二的(你可以理解为处理图片很方便)。

车牌识别系统重点在于车牌的识别,还有后台的处理。要使它成为一个系统,缺一不可。

大致上分为三个部分:信息采集和传输,接收图片并识别客户端请求,信息的存储和查询


1.信息采集和传输

这里我们采用的是 网上买的小摄像头+网上的开源项目mjpg-stream

对于mjpg-stream的使用,网上已经有很多博客了,你可以找到很多。

mjpg-stream 不仅能调用摄像头拍摄照片还可以作为服务器发送图片数据,所以我这里直接使用它作为服务器发送给我自己写的客户端数据。

2.接收图片并进行图片识别和显示

这里就需要用到opencv来进行处理了。

大致上车牌识别分为:车牌提取,字符提取,字符识别

车牌提取:需要调用opencv里面图片处理的几个函数接口:

灰度处理-》竖向边缘检测(因为车牌大部分竖向的)-》二值化处理-》形态学处理-》车牌截取

 string read_plate(string path)
{
/*加载图片*/
const char* imagename = path.c_str();
IplImage * img = cvLoadImage(imagename);
if(!img)
{
exit();
} if( !img->imageData ) // 检查是否正确载入图像
exit(); cvNamedWindow("image", CV_WINDOW_AUTOSIZE); //创建窗口
// cvShowImage("image", img); //显示图像
/*灰度化处理*/
IplImage* img1 = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, );//创建目标图像
cvCvtColor(img,img1,CV_BGR2GRAY);//cvCvtColor(src,des,CV_BGR2GRAY)
cvNamedWindow("gray_image",CV_WINDOW_AUTOSIZE);//创建显示目标的窗口 // cvShowImage("gray_image",img1);//显示灰度图像
/*滤波处理*/
IplImage* temp = cvCreateImage(cvGetSize(img1), IPL_DEPTH_8U, );//创建目标图像
cvSmooth(img1,temp,CV_GAUSSIAN,,);//高斯模糊
// cvShowImage("guolv_image",temp);//显示过滤图 /*竖向边缘检测 竖向只是参数的改变*/
IplImage * sobel=cvCreateImage(cvGetSize(temp),IPL_DEPTH_16S,);
IplImage *sobelimg=cvCreateImage(cvGetSize(temp),IPL_DEPTH_8U,);
cvSobel(temp,sobel,,,);
cvConvertScaleAbs(sobel,sobelimg, 0.00390625,);
// cvShowImage("灰度图像Sobel变换",sobelimg); /*二值化处理*/
IplImage *two=cvCreateImage(cvGetSize(temp),IPL_DEPTH_8U,);
cvThreshold(sobelimg, two, , , CV_THRESH_BINARY| CV_THRESH_OTSU);
// cvShowImage("two",two); /*形态学处理 腐蚀膨胀*/
IplImage *closeimg=cvCreateImage(cvGetSize(temp),IPL_DEPTH_8U,);
IplConvKernel* kernal=cvCreateStructuringElementEx(,, , , CV_SHAPE_RECT);
cvDilate(two, closeimg, kernal, );
cvErode(closeimg, closeimg, kernal, );
cvDilate(closeimg, closeimg, kernal, );
kernal = cvCreateStructuringElementEx(, , , , CV_SHAPE_RECT);
cvErode(closeimg, closeimg, kernal, );
cvDilate(closeimg, closeimg, kernal, );
//cvShowImage("closeimg",closeimg); /*筛选最大的那块矩形*/
IplImage* copy = cvCloneImage(closeimg);
IplImage* dst = cvCloneImage(img);
CvMemStorage* storage = cvCreateMemStorage();
CvSeq* contours;
CvRect rect,max;
int count=;
double wide=,height=;
count= cvFindContours (copy, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
for (;contours != NULL; contours = contours->h_next)
{
rect = cvBoundingRect(contours);
if(rect.width > (rect.height*))
{
if(rect.height>height && rect.width>wide)
{
max = rect;
height = rect.height;
wide = rect.width; }
}
}
cvSetImageROI(dst,cvRect(max.x+,max.y+,max.width-,max.height-));
cvShowImage("choose",dst); }

plate shot

代码中对截取车牌进行了操作

下面是字符的识别:字符识别有很多方法,但是都是算法的,我研究的不是很深,选取了最简单的一种,自己做字符库,然后比对。

 //车牌识别
#include "char.h" //中文字模 注意绝对路径= =
const char *mb_ku_zw[] = {
"/home/panhao/QtProject/MyANPR/char_img/zw1.bmp","/home/panhao/QtProject/MyANPR/char_img/zw2.bmp","/home/panhao/QtProject/MyANPR/char_img/zw3.bmp",
"/home/panhao/QtProject/MyANPR/char_img/zw4.bmp","/home/panhao/QtProject/MyANPR/char_img/zw5.bmp",
"/home/panhao/QtProject/MyANPR/char_img/zw6.bmp","/home/panhao/QtProject/MyANPR/char_img/zw7.bmp","/home/panhao/QtProject/MyANPR/char_img/zw8.bmp",
"/home/panhao/QtProject/MyANPR/char_img/zw9.bmp","/home/panhao/QtProject/MyANPR/char_img/zw10.bmp","/home/panhao/QtProject/MyANPR/char_img/zw11.bmp",
"/home/panhao/QtProject/MyANPR/char_img/zw12.bmp","/home/panhao/QtProject/MyANPR/char_img/zw13.bmp","/home/panhao/QtProject/MyANPR/char_img/zw14.bmp",
"/home/panhao/QtProject/MyANPR/char_img/zw15.bmp","/home/panhao/QtProject/MyANPR/char_img/zw16.bmp","/home/panhao/QtProject/MyANPR/char_img/zw17.bmp",
"/home/panhao/QtProject/MyANPR/char_img/zw18.bmp","/home/panhao/QtProject/MyANPR/char_img/zw19.bmp","/home/panhao/QtProject/MyANPR/char_img/zw20.bmp",
"/home/panhao/QtProject/MyANPR/char_img/zw21.bmp","/home/panhao/QtProject/MyANPR/char_img/zw22.bmp","/home/panhao/QtProject/MyANPR/char_img/zw23.bmp",
"/home/panhao/QtProject/MyANPR/char_img/zw24.bmp","/home/panhao/QtProject/MyANPR/char_img/zw25.bmp","/home/panhao/QtProject/MyANPR/char_img/zw26.bmp",
"/home/panhao/QtProject/MyANPR/char_img/zw27.bmp","/home/panhao/QtProject/MyANPR/char_img/zw28.bmp","/home/panhao/QtProject/MyANPR/char_img/zw29.bmp",
"/home/panhao/QtProject/MyANPR/char_img/zw30.bmp","/home/panhao/QtProject/MyANPR/char_img/zw31.bmp",
};
const char *mb_ku_zf[] ={
"/home/panhao/QtProject/MyANPR/char_img/A.bmp","/home/panhao/QtProject/MyANPR/char_img/B.bmp",
"/home/panhao/QtProject/MyANPR/char_img/C.bmp","/home/panhao/QtProject/MyANPR/char_img/D.bmp",
"/home/panhao/QtProject/MyANPR/char_img/E.bmp","/home/panhao/QtProject/MyANPR/char_img/F.bmp",
"/home/panhao/QtProject/MyANPR/char_img/G.bmp","/home/panhao/QtProject/MyANPR/char_img/H.bmp",
"/home/panhao/QtProject/MyANPR/char_img/J.bmp","/home/panhao/QtProject/MyANPR/char_img/K.bmp",
"/home/panhao/QtProject/MyANPR/char_img/L.bmp","/home/panhao/QtProject/MyANPR/char_img/M.bmp",
"/home/panhao/QtProject/MyANPR/char_img/N.bmp","/home/panhao/QtProject/MyANPR/char_img/P.bmp",
"/home/panhao/QtProject/MyANPR/char_img/Q.bmp","/home/panhao/QtProject/MyANPR/char_img/R.bmp",
"/home/panhao/QtProject/MyANPR/char_img/S.bmp","/home/panhao/QtProject/MyANPR/char_img/T.bmp",
"/home/panhao/QtProject/MyANPR/char_img/U.bmp","/home/panhao/QtProject/MyANPR/char_img/V.bmp",
"/home/panhao/QtProject/MyANPR/char_img/W.bmp","/home/panhao/QtProject/MyANPR/char_img/X.bmp",
"/home/panhao/QtProject/MyANPR/char_img/Y.bmp","/home/panhao/QtProject/MyANPR/char_img/Z.bmp",
};
const char *mb_ku_sz[] ={
"/home/panhao/QtProject/MyANPR/char_img/0.bmp","/home/panhao/QtProject/MyANPR/char_img/1.bmp","/home/panhao/QtProject/MyANPR/char_img/2.bmp",
"/home/panhao/QtProject/MyANPR/char_img/3.bmp","/home/panhao/QtProject/MyANPR/char_img/4.bmp","/home/panhao/QtProject/MyANPR/char_img/5.bmp",
"/home/panhao/QtProject/MyANPR/char_img/6.bmp","/home/panhao/QtProject/MyANPR/char_img/7.bmp","/home/panhao/QtProject/MyANPR/char_img/8.bmp",
"/home/panhao/QtProject/MyANPR/char_img/9.bmp",
};
const char *mb_ku_sf[] = {
"/home/panhao/QtProject/MyANPR/char_img/0.bmp","/home/panhao/QtProject/MyANPR/char_img/1.bmp","/home/panhao/QtProject/MyANPR/char_img/2.bmp",
"/home/panhao/QtProject/MyANPR/char_img/3.bmp","/home/panhao/QtProject/MyANPR/char_img/4.bmp","/home/panhao/QtProject/MyANPR/char_img/5.bmp",
"/home/panhao/QtProject/MyANPR/char_img/6.bmp","/home/panhao/QtProject/MyANPR/char_img/7.bmp","/home/panhao/QtProject/MyANPR/char_img/8.bmp",
"/home/panhao/QtProject/MyANPR/char_img/9.bmp","/home/panhao/QtProject/MyANPR/char_img/A.bmp","/home/panhao/QtProject/MyANPR/char_img/B.bmp",
"/home/panhao/QtProject/MyANPR/char_img/C.bmp","/home/panhao/QtProject/MyANPR/char_img/D.bmp","/home/panhao/QtProject/MyANPR/char_img/E.bmp",
"/home/panhao/QtProject/MyANPR/char_img/F.bmp","/home/panhao/QtProject/MyANPR/char_img/G.bmp","/home/panhao/QtProject/MyANPR/char_img/H.bmp",
"/home/panhao/QtProject/MyANPR/char_img/J.bmp","/home/panhao/QtProject/MyANPR/char_img/K.bmp","/home/panhao/QtProject/MyANPR/char_img/L.bmp",
"/home/panhao/QtProject/MyANPR/char_img/M.bmp","/home/panhao/QtProject/MyANPR/char_img/N.bmp","/home/panhao/QtProject/MyANPR/char_img/P.bmp",
"/home/panhao/QtProject/MyANPR/char_img/Q.bmp","/home/panhao/QtProject/MyANPR/char_img/R.bmp","/home/panhao/QtProject/MyANPR/char_img/S.bmp",
"/home/panhao/QtProject/MyANPR/char_img/T.bmp","/home/panhao/QtProject/MyANPR/char_img/U.bmp","/home/panhao/QtProject/MyANPR/char_img/V.bmp",
"/home/panhao/QtProject/MyANPR/char_img/W.bmp","/home/panhao/QtProject/MyANPR/char_img/X.bmp","/home/panhao/QtProject/MyANPR/char_img/Y.bmp",
"/home/panhao/QtProject/MyANPR/char_img/Z.bmp", }; string shibie(char *imgpath)
{
IplImage *pSrcImage = cvLoadImage(imgpath, ); //定位后车牌路径
IplImage *pGrayImage = NULL;
IplImage *pBinaryImage = NULL;
IplImage *ty_cpimg = NULL;
// 转为灰度图
pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, );
cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);
// 创建二值图
pBinaryImage = cvCreateImage(cvGetSize(pGrayImage), IPL_DEPTH_8U, );
//转为二值图,自适二值化CV_THRESH_OTSU
cvThreshold(pGrayImage, pBinaryImage, , , CV_THRESH_BINARY | CV_THRESH_OTSU); cvNamedWindow("input",);
cvShowImage("input",pBinaryImage); //识别铆钉
const int height_md_yz = pBinaryImage->height / ; //y轴方向的阈值
const int width_md_yz = pBinaryImage->width; //x轴方向的阈值
IplImage* cyp = cvCloneImage( pBinaryImage );
int width_md = ;
int height_md = ;
int count_bd = ;
uchar count_bd_str[width_md_yz];
for(count_bd = ; count_bd < width_md_yz; count_bd++)
count_bd_str[count_bd] = ;
uchar *pt = (uchar *)cyp->imageData;
const uchar step = cyp->widthStep; //扫描白点并记录
for(width_md = ; width_md < width_md_yz; width_md++)
{
for(height_md = ; height_md < height_md_yz; height_md++)
{
if(pt[height_md*step + width_md])
count_bd_str[width_md]++;
}
} int width_bf = ;
int width_ls = ;
for(width_md = ; width_md < width_md_yz; width_md++)
{
if(count_bd_str[width_md] > height_md_yz/)
if(width_md < width_md_yz-)
if(count_bd_str[++width_md]> height_md_yz/)
{
if(!width_bf)
{
if(width_md > width_md_yz*0.2)
width_bf = width_md;
}
else if(width_md - width_bf > width_md_yz/)
{
if(width_md > width_md_yz*0.6)
width_ls = width_md;
}
}
}
//如果判断是柳钉则使用柳钉计算比例定位
if(width_md_yz*0.4 < (width_ls - width_bf) && (width_ls - width_bf) < width_md_yz*0.6)
{
float img_bl = ((float)(width_ls - width_bf))/;
int width_left_new = width_bf - (int)(img_bl*);
int width_right_new = width_ls + (int)(img_bl*);
if(width_left_new<)width_left_new=;
if(width_right_new>pBinaryImage->width)width_right_new=pBinaryImage->width;
int height_top_new = ;
int height_down_new = pBinaryImage->height;
const uchar height_yz_x = pBinaryImage->height/;
uchar count_bd_x_str[height_yz_x];
for(count_bd = ; count_bd < height_yz_x; count_bd++) //数组清零
count_bd_x_str[count_bd] = ;
for(int height_ydw = ; height_ydw < height_yz_x; height_ydw++)
{
for(width_md = ; width_md < width_md_yz; width_md++)
{
if(pt[height_ydw*step + width_md])
count_bd_x_str[height_ydw]++;
}
}
for(int height_ydw = ; height_ydw < height_yz_x; height_ydw++)
{
if(count_bd_x_str[height_ydw] < (int)(pBinaryImage->width*/)) //切割条件->白点个数 阈值
height_top_new = height_ydw;
} for(count_bd = ; count_bd < height_yz_x; count_bd++)
count_bd_x_str[count_bd] = ;
for(int height_ydw = ; height_ydw < height_yz_x; height_ydw++)
{
for(width_md = ; width_md < width_md_yz; width_md++)
{
if(pt[(pBinaryImage->height - height_ydw)*step + width_md])
count_bd_x_str[height_ydw]++;
}
}
for(int height_ydw = ; height_ydw < height_yz_x; height_ydw++)
{
if(count_bd_x_str[height_ydw] < (int)(pBinaryImage->width*/))
height_down_new = pBinaryImage->height - height_ydw;
} IplImage* cyp_ptx = cvCloneImage( pBinaryImage );
CvRect ptx;
ptx.x = width_left_new;
ptx.y = height_top_new;
ptx.height = height_down_new - height_top_new;
ptx.width = width_right_new - width_left_new;
cvSetImageROI(cyp_ptx, ptx);
cvSaveImage("/home/panhao/QtProject/MyANPR/img/cyp_ptx.jpg", cyp_ptx);
ty_cpimg = cvCloneImage(cyp_ptx);
cvResetImageROI(cyp_ptx);
}
//如果无法识别铆钉,那就先投影切割后按比例切割字符
else
{
int width_left_new_y = ;
int width_right_new_y = pBinaryImage->width;
int height_top_new_y = ;
int height_down_new_y = pBinaryImage->height;
const uchar height_yz_y = pBinaryImage->height/;
const uchar width_yz_y = pBinaryImage->width/; //阈值 请修改
uchar width_bd_ptr_y[width_yz_y];
uchar height_bd_ptr_y[height_yz_y];
for(count_bd = ; count_bd < width_yz_y; count_bd++)
width_bd_ptr_y[count_bd] = ;
for(count_bd = ; count_bd < height_yz_y; count_bd++)
height_bd_ptr_y[count_bd] = ;
for(int width_yd_y = ; width_yd_y < width_yz_y; width_yd_y++)
for(int height_yd_y = ; height_yd_y < pBinaryImage->height; height_yd_y++)
{
if(pt[height_yd_y*step + width_yd_y])
width_bd_ptr_y[width_yd_y]++;
}
for(int width_yd_y = ; width_yd_y < width_yz_y; width_yd_y++)
{
if(width_bd_ptr_y[width_yd_y] < (int)(pBinaryImage->height*/))
width_left_new_y = width_yd_y;
// int x = width_bd_ptr_y[width_yd_y];
}
for(count_bd = ; count_bd < width_yz_y; count_bd++)
width_bd_ptr_y[count_bd] = ;
for(int width_yd_y = ; width_yd_y < width_yz_y; width_yd_y++)
for(int height_yd_y = ; height_yd_y < pBinaryImage->height; height_yd_y++)
{
if(pt[height_yd_y*step + pBinaryImage->width - width_yd_y])
width_bd_ptr_y[width_yd_y]++;
}
for(int width_yd_y = ; width_yd_y < width_yz_y; width_yd_y++)
{
if(width_bd_ptr_y[width_yd_y] < (int)(pBinaryImage->height*/))
width_right_new_y =pBinaryImage->width - width_yd_y;
} for(int height_yd_y = ; height_yd_y < height_yz_y; height_yd_y++)
for(int width_yd_y = ; width_yd_y < pBinaryImage->width; width_yd_y++)
{
if(pt[height_yd_y*step + width_yd_y])
height_bd_ptr_y[height_yd_y]++;
}
for(int height_yd_y = ; height_yd_y < height_yz_y; height_yd_y++)
{
if(height_bd_ptr_y[height_yd_y] < (int)(pBinaryImage->width*/))
height_top_new_y = height_yd_y;
}
for(count_bd = ; count_bd < height_yz_y; count_bd++)
height_bd_ptr_y[count_bd] = ;
for(int height_yd_y = ; height_yd_y < height_yz_y; height_yd_y++)
for(int width_yd_y = ; width_yd_y < pBinaryImage->width; width_yd_y++)
{
if(pt[(pBinaryImage->height - height_yd_y)*step + width_yd_y])
height_bd_ptr_y[height_yd_y]++;
}
for(int height_yd_y = ; height_yd_y < height_yz_y; height_yd_y++)
{
if(height_bd_ptr_y[height_yd_y] < (int)(pBinaryImage->width*/)) //上下切
height_down_new_y = pBinaryImage->height - height_yd_y;
}
IplImage* cyp_ptx = cvCloneImage( pBinaryImage );
CvRect ptx;
ptx.x = width_left_new_y;
ptx.y = height_top_new_y;
ptx.height = height_down_new_y - height_top_new_y;
ptx.width = width_right_new_y - width_left_new_y;
cvSetImageROI(cyp_ptx, ptx);
cvSaveImage("/home/panhao/QtProject/MyANPR/img/cyp_ptx_y.jpg", cyp_ptx); //保存查看投影切割的结果
ty_cpimg = cvCloneImage(cyp_ptx);
cvResetImageROI(cyp_ptx);
} //图片统一尺寸180x40 开始字符切割(字符切割使用的是最最简单的按比例切割,效果不是很理想,如果要高识别率,需要对字符进行上下左右的投影切割,然后再进行归一化,这样可以提高识别率)
IplImage *img_ty = NULL;
CvSize dst_cvsize;
dst_cvsize.height = ;
dst_cvsize.width = ;
img_ty = cvCreateImage(dst_cvsize, ty_cpimg->depth, ty_cpimg->nChannels);
cvResize(ty_cpimg, img_ty, CV_INTER_LINEAR); //二线性插值法会出现灰度
ty_cpimg = cvCloneImage( img_ty );
cvThreshold(ty_cpimg, img_ty, , , CV_THRESH_BINARY | CV_THRESH_OTSU); //再次二值化
cvSaveImage("/home/panhao/QtProject/MyANPR/img/img_ty.jpg", img_ty);
dst_cvsize.height = ;
dst_cvsize.width = ;
IplImage *pic1 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
IplImage *pic2 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
IplImage *pic3 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
IplImage *pic4 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
IplImage *pic5 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
IplImage *pic6 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
IplImage *pic7 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
IplImage* copy_zf = NULL;
copy_zf = cvCloneImage( img_ty );
CvRect ptx;
ptx.x = ;
ptx.y = ;
ptx.height = ;
ptx.width = ;
cvSetImageROI(copy_zf, ptx);
cvCopy(copy_zf, pic1);
cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf1.jpg", pic1); //注意绝对路径 出错请debug
pic1 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf1.jpg", ); //注意 这两句必须要,否则后面结果就不对 copy_zf = cvCloneImage( img_ty );
ptx.x = +;
ptx.y = ;
ptx.height = ;
ptx.width = ;
cvSetImageROI(copy_zf, ptx);
cvCopy(copy_zf, pic2);
cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf2.jpg", pic2);
pic2 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf2.jpg", ); copy_zf = cvCloneImage( img_ty );
ptx.x = +++;
ptx.y = ;
ptx.height = ;
ptx.width = ;
cvSetImageROI(copy_zf, ptx);
cvCopy(copy_zf, pic3);
cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf3.jpg", pic3);
pic3 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf3.jpg", ); copy_zf = cvCloneImage( img_ty );
ptx.x = +++++;
ptx.y = ;
ptx.height = ;
ptx.width = ;
cvSetImageROI(copy_zf, ptx);
cvCopy(copy_zf, pic4);
cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf4.jpg", pic4);
pic4 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf4.jpg", ); copy_zf = cvCloneImage( img_ty );
ptx.x = +++++++;
ptx.y = ;
ptx.height = ;
ptx.width = ;
cvSetImageROI(copy_zf, ptx);
cvCopy(copy_zf, pic5);
cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf5.jpg", pic5);
pic5 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf5.jpg", ); copy_zf = cvCloneImage( img_ty );
ptx.x = +++++++++;
ptx.y = ;
ptx.height = ;
ptx.width = ;
cvSetImageROI(copy_zf, ptx);
cvCopy(copy_zf, pic6);
cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf6.jpg", pic6);
pic6 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf6.jpg", ); copy_zf = cvCloneImage( img_ty );
ptx.x = +++++++++++;
ptx.y = ;
ptx.height = ;
ptx.width = ;
cvSetImageROI(copy_zf, ptx);
cvCopy(copy_zf, pic7);
cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf7.jpg", pic7);
pic7 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf7.jpg", ); //字符识别(使用模版逐点比对式,相似点*100/总点数=成功率)
string wz_1 = db_successlv_1(pic1); //车牌第一个字符 以下以此类推 做返回值string中若有中文会有乱码
string wz_2 = db_successlv_2(pic2);
string wz_3 = db_successlv_3(pic3);
string wz_4 = db_successlv_3(pic4);
string wz_5 = db_successlv_4_7(pic5);
string wz_6 = db_successlv_4_7(pic6);
string wz_7 = db_successlv_4_7(pic7);
string finish = wz_1 + wz_2 + wz_3 + wz_4 + wz_5 + wz_6 + wz_7; //最后结果
//cout << "finish:"<<finish << endl;
//printf("endl\n"); cvReleaseImage(&pic1);
cvReleaseImage(&pic2);
cvReleaseImage(&pic3);
cvReleaseImage(&pic4);
cvReleaseImage(&pic5);
cvReleaseImage(&pic6);
cvReleaseImage(&pic7);
cvReleaseImage(&copy_zf);
cvReleaseImage(&img_ty);
cvReleaseImage(&ty_cpimg);
cvReleaseImage(&pSrcImage);
cvReleaseImage(&pGrayImage);
cvReleaseImage(&pBinaryImage);
cvReleaseImage(&cyp); return finish;
} int sb_count_bd(IplImage *img)
{
int count = ;
uchar *pt = (uchar *)img->imageData;
const uchar step = img->widthStep;
for(int w = ; w < img->width; w++)
for(int h = ; h < img->height; h++)
if(pt[h*step + w])
count += w*h;
return count;
} string db_successlv_3(IplImage *cs)
{
uchar *pt_cs = (uchar *)cs->imageData;
uchar i = ;
uchar max = ;
uchar max_backup = ;
uchar zf = ;
string fhz = "\0";
for(i = ; i < ; i++)
{
IplImage *mb = cvLoadImage(mb_ku_sf[i], );
uchar cgl = ; int cg_count = ;
int bd_count = ;
uchar *pt_mb = (uchar *)mb->imageData;
const uchar step_cs = cs->widthStep;
const uchar step_mb = mb->widthStep;
for(int w = ; w < cs->width; w++)
for(int h = ; h < cs->height; h++)
{
if((pt_cs[h*step_cs + w] == pt_mb[h*step_mb + w]))
cg_count++;
if(pt_mb[h*step_mb + w])
bd_count++;
}
cvReleaseImage(&mb);
cgl = (uchar)(((float)cg_count/(cs->height*cs->width))*);
max = max<cgl? cgl : max;
if(max != max_backup)
zf = i;
max_backup = max;
}
switch(zf)
{
case : fhz = "";break; case : fhz = "";break; case : fhz = "";break; case : fhz = "";break;
case : fhz = "";break; case : fhz = "";break; case : fhz = "";break; case : fhz = "";break;
case : fhz = "";break; case : fhz = "";break; case : fhz = "A";break; case : fhz = "B";break;
case : fhz = "C";break; case : fhz = "D";break; case : fhz = "E";break; case : fhz = "F";break;
case : fhz = "G";break; case : fhz = "H";break; case : fhz = "J";break; case : fhz = "K";break;
case : fhz = "L";break; case : fhz = "M";break; case : fhz = "N";break; case : fhz = "P";break;
case : fhz = "Q";break; case : fhz = "R";break; case : fhz = "S";break; case : fhz = "T";break;
case : fhz = "U";break; case : fhz = "V";break; case : fhz = "W";break; case : fhz = "X";break;
case : fhz = "Y";break; case : fhz = "Z";break;
}
return (fhz);
} string db_successlv_1(IplImage *cs)
{
string fhz = "\0";
uchar *pt_cs = (uchar *)cs->imageData;
uchar i = ;
uchar max = ;
uchar max_backup = ;
uchar zf = ;
for(i = ; i < ; i++)
{
IplImage *mb = cvLoadImage(mb_ku_zw[i], );
uchar cgl = ; int cg_count = ;
int bd_count = ;
uchar *pt_mb = (uchar *)mb->imageData;
const uchar step_cs = cs->widthStep;
const uchar step_mb = mb->widthStep;
for(int w = ; w < cs->width; w++)
for(int h = ; h < cs->height; h++)
{
if((pt_cs[h*step_cs + w] == pt_mb[h*step_mb + w]))
cg_count++;
if(pt_mb[h*step_mb + w])
bd_count++;
}
cvReleaseImage(&mb);
cgl = (uchar)(((float)cg_count/(cs->height*cs->width))*);
max = max<cgl? cgl : max;
if(max != max_backup)
zf = i;
max_backup = max;
//printf("zf=%d\n",(int)zf);
} switch(zf)
{
case : fhz = "藏";break; case : fhz = "川";break; case : fhz = "鄂";break; case : fhz = "甘";break;
case : fhz = "赣";break; case : fhz = "贵";break; case : fhz = "桂";break; case : fhz = "黑";break;
case : fhz = "沪";break; case : fhz = "吉";break; case : fhz = "冀";break; case : fhz = "津";break;
case : fhz = "晋";break; case : fhz = "京";break; case : fhz = "辽";break; case : fhz = "鲁";break;
case : fhz = "蒙";break; case : fhz = "闽";break; case : fhz = "宁";break; case : fhz = "青";break;
case : fhz = "琼";break; case : fhz = "陕";break; case : fhz = "苏";break; case : fhz = "皖";break;
case : fhz = "湘";break; case : fhz = "新";break; case : fhz = "渝";break; case : fhz = "豫";break;
case : fhz = "粤";break; case : fhz = "云";break; case : fhz = "浙";break;
}
//cout << "return"<<endl;
return (fhz);
} string db_successlv_2(IplImage *cs)
{
string fhz = "\0";
uchar *pt_cs = (uchar *)cs->imageData;
uchar i = ;
uchar max = ;
uchar max_backup = ;
uchar zf = ;
for(i = ; i < ; i++)
{
IplImage *mb = cvLoadImage(mb_ku_zf[i], );
uchar cgl = ; int cg_count = ;
int bd_count = ;
uchar *pt_mb = (uchar *)mb->imageData;
const uchar step_cs = cs->widthStep;
const uchar step_mb = mb->widthStep;
for(int w = ; w < cs->width; w++)
for(int h = ; h < cs->height; h++)
{
if((pt_cs[h*step_cs + w] == pt_mb[h*step_mb + w]))
cg_count++;
if(pt_mb[h*step_mb + w])
bd_count++;
}
cvReleaseImage(&mb);
cgl = (uchar)(((float)cg_count/(cs->height*cs->width))*);
max = max<cgl? cgl : max;
if(max != max_backup)
zf = i;
max_backup = max;
//printf("wz_2 i=%d,zf=%d,max=%d\n",(int)i,(int)zf,(int)max);
}
switch(zf)
{
case : fhz = "A";break; case : fhz = "B";break;
case : fhz = "C";break; case : fhz = "D";break; case : fhz = "E";break; case : fhz = "F";break;
case : fhz = "G";break; case : fhz = "H";break; case : fhz = "J";break; case : fhz = "K";break;
case : fhz = "L";break; case : fhz = "M";break; case : fhz = "N";break; case : fhz = "P";break;
case : fhz = "Q";break; case : fhz = "R";break; case : fhz = "S";break; case : fhz = "T";break;
case : fhz = "U";break; case : fhz = "V";break; case : fhz = "W";break; case : fhz = "X";break;
case : fhz = "Y";break; case : fhz = "Z";break;
}
return (fhz);
} string db_successlv_4_7(IplImage *cs)
{
string fhz = "\0";
uchar *pt_cs = (uchar *)cs->imageData;
uchar i = ;
uchar max = ;
uchar max_backup = ;
uchar zf = ;
for(i = ; i < ; i++)
{
IplImage *mb = cvLoadImage(mb_ku_sz[i], );
uchar cgl = ; int cg_count = ;
int bd_count = ;
uchar *pt_mb = (uchar *)mb->imageData;
const uchar step_cs = cs->widthStep;
const uchar step_mb = mb->widthStep;
for(int w = ; w < cs->width; w++)
for(int h = ; h < cs->height; h++)
{
if((pt_cs[h*step_cs + w] == pt_mb[h*step_mb + w]))
cg_count++;
if(pt_mb[h*step_mb + w])
bd_count++;
}
cvReleaseImage(&mb);
cgl = (uchar)(((float)cg_count/(cs->height*cs->width))*);
max = max<cgl? cgl : max;
if(max != max_backup)
zf = i;
max_backup = max;
}
switch(zf)
{
case : fhz = "";break; case : fhz = "";break; case : fhz = "";break; case : fhz = "";break;
case : fhz = "";break; case : fhz = "";break; case : fhz = "";break; case : fhz = "";break;
case : fhz = "";break; case : fhz = "";break;
}
return (fhz);
}

char

前面的路径中就是字符库的图片路径。

最后可以得到车牌号码的 字符串,接下来就是后台的处理。

3.对进出用户的信息存储和读取。

这里我们使用的是Qt界面程序语言编写的客户端。

这里是真正的发挥空间,可以使用得来的数据进行存储,还有手机客户端给用户信息。

 

 

基于opencv的车牌识别系统的相关教程结束。

《基于opencv的车牌识别系统.doc》

下载本文的Word格式文档,以方便收藏与打印。