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里面图片处理的几个函数接口:
灰度处理-》竖向边缘检测(因为车牌大部分竖向的)-》二值化处理-》形态学处理-》车牌截取
1 string read_plate(string path) 2 { 3 /*加载图片*/ 4 const char* imagename = path.c_str(); 5 IplImage * img = cvLoadImage(imagename); 6 if(!img) 7 { 8 exit(1); 9 } 10 11 if( !img->imageData ) // 检查是否正确载入图像 12 exit(1); 13 14 cvNamedWindow("image", CV_WINDOW_AUTOSIZE); //创建窗口 15 // cvShowImage("image", img); //显示图像 16 /*灰度化处理*/ 17 IplImage* img1 = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);//创建目标图像 18 cvCvtColor(img,img1,CV_BGR2GRAY);//cvCvtColor(src,des,CV_BGR2GRAY) 19 cvNamedWindow("gray_image",CV_WINDOW_AUTOSIZE);//创建显示目标的窗口 20 21 // cvShowImage("gray_image",img1);//显示灰度图像 22 /*滤波处理*/ 23 IplImage* temp = cvCreateImage(cvGetSize(img1), IPL_DEPTH_8U, 1);//创建目标图像 24 cvSmooth(img1,temp,CV_GAUSSIAN,1,1);//高斯模糊 25 // cvShowImage("guolv_image",temp);//显示过滤图 26 27 /*竖向边缘检测 竖向只是参数的改变*/ 28 IplImage * sobel=cvCreateImage(cvGetSize(temp),IPL_DEPTH_16S,1); 29 IplImage *sobelimg=cvCreateImage(cvGetSize(temp),IPL_DEPTH_8U,1); 30 cvSobel(temp,sobel,2,0,7); 31 cvConvertScaleAbs(sobel,sobelimg, 0.00390625,0); 32 // cvShowImage("灰度图像Sobel变换",sobelimg); 33 34 /*二值化处理*/ 35 IplImage *two=cvCreateImage(cvGetSize(temp),IPL_DEPTH_8U,1); 36 cvThreshold(sobelimg, two, 0, 255, CV_THRESH_BINARY| CV_THRESH_OTSU); 37 // cvShowImage("two",two); 38 39 /*形态学处理 腐蚀膨胀*/ 40 IplImage *closeimg=cvCreateImage(cvGetSize(temp),IPL_DEPTH_8U,1); 41 IplConvKernel* kernal=cvCreateStructuringElementEx(3,1, 1, 0, CV_SHAPE_RECT); 42 cvDilate(two, closeimg, kernal, 6); 43 cvErode(closeimg, closeimg, kernal, 4); 44 cvDilate(closeimg, closeimg, kernal, 2); 45 kernal = cvCreateStructuringElementEx(1, 3, 0, 1, CV_SHAPE_RECT); 46 cvErode(closeimg, closeimg, kernal, 4); 47 cvDilate(closeimg, closeimg, kernal, 2); 48 //cvShowImage("closeimg",closeimg); 49 50 /*筛选最大的那块矩形*/ 51 IplImage* copy = cvCloneImage(closeimg); 52 IplImage* dst = cvCloneImage(img); 53 CvMemStorage* storage = cvCreateMemStorage(); 54 CvSeq* contours; 55 CvRect rect,max; 56 int count=0; 57 double wide=0,height=0; 58 count= cvFindContours (copy, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE); 59 for (;contours != NULL; contours = contours->h_next) 60 { 61 rect = cvBoundingRect(contours); 62 if(rect.width > (rect.height*2)) 63 { 64 if(rect.height>height && rect.width>wide) 65 { 66 max = rect; 67 height = rect.height; 68 wide = rect.width; 69 70 } 71 } 72 } 73 cvSetImageROI(dst,cvRect(max.x+11,max.y+2,max.width-16,max.height-2)); 74 cvShowImage("choose",dst); 75 76 }