前言
学习了很长一段时间了,需要沉淀下,而最好的办法就是做一个东西来应用学习的东西,同时也是一个学习的过程。
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 }
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(©_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界面程序语言编写的客户端。
这里是真正的发挥空间,可以使用得来的数据进行存储,还有手机客户端给用户信息。