基于opencv的车牌识别系统

前言

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

概述    

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 }

plate shot

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

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

  1 //车牌识别
  2 #include "char.h"
  3
  4 //中文字模   注意绝对路径= =
  5 const char *mb_ku_zw[31] = {
  6     "/home/panhao/QtProject/MyANPR/char_img/zw1.bmp","/home/panhao/QtProject/MyANPR/char_img/zw2.bmp","/home/panhao/QtProject/MyANPR/char_img/zw3.bmp",
  7     "/home/panhao/QtProject/MyANPR/char_img/zw4.bmp","/home/panhao/QtProject/MyANPR/char_img/zw5.bmp",
  8     "/home/panhao/QtProject/MyANPR/char_img/zw6.bmp","/home/panhao/QtProject/MyANPR/char_img/zw7.bmp","/home/panhao/QtProject/MyANPR/char_img/zw8.bmp",
  9     "/home/panhao/QtProject/MyANPR/char_img/zw9.bmp","/home/panhao/QtProject/MyANPR/char_img/zw10.bmp","/home/panhao/QtProject/MyANPR/char_img/zw11.bmp",
 10     "/home/panhao/QtProject/MyANPR/char_img/zw12.bmp","/home/panhao/QtProject/MyANPR/char_img/zw13.bmp","/home/panhao/QtProject/MyANPR/char_img/zw14.bmp",
 11     "/home/panhao/QtProject/MyANPR/char_img/zw15.bmp","/home/panhao/QtProject/MyANPR/char_img/zw16.bmp","/home/panhao/QtProject/MyANPR/char_img/zw17.bmp",
 12     "/home/panhao/QtProject/MyANPR/char_img/zw18.bmp","/home/panhao/QtProject/MyANPR/char_img/zw19.bmp","/home/panhao/QtProject/MyANPR/char_img/zw20.bmp",
 13     "/home/panhao/QtProject/MyANPR/char_img/zw21.bmp","/home/panhao/QtProject/MyANPR/char_img/zw22.bmp","/home/panhao/QtProject/MyANPR/char_img/zw23.bmp",
 14     "/home/panhao/QtProject/MyANPR/char_img/zw24.bmp","/home/panhao/QtProject/MyANPR/char_img/zw25.bmp","/home/panhao/QtProject/MyANPR/char_img/zw26.bmp",
 15     "/home/panhao/QtProject/MyANPR/char_img/zw27.bmp","/home/panhao/QtProject/MyANPR/char_img/zw28.bmp","/home/panhao/QtProject/MyANPR/char_img/zw29.bmp",
 16     "/home/panhao/QtProject/MyANPR/char_img/zw30.bmp","/home/panhao/QtProject/MyANPR/char_img/zw31.bmp",
 17 };
 18 const char *mb_ku_zf[24] ={
 19     "/home/panhao/QtProject/MyANPR/char_img/A.bmp","/home/panhao/QtProject/MyANPR/char_img/B.bmp",
 20     "/home/panhao/QtProject/MyANPR/char_img/C.bmp","/home/panhao/QtProject/MyANPR/char_img/D.bmp",
 21     "/home/panhao/QtProject/MyANPR/char_img/E.bmp","/home/panhao/QtProject/MyANPR/char_img/F.bmp",
 22     "/home/panhao/QtProject/MyANPR/char_img/G.bmp","/home/panhao/QtProject/MyANPR/char_img/H.bmp",
 23     "/home/panhao/QtProject/MyANPR/char_img/J.bmp","/home/panhao/QtProject/MyANPR/char_img/K.bmp",
 24     "/home/panhao/QtProject/MyANPR/char_img/L.bmp","/home/panhao/QtProject/MyANPR/char_img/M.bmp",
 25     "/home/panhao/QtProject/MyANPR/char_img/N.bmp","/home/panhao/QtProject/MyANPR/char_img/P.bmp",
 26     "/home/panhao/QtProject/MyANPR/char_img/Q.bmp","/home/panhao/QtProject/MyANPR/char_img/R.bmp",
 27     "/home/panhao/QtProject/MyANPR/char_img/S.bmp","/home/panhao/QtProject/MyANPR/char_img/T.bmp",
 28     "/home/panhao/QtProject/MyANPR/char_img/U.bmp","/home/panhao/QtProject/MyANPR/char_img/V.bmp",
 29     "/home/panhao/QtProject/MyANPR/char_img/W.bmp","/home/panhao/QtProject/MyANPR/char_img/X.bmp",
 30     "/home/panhao/QtProject/MyANPR/char_img/Y.bmp","/home/panhao/QtProject/MyANPR/char_img/Z.bmp",
 31 };
 32 const char *mb_ku_sz[10] ={
 33     "/home/panhao/QtProject/MyANPR/char_img/0.bmp","/home/panhao/QtProject/MyANPR/char_img/1.bmp","/home/panhao/QtProject/MyANPR/char_img/2.bmp",
 34     "/home/panhao/QtProject/MyANPR/char_img/3.bmp","/home/panhao/QtProject/MyANPR/char_img/4.bmp","/home/panhao/QtProject/MyANPR/char_img/5.bmp",
 35     "/home/panhao/QtProject/MyANPR/char_img/6.bmp","/home/panhao/QtProject/MyANPR/char_img/7.bmp","/home/panhao/QtProject/MyANPR/char_img/8.bmp",
 36     "/home/panhao/QtProject/MyANPR/char_img/9.bmp",
 37 };
 38 const char *mb_ku_sf[34] = {
 39     "/home/panhao/QtProject/MyANPR/char_img/0.bmp","/home/panhao/QtProject/MyANPR/char_img/1.bmp","/home/panhao/QtProject/MyANPR/char_img/2.bmp",
 40     "/home/panhao/QtProject/MyANPR/char_img/3.bmp","/home/panhao/QtProject/MyANPR/char_img/4.bmp","/home/panhao/QtProject/MyANPR/char_img/5.bmp",
 41     "/home/panhao/QtProject/MyANPR/char_img/6.bmp","/home/panhao/QtProject/MyANPR/char_img/7.bmp","/home/panhao/QtProject/MyANPR/char_img/8.bmp",
 42     "/home/panhao/QtProject/MyANPR/char_img/9.bmp","/home/panhao/QtProject/MyANPR/char_img/A.bmp","/home/panhao/QtProject/MyANPR/char_img/B.bmp",
 43     "/home/panhao/QtProject/MyANPR/char_img/C.bmp","/home/panhao/QtProject/MyANPR/char_img/D.bmp","/home/panhao/QtProject/MyANPR/char_img/E.bmp",
 44     "/home/panhao/QtProject/MyANPR/char_img/F.bmp","/home/panhao/QtProject/MyANPR/char_img/G.bmp","/home/panhao/QtProject/MyANPR/char_img/H.bmp",
 45     "/home/panhao/QtProject/MyANPR/char_img/J.bmp","/home/panhao/QtProject/MyANPR/char_img/K.bmp","/home/panhao/QtProject/MyANPR/char_img/L.bmp",
 46     "/home/panhao/QtProject/MyANPR/char_img/M.bmp","/home/panhao/QtProject/MyANPR/char_img/N.bmp","/home/panhao/QtProject/MyANPR/char_img/P.bmp",
 47     "/home/panhao/QtProject/MyANPR/char_img/Q.bmp","/home/panhao/QtProject/MyANPR/char_img/R.bmp","/home/panhao/QtProject/MyANPR/char_img/S.bmp",
 48     "/home/panhao/QtProject/MyANPR/char_img/T.bmp","/home/panhao/QtProject/MyANPR/char_img/U.bmp","/home/panhao/QtProject/MyANPR/char_img/V.bmp",
 49     "/home/panhao/QtProject/MyANPR/char_img/W.bmp","/home/panhao/QtProject/MyANPR/char_img/X.bmp","/home/panhao/QtProject/MyANPR/char_img/Y.bmp",
 50     "/home/panhao/QtProject/MyANPR/char_img/Z.bmp",
 51
 52 };
 53
 54 string shibie(char *imgpath)
 55 {
 56     IplImage *pSrcImage = cvLoadImage(imgpath, 1);       //定位后车牌路径
 57     IplImage *pGrayImage = NULL;
 58     IplImage *pBinaryImage = NULL;
 59     IplImage *ty_cpimg = NULL;
 60     // 转为灰度图
 61     pGrayImage =  cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);
 62     cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);
 63     // 创建二值图
 64     pBinaryImage = cvCreateImage(cvGetSize(pGrayImage), IPL_DEPTH_8U, 1);
 65     //转为二值图,自适二值化CV_THRESH_OTSU
 66     cvThreshold(pGrayImage, pBinaryImage, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
 67
 68     cvNamedWindow("input",1);
 69     cvShowImage("input",pBinaryImage);
 70
 71     //识别铆钉
 72     const int height_md_yz = pBinaryImage->height / 10;        //y轴方向的阈值
 73     const int width_md_yz  = pBinaryImage->width;              //x轴方向的阈值
 74     IplImage* cyp = cvCloneImage( pBinaryImage );
 75     int width_md = 0;
 76     int height_md  = 0;
 77     int count_bd = 0;
 78     uchar count_bd_str[width_md_yz];
 79     for(count_bd = 0; count_bd < width_md_yz; count_bd++)
 80         count_bd_str[count_bd] = 0;
 81     uchar *pt = (uchar *)cyp->imageData;
 82     const uchar step = cyp->widthStep;
 83
 84     //扫描白点并记录
 85     for(width_md  = 0 ; width_md < width_md_yz; width_md++)
 86     {
 87         for(height_md = 0 ; height_md < height_md_yz; height_md++)
 88         {
 89             if(pt[height_md*step + width_md])
 90                 count_bd_str[width_md]++;
 91         }
 92     }
 93
 94
 95     int width_bf   = 0;
 96     int width_ls   = 0;
 97     for(width_md  = 0 ; width_md < width_md_yz; width_md++)
 98     {
 99         if(count_bd_str[width_md] > height_md_yz/2)
100             if(width_md < width_md_yz-1)
101                 if(count_bd_str[++width_md]> height_md_yz/2)
102                 {
103                     if(!width_bf)
104                     {
105                         if(width_md > width_md_yz*0.2)
106                             width_bf = width_md;
107                     }
108                     else if(width_md - width_bf > width_md_yz/3)
109                     {
110                         if(width_md > width_md_yz*0.6)
111                             width_ls = width_md;
112                     }
113                 }
114     }
115     //如果判断是柳钉则使用柳钉计算比例定位
116     if(width_md_yz*0.4 < (width_ls - width_bf) && (width_ls - width_bf) < width_md_yz*0.6)
117     {
118         float img_bl = ((float)(width_ls - width_bf))/220;
119         int width_left_new = width_bf - (int)(img_bl*78);
120         int width_right_new = width_ls + (int)(img_bl*78);
121         if(width_left_new<0)width_left_new=0;
122         if(width_right_new>pBinaryImage->width)width_right_new=pBinaryImage->width;
123         int height_top_new = 0;
124         int height_down_new = pBinaryImage->height;
125         const uchar height_yz_x = pBinaryImage->height/5;
126         uchar count_bd_x_str[height_yz_x];
127         for(count_bd = 0; count_bd < height_yz_x; count_bd++)             //数组清零
128             count_bd_x_str[count_bd] = 0;
129         for(int height_ydw = 0; height_ydw < height_yz_x; height_ydw++)
130         {
131             for(width_md  = 0 ; width_md < width_md_yz; width_md++)
132             {
133                 if(pt[height_ydw*step + width_md])
134                     count_bd_x_str[height_ydw]++;
135             }
136         }
137         for(int height_ydw = 0; height_ydw < height_yz_x; height_ydw++)
138         {
139             if(count_bd_x_str[height_ydw] < (int)(pBinaryImage->width*25/100))    //切割条件->白点个数 阈值
140                 height_top_new = height_ydw;
141         }
142
143         for(count_bd = 0; count_bd < height_yz_x; count_bd++)
144             count_bd_x_str[count_bd] = 0;
145         for(int height_ydw = 0; height_ydw < height_yz_x; height_ydw++)
146         {
147             for(width_md  = 0 ; width_md < width_md_yz; width_md++)
148             {
149                 if(pt[(pBinaryImage->height - height_ydw)*step + width_md])
150                     count_bd_x_str[height_ydw]++;
151             }
152         }
153         for(int height_ydw = 0; height_ydw < height_yz_x; height_ydw++)
154         {
155             if(count_bd_x_str[height_ydw] < (int)(pBinaryImage->width*25/100))
156                 height_down_new = pBinaryImage->height - height_ydw;
157         }
158
159         IplImage* cyp_ptx = cvCloneImage( pBinaryImage );
160         CvRect ptx;
161         ptx.x = width_left_new;
162         ptx.y = height_top_new;
163         ptx.height = height_down_new - height_top_new;
164         ptx.width  = width_right_new - width_left_new;
165         cvSetImageROI(cyp_ptx, ptx);
166         cvSaveImage("/home/panhao/QtProject/MyANPR/img/cyp_ptx.jpg", cyp_ptx);
167         ty_cpimg = cvCloneImage(cyp_ptx);
168         cvResetImageROI(cyp_ptx);
169     }
170     //如果无法识别铆钉,那就先投影切割后按比例切割字符
171     else
172     {
173         int width_left_new_y = 0;
174         int width_right_new_y = pBinaryImage->width;
175         int height_top_new_y = 0;
176         int height_down_new_y = pBinaryImage->height;
177         const uchar height_yz_y = pBinaryImage->height/5;
178         const uchar width_yz_y = pBinaryImage->width/16;    //阈值 请修改
179         uchar width_bd_ptr_y[width_yz_y];
180         uchar height_bd_ptr_y[height_yz_y];
181         for(count_bd = 0; count_bd < width_yz_y; count_bd++)
182             width_bd_ptr_y[count_bd] = 0;
183         for(count_bd = 0; count_bd < height_yz_y; count_bd++)
184             height_bd_ptr_y[count_bd] = 0;
185         for(int width_yd_y = 0; width_yd_y < width_yz_y; width_yd_y++)
186             for(int height_yd_y = 0; height_yd_y < pBinaryImage->height; height_yd_y++)
187             {
188                 if(pt[height_yd_y*step + width_yd_y])
189                     width_bd_ptr_y[width_yd_y]++;
190             }
191         for(int width_yd_y = 0; width_yd_y < width_yz_y; width_yd_y++)
192         {
193             if(width_bd_ptr_y[width_yd_y] < (int)(pBinaryImage->height*2/10))
194                 width_left_new_y = width_yd_y;
195 //            int x = width_bd_ptr_y[width_yd_y];
196         }
197         for(count_bd = 0; count_bd < width_yz_y; count_bd++)
198             width_bd_ptr_y[count_bd] = 0;
199         for(int width_yd_y = 0; width_yd_y < width_yz_y; width_yd_y++)
200             for(int height_yd_y = 0; height_yd_y < pBinaryImage->height; height_yd_y++)
201             {
202                 if(pt[height_yd_y*step + pBinaryImage->width - width_yd_y])
203                     width_bd_ptr_y[width_yd_y]++;
204             }
205         for(int width_yd_y = 0; width_yd_y < width_yz_y; width_yd_y++)
206         {
207             if(width_bd_ptr_y[width_yd_y] < (int)(pBinaryImage->height*2/10))
208                 width_right_new_y =pBinaryImage->width - width_yd_y;
209         }
210
211         for(int height_yd_y = 0; height_yd_y < height_yz_y; height_yd_y++)
212             for(int width_yd_y = 0; width_yd_y < pBinaryImage->width; width_yd_y++)
213             {
214                 if(pt[height_yd_y*step + width_yd_y])
215                     height_bd_ptr_y[height_yd_y]++;
216             }
217         for(int height_yd_y = 0; height_yd_y < height_yz_y; height_yd_y++)
218         {
219             if(height_bd_ptr_y[height_yd_y] < (int)(pBinaryImage->width*18/100))
220                 height_top_new_y = height_yd_y;
221         }
222         for(count_bd = 0; count_bd < height_yz_y; count_bd++)
223             height_bd_ptr_y[count_bd] = 0;
224         for(int height_yd_y = 0; height_yd_y < height_yz_y; height_yd_y++)
225             for(int width_yd_y = 0; width_yd_y < pBinaryImage->width; width_yd_y++)
226             {
227                 if(pt[(pBinaryImage->height - height_yd_y)*step + width_yd_y])
228                     height_bd_ptr_y[height_yd_y]++;
229             }
230         for(int height_yd_y = 0; height_yd_y < height_yz_y; height_yd_y++)
231         {
232             if(height_bd_ptr_y[height_yd_y] < (int)(pBinaryImage->width*18/100))    //上下切
233                 height_down_new_y = pBinaryImage->height - height_yd_y;
234         }
235         IplImage* cyp_ptx = cvCloneImage( pBinaryImage );
236         CvRect ptx;
237         ptx.x = width_left_new_y;
238         ptx.y = height_top_new_y;
239         ptx.height = height_down_new_y - height_top_new_y;
240         ptx.width  = width_right_new_y - width_left_new_y;
241         cvSetImageROI(cyp_ptx, ptx);
242         cvSaveImage("/home/panhao/QtProject/MyANPR/img/cyp_ptx_y.jpg", cyp_ptx);        //保存查看投影切割的结果
243         ty_cpimg = cvCloneImage(cyp_ptx);
244         cvResetImageROI(cyp_ptx);
245     }
246
247     //图片统一尺寸180x40  开始字符切割(字符切割使用的是最最简单的按比例切割,效果不是很理想,如果要高识别率,需要对字符进行上下左右的投影切割,然后再进行归一化,这样可以提高识别率)
248     IplImage *img_ty = NULL;
249     CvSize dst_cvsize;
250     dst_cvsize.height = 40;
251     dst_cvsize.width = 180;
252     img_ty = cvCreateImage(dst_cvsize, ty_cpimg->depth, ty_cpimg->nChannels);
253     cvResize(ty_cpimg, img_ty, CV_INTER_LINEAR);         //二线性插值法会出现灰度
254     ty_cpimg = cvCloneImage( img_ty );
255     cvThreshold(ty_cpimg, img_ty, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);   //再次二值化
256     cvSaveImage("/home/panhao/QtProject/MyANPR/img/img_ty.jpg", img_ty);
257     dst_cvsize.height = 40;
258     dst_cvsize.width = 20;
259     IplImage *pic1 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
260     IplImage *pic2 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
261     IplImage *pic3 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
262     IplImage *pic4 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
263     IplImage *pic5 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
264     IplImage *pic6 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
265     IplImage *pic7 = cvCreateImage(dst_cvsize, img_ty->depth, img_ty->nChannels);
266     IplImage* copy_zf = NULL;
267     copy_zf = cvCloneImage( img_ty );
268     CvRect ptx;
269     ptx.x = 0;
270     ptx.y = 0;
271     ptx.height = 40;
272     ptx.width  = 20;
273     cvSetImageROI(copy_zf, ptx);
274     cvCopy(copy_zf, pic1);
275     cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf1.jpg", pic1);                        //注意绝对路径 出错请debug
276     pic1 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf1.jpg", 1);                    //注意 这两句必须要,否则后面结果就不对
277
278
279     copy_zf = cvCloneImage( img_ty );
280     ptx.x = 20+6;
281     ptx.y = 0;
282     ptx.height = 40;
283     ptx.width  = 20;
284     cvSetImageROI(copy_zf, ptx);
285     cvCopy(copy_zf, pic2);
286     cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf2.jpg", pic2);
287     pic2 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf2.jpg", 1);
288
289
290     copy_zf = cvCloneImage( img_ty );
291     ptx.x = 20+6+20+15;
292     ptx.y = 0;
293     ptx.height = 40;
294     ptx.width  = 20;
295     cvSetImageROI(copy_zf, ptx);
296     cvCopy(copy_zf, pic3);
297     cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf3.jpg", pic3);
298     pic3 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf3.jpg", 1);
299
300
301     copy_zf = cvCloneImage( img_ty );
302     ptx.x = 20+6+20+15+20+4;
303     ptx.y = 0;
304     ptx.height = 40;
305     ptx.width  = 20;
306     cvSetImageROI(copy_zf, ptx);
307     cvCopy(copy_zf, pic4);
308     cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf4.jpg", pic4);
309     pic4 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf4.jpg", 1);
310
311
312     copy_zf = cvCloneImage( img_ty );
313     ptx.x = 20+6+20+15+20+6+20+4;
314     ptx.y = 0;
315     ptx.height = 40;
316     ptx.width  = 20;
317     cvSetImageROI(copy_zf, ptx);
318     cvCopy(copy_zf, pic5);
319     cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf5.jpg", pic5);
320     pic5 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf5.jpg", 1);
321
322
323     copy_zf = cvCloneImage( img_ty );
324     ptx.x = 20+6+20+15+20+6+20+6+20+2;
325     ptx.y = 0;
326     ptx.height = 40;
327     ptx.width  = 20;
328     cvSetImageROI(copy_zf, ptx);
329     cvCopy(copy_zf, pic6);
330     cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf6.jpg", pic6);
331     pic6 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf6.jpg", 1);
332
333
334     copy_zf = cvCloneImage( img_ty );
335     ptx.x = 20+6+20+15+20+6+20+6+20+6+20+1;
336     ptx.y = 0;
337     ptx.height = 40;
338     ptx.width  = 20;
339     cvSetImageROI(copy_zf, ptx);
340     cvCopy(copy_zf, pic7);
341     cvSaveImage("/home/panhao/QtProject/MyANPR/img/copy_zf7.jpg", pic7);
342     pic7 = cvLoadImage("/home/panhao/QtProject/MyANPR/img/copy_zf7.jpg", 1);
343
344
345
346     //字符识别(使用模版逐点比对式,相似点*100/总点数=成功率)
347     string wz_1 = db_successlv_1(pic1);                     //车牌第一个字符   以下以此类推   做返回值string中若有中文会有乱码
348     string wz_2 = db_successlv_2(pic2);
349     string wz_3 = db_successlv_3(pic3);
350     string wz_4 = db_successlv_3(pic4);
351     string wz_5 = db_successlv_4_7(pic5);
352     string wz_6 = db_successlv_4_7(pic6);
353     string wz_7 = db_successlv_4_7(pic7);
354     string finish = wz_1 + wz_2 + wz_3 + wz_4 + wz_5 + wz_6 + wz_7;    //最后结果
355     //cout << "finish:"<<finish << endl;
356     //printf("endl\n");
357
358
359     cvReleaseImage(&pic1);
360     cvReleaseImage(&pic2);
361     cvReleaseImage(&pic3);
362     cvReleaseImage(&pic4);
363     cvReleaseImage(&pic5);
364     cvReleaseImage(&pic6);
365     cvReleaseImage(&pic7);
366     cvReleaseImage(&copy_zf);
367     cvReleaseImage(&img_ty);
368     cvReleaseImage(&ty_cpimg);
369     cvReleaseImage(&pSrcImage);
370     cvReleaseImage(&pGrayImage);
371     cvReleaseImage(&pBinaryImage);
372     cvReleaseImage(&cyp);
373
374     return finish;
375 }
376
377
378 int sb_count_bd(IplImage *img)
379 {
380     int count = 0;
381     uchar *pt = (uchar *)img->imageData;
382     const uchar step = img->widthStep;
383     for(int w = 0; w < img->width; w++)
384         for(int h = 0; h < img->height; h++)
385             if(pt[h*step + w])
386                 count += w*h;
387     return count;
388 }
389
390 string db_successlv_3(IplImage *cs)
391 {
392     uchar *pt_cs = (uchar *)cs->imageData;
393     uchar i = 0;
394     uchar max = 0;
395     uchar max_backup = 0;
396     uchar zf  = 0;
397     string fhz = "\0";
398     for(i = 0; i < 34; i++)
399     {
400         IplImage *mb = cvLoadImage(mb_ku_sf[i], 1);
401         uchar cgl = 0;
402
403         int cg_count = 0;
404         int bd_count = 0;
405         uchar *pt_mb = (uchar *)mb->imageData;
406         const uchar step_cs = cs->widthStep;
407         const uchar step_mb = mb->widthStep;
408         for(int w = 0; w < cs->width; w++)
409             for(int h = 0; h < cs->height; h++)
410             {
411                 if((pt_cs[h*step_cs + w] == pt_mb[h*step_mb + w]))
412                     cg_count++;
413                 if(pt_mb[h*step_mb + w])
414                     bd_count++;
415             }
416         cvReleaseImage(&mb);
417             cgl = (uchar)(((float)cg_count/(cs->height*cs->width))*100);
418         max = max<cgl? cgl : max;
419         if(max != max_backup)
420             zf = i;
421         max_backup = max;
422     }
423     switch(zf)
424     {
425     case 0: fhz = "0";break; case 1: fhz = "1";break; case 2: fhz = "2";break; case 3: fhz = "3";break;
426     case 4: fhz = "4";break; case 5: fhz = "5";break; case 6: fhz = "6";break; case 7: fhz = "7";break;
427     case 8: fhz = "8";break; case 9: fhz = "9";break; case 10: fhz = "A";break; case 11: fhz = "B";break;
428     case 12: fhz = "C";break; case 13: fhz = "D";break; case 14: fhz = "E";break; case 15: fhz = "F";break;
429     case 16: fhz = "G";break; case 17: fhz = "H";break; case 18: fhz = "J";break; case 19: fhz = "K";break;
430     case 20: fhz = "L";break; case 21: fhz = "M";break; case 22: fhz = "N";break; case 23: fhz = "P";break;
431     case 24: fhz = "Q";break; case 25: fhz = "R";break; case 26: fhz = "S";break; case 27: fhz = "T";break;
432     case 28: fhz = "U";break; case 29: fhz = "V";break; case 30: fhz = "W";break; case 31: fhz = "X";break;
433     case 32: fhz = "Y";break; case 33: fhz = "Z";break;
434     }
435     return (fhz);
436 }
437
438 string db_successlv_1(IplImage *cs)
439 {
440     string fhz = "\0";
441     uchar *pt_cs = (uchar *)cs->imageData;
442     uchar i = 0;
443     uchar max = 0;
444     uchar max_backup = 0;
445     uchar zf  = 0;
446     for(i = 0; i < 31; i++)
447     {
448         IplImage *mb = cvLoadImage(mb_ku_zw[i], 1);
449         uchar cgl = 0;
450
451         int cg_count = 0;
452         int bd_count = 0;
453         uchar *pt_mb = (uchar *)mb->imageData;
454         const uchar step_cs = cs->widthStep;
455         const uchar step_mb = mb->widthStep;
456         for(int w = 0; w < cs->width; w++)
457             for(int h = 0; h < cs->height; h++)
458             {
459                 if((pt_cs[h*step_cs + w] == pt_mb[h*step_mb + w]))
460                     cg_count++;
461                 if(pt_mb[h*step_mb + w])
462                     bd_count++;
463             }
464         cvReleaseImage(&mb);
465             cgl = (uchar)(((float)cg_count/(cs->height*cs->width))*100);
466         max = max<cgl? cgl : max;
467         if(max != max_backup)
468             zf = i;
469         max_backup = max;
470         //printf("zf=%d\n",(int)zf);
471     }
472
473     switch(zf)
474     {
475     case 0: fhz = "藏";break; case 1: fhz = "川";break; case 2: fhz = "鄂";break; case 3: fhz = "甘";break;
476     case 4: fhz = "赣";break; case 5: fhz = "贵";break; case 6: fhz = "桂";break; case 7: fhz = "黑";break;
477     case 8: fhz = "沪";break; case 9: fhz = "吉";break; case 10: fhz = "冀";break; case 11: fhz = "津";break;
478     case 12: fhz = "晋";break; case 13: fhz = "京";break; case 14: fhz = "辽";break; case 15: fhz = "鲁";break;
479     case 16: fhz = "蒙";break; case 17: fhz = "闽";break; case 18: fhz = "宁";break; case 19: fhz = "青";break;
480     case 20: fhz = "琼";break; case 21: fhz = "陕";break; case 22: fhz = "苏";break; case 23: fhz = "皖";break;
481     case 24: fhz = "湘";break; case 25: fhz = "新";break; case 26: fhz = "渝";break; case 27: fhz = "豫";break;
482     case 28: fhz = "粤";break; case 29: fhz = "云";break; case 30: fhz = "浙";break;
483     }
484     //cout << "return"<<endl;
485     return (fhz);
486 }
487
488 string db_successlv_2(IplImage *cs)
489 {
490     string fhz = "\0";
491     uchar *pt_cs = (uchar *)cs->imageData;
492     uchar i = 0;
493     uchar max = 0;
494     uchar max_backup = 0;
495     uchar zf  = 0;
496     for(i = 0; i < 24; i++)
497     {
498         IplImage *mb = cvLoadImage(mb_ku_zf[i], 1);
499         uchar cgl = 0;
500
501         int cg_count = 0;
502         int bd_count = 0;
503         uchar *pt_mb = (uchar *)mb->imageData;
504         const uchar step_cs = cs->widthStep;
505         const uchar step_mb = mb->widthStep;
506         for(int w = 0; w < cs->width; w++)
507             for(int h = 0; h < cs->height; h++)
508             {
509                 if((pt_cs[h*step_cs + w] == pt_mb[h*step_mb + w]))
510                     cg_count++;
511                 if(pt_mb[h*step_mb + w])
512                     bd_count++;
513             }
514         cvReleaseImage(&mb);
515             cgl = (uchar)(((float)cg_count/(cs->height*cs->width))*100);
516         max = max<cgl? cgl : max;
517         if(max != max_backup)
518             zf = i;
519         max_backup = max;
520         //printf("wz_2  i=%d,zf=%d,max=%d\n",(int)i,(int)zf,(int)max);
521     }
522     switch(zf)
523     {
524     case 0: fhz = "A";break; case 1: fhz = "B";break;
525     case 2: fhz = "C";break; case 3: fhz = "D";break; case 4: fhz = "E";break; case 5: fhz = "F";break;
526     case 6: fhz = "G";break; case 7: fhz = "H";break; case 8: fhz = "J";break; case 9: fhz = "K";break;
527     case 10: fhz = "L";break; case 11: fhz = "M";break; case 12: fhz = "N";break; case 13: fhz = "P";break;
528     case 14: fhz = "Q";break; case 15: fhz = "R";break; case 16: fhz = "S";break; case 17: fhz = "T";break;
529     case 18: fhz = "U";break; case 19: fhz = "V";break; case 20: fhz = "W";break; case 21: fhz = "X";break;
530     case 22: fhz = "Y";break; case 23: fhz = "Z";break;
531     }
532     return (fhz);
533 }
534
535 string db_successlv_4_7(IplImage *cs)
536 {
537     string fhz = "\0";
538     uchar *pt_cs = (uchar *)cs->imageData;
539     uchar i = 0;
540     uchar max = 0;
541     uchar max_backup = 0;
542     uchar zf  = 0;
543     for(i = 0; i < 10; i++)
544     {
545         IplImage *mb = cvLoadImage(mb_ku_sz[i], 1);
546         uchar cgl = 0;
547
548         int cg_count = 0;
549         int bd_count = 0;
550         uchar *pt_mb = (uchar *)mb->imageData;
551         const uchar step_cs = cs->widthStep;
552         const uchar step_mb = mb->widthStep;
553         for(int w = 0; w < cs->width; w++)
554             for(int h = 0; h < cs->height; h++)
555             {
556                 if((pt_cs[h*step_cs + w] == pt_mb[h*step_mb + w]))
557                     cg_count++;
558                 if(pt_mb[h*step_mb + w])
559                     bd_count++;
560             }
561         cvReleaseImage(&mb);
562             cgl = (uchar)(((float)cg_count/(cs->height*cs->width))*100);
563         max = max<cgl? cgl : max;
564         if(max != max_backup)
565             zf = i;
566         max_backup = max;
567     }
568     switch(zf)
569     {
570     case 0: fhz = "0";break; case 1: fhz = "1";break; case 2: fhz = "2";break; case 3: fhz = "3";break;
571     case 4: fhz = "4";break; case 5: fhz = "5";break; case 6: fhz = "6";break; case 7: fhz = "7";break;
572     case 8: fhz = "8";break; case 9: fhz = "9";break;
573     }
574     return (fhz);
575 }

