前言算法
學習了很長一段時間了,須要沉澱下,而最好的辦法就是作一個東西來應用學習的東西,同時也是一個學習的過程。數組
PS:這篇小文是畢業以前和同窗作的一個小項目,因此寫的比較匆忙,代碼也是直接粘貼的,基於qt開發的C++代碼,不能保證沒有錯誤,請慎重。不但願對你產生誤導,有任何問題能夠聯繫我,一塊兒探討下。最後,我如今已經沒有搞嵌入式方面的開發了。服務器
概述 ide
OpenCV的全稱是:Open Source Computer Vision Library。OpenCV是一個基於(開源)發行的跨平臺計算機視覺庫,能夠運行在Linux、Windows和Mac OS操做系統上。它輕量級並且高效——由一系列 C 函數和少許 C++ 類構成,同時提供了Python、Ruby、MATLAB等語言的接口,實現了圖像處理和計算機視覺方面的不少通用算法。函數
來自百度的解釋,之因此選擇opencv是由於:首先向學習一個新的東西來看看本身的學習接受能力,而後是感受opencv很酷,處理圖片真實說一是一的(你能夠理解爲處理圖片很方便)。學習
車牌識別系統重點在於車牌的識別,還有後臺的處理。要使它成爲一個系統,缺一不可。spa
大體上分爲三個部分:信息採集和傳輸,接收圖片並識別客戶端請求,信息的存儲和查詢操作系統
1.信息採集和傳輸debug
這裏咱們採用的是 網上買的小攝像頭+網上的開源項目mjpg-streamcode
對於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 }
代碼中對截取車牌進行了操做
下面是字符的識別:字符識別有不少方法,可是都是算法的,我研究的不是很深,選取了最簡單的一種,本身作字符庫,而後比對。
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 }
前面的路徑中就是字符庫的圖片路徑。
最後能夠獲得車牌號碼的 字符串,接下來就是後臺的處理。
3.對進出用戶的信息存儲和讀取。
這裏咱們使用的是Qt界面程序語言編寫的客戶端。
這裏是真正的發揮空間,能夠使用得來的數據進行存儲,還有手機客戶端給用戶信息。