char

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

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

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

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

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

 

 

时间: 2024-10-02 07:02:50

基于opencv的车牌识别系统的相关文章

python基于OpenCV的人脸识别系统

想获得所有的代码,请下载(来自我的CSDN): https://download.csdn.net/download/qq_40875849/11292912 主函数: from recognition import recognition from training import training from datasets import datasets from delFile import del_file def main(): facedict = {} cur_path = r'.

基于SVM与人工神经网络的车牌识别系统

最近研究了支持向量机(Support Vector Machine,SVM)和人工神经网络(Artifical Neural Network,ANN)等模式识别理论,结合OpenCV的书:<Mastering OpenCV with Practical Computer Vision Projects>,将两种思想运用到车辆的车牌识别算法中.车辆识别结合了多种图像处理技术,如视频监控.图像检测.图像分割和光学字符识别(OCR)等,在道路交通监控中有着重要的作用.以下内容主要包含几个方面: 车牌

基于QT和OpenCV的人脸识别系统

1 系统方案设计 1.1 引言 人脸是一个常见而复杂的视觉模式,人脸所反映的视觉信息在人与人的交流和交往中有着重 要的作用和意义,对人脸进行处理和分析在视频监控.出入口控制.视频会议以及人机交互等领 域都有着广泛的应用前景,因此是模式识别和计算机视觉领域持续的研究热点. 本系统在 FriendlyARM Tiny6410 开发板基础上,利用 OpenCV 计算机视觉库和 QT 图形库,通 过普通的 USB 摄像头实现了自动人脸识别,准确率较高,方便易用. 1.2 系统总体架构 "人脸识别&quo

EasyPR是一个中文的开源车牌识别系统

EasyPR EasyPR是一个中文的开源车牌识别系统,其目标是成为一个简单.高效.准确的车牌识别引擎. 相比于其他的车牌识别系统,EasyPR有如下特点: 它基于openCV这个开源库.这意味着你可以获取全部源代码,并且移植到opencv支持的所有平台. 它能够识别中文.例如车牌为苏EUK722的图片,它可以准确地输出std:string类型的"苏EUK722"的结果. 它的识别率较高.图片清晰情况下,车牌检测与字符识别可以达到80%以上的精度. 跨平台 目前除了windows平台以

手机端车牌识别系统(支持安卓、ios系统)

私家车的数量的急剧增长,既带来了喜也同样带来悲.一方面给我们的生活带来的了很多便利,另一方面也同样带来了交通拥堵.交通事故等问题.因为对于车辆的管理尤为重要! 比如说违章停车登记,传统方法是:执法人员通过携带的数码相机对违法停车的车辆拍照取证,然后手动输入车牌号码进行登记. 针对于这种违章停车的管理问题,北京易泊时代研发了一款基于安卓/ios的手机端车牌识别系统, 执法人员通过持有集成了安卓ios移动端车牌识别系统的手机,通过摄像头对违法停车车辆进行拍照取证的同时,可以自动获取车牌号码.违法停车

车牌识别系统,助力智慧城市

城市在发展进程中总会遇到各种各样的问题,如今看来,例如停车,停车难已经成为一线二线城市,城市化过程中一个畅聊的话题,停车位少.停车位不好找.停车收费慢等等,所以今天我们要讨论的话题就是车牌识别一体机对提高城市停车管理的重要性,车牌识别一体机不仅可以减轻停车场负担,收费难管理难的压力,还能为安防等行业,提供便利. 城市在设计的过程中,优化了停车场的布局,在建设停车场的时候更加的人性化.方便化,比如立体车库的不断涌现.当然,我们如何知道停车场内是否有空余车位.哪个位置有停车位.这就离不开车牌识别的作

基于 OpenCV 的人脸识别

基于 OpenCV 的人脸识别 一点背景知识 OpenCV 是一个开源的计算机视觉和机器学习库.它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包.根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从谷歌街景的图片拼接,到交互艺术展览的技术实现中,都有 OpenCV 的身影. OpenCV 起始于 1999 年 Intel 的一个内部研究项目.从那时起,它的开发就一直很活跃.进化到现在,它已支持如 OpenCL 和 OpenGL 的多种现代技术,也支持如 iOS

车牌识别系统应用之“无感支付”

好消息来了! 本月底前山东高速管辖范围内的所有收费站出口都将实现"无感支付"!又是一项车牌识别系统的应用. 未来将实现不停车不掏手机 刷一下车牌, 自动抬杆就走人~ 超方便! 什么是"无感支付"? "无感支付"就是采用"车牌识别+手机APP"的模式,实现车主自助绑定车牌和支付方式,出口车道无干预地完成通行费快速支付,车辆不停车即可成功付费的互联网支付产品"ITC",是传统ETC业务的升级产品. 由于目前仅有

opencv实现车牌识别之字符识别

简介 在前面已经讲了车牌的定位和对车牌字符的分割,这里继续是最后对车牌的识别. 字符识别 主要是用了两张办法,第一个是前面 <opencv实现车牌识别之失败经验> 这一篇中用到过的,opencv自带的getPSNR函数,这里不再对它进行讲解. 另一种方法是将分割出来的字符和模板字符都分割成9宫格形式,对比比较每个块中,像素占的比例来匹配分辨出字符. 具体代码如下: double proCale(Mat& mat1, int width_1, int height_1, int widt