ann

轉自 http://blog.csdn.net/yiluoyan/article/details/45308785ios

 

這篇文章接着以前的車牌識別,從輸入的車圖片中分割識別出車牌以後,將進行下一步:車牌號的識別,這裏主要使用光學字符識別車牌字符。對每一個檢測到的車牌,將其每一個字符分割出來,而後使用人工神經網絡(artificial neural network,ANN)學習算法識別字符。算法

1.字符分割 
將得到的車牌圖像進行直方圖均衡,而後採用閾值濾波器對圖像進行處理,而後查找字符輪廓。數組

原圖像: 
這裏寫圖片描述網絡

閾值圖像: 
這裏寫圖片描述數據結構

查找輪廓,後畫出其外接矩形圖像: 
這裏寫圖片描述函數

而後將字符逐一分割,學習

這裏寫圖片描述

分割code:測試

#include <iostream> #include <stdlib.h> #include <vector> #include <cv.h> #include <highgui.h> #include <ml.h> #include <cvaux.h> using namespace std; using namespace cv; #define HORIZONTAL 1 #define VERTICAL 0 bool verifySizes(Mat r) //驗證框出來的區域是否爲字符 { //char sizes 45*77 float aspect = 45.0f / 77.0f; //字符的寬高比爲 45/77 float charAspect = (float) r.cols / (float) r.rows; float error = 0.35; float minHeight = 15; float maxHeight = 28; float minAspect = 0.2; float maxAspect = aspect + aspect * error; float area = countNonZero(r); //統計區域像素 float bbArea = r.cols * r.rows; //區域面積 float percPixels = area / bbArea; //像素比值 if(percPixels < 0.8 && charAspect > minAspect && charAspect < maxAspect && r.rows >= minHeight && r.rows < maxHeight) return true; else return false; } Mat preprocessChar(Mat in) { int h = in.rows; int w = in.cols; int charSize = 20; //統一字符大小 Mat transformMat = Mat :: eye(2, 3, CV_32F); int m = max (w, h); transformMat.at<float>(0,2) = m/2 -w/2; transformMat.at<float>(1,2) = m/2 -h/2; Mat warpImage(m, m, in.type()); warpAffine(in, warpImage, transformMat, warpImage.size(), INTER_LINEAR, BORDER_CONSTANT,Scalar(0)); Mat out; resize(warpImage, out, Size( charSize, charSize)); return out; } //計算累積直方圖 Mat ProjectedHistogram(Mat img, int t) { int sz = (t) ? img.rows :img.cols; Mat mhist = Mat :: zeros(1, sz, CV_32F); for (int j =0; j < sz; j++) { Mat data = (t)? img.row(j) : img.col(j); mhist.at<float>(j) = countNonZero(data); //統計這一行/列中的非零元素個數,保存到mhist中 } double min, max; minMaxLoc(mhist, &min, &max); if (max > 0) { mhist.convertTo(mhist, -1, 1.0f / max, 0); // 用mhist直方圖的最大值,歸一化直方圖 } return mhist; } Mat getVisualHistogram(Mat *hist, int type) { int size =100; Mat imHist; if(type == HORIZONTAL) imHist.create(Size(size, hist->cols), CV_8UC3 ); else imHist.create(Size(hist->cols, size), CV_8UC3); imHist = Scalar(55, 55, 55); for (int i = 0; i < hist->cols; i++) { float value = hist->at<float>(i); int maxval = (int) (value * size); Point pt1; Point pt2, pt3, pt4; if (type == HORIZONTAL) { pt1.x = pt3.x = 0; pt2.x = pt4.x = maxval; pt1.y = pt2.y = i; pt3.y = pt4.y = i+1; line(imHist, pt1, pt2, CV_RGB(220, 220, 220), 1, 8, 0); line(imHist, pt3, pt4, CV_RGB(34, 34, 34), 1, 8, 0); pt3.y = pt4.y = i+2; line(imHist, pt3, pt4, CV_RGB(44, 44, 44), 1, 8, 0); pt3.y = pt4.y = i+3; line(imHist, pt3, pt4, CV_RGB(50, 50, 50), 1, 8, 0); } else { pt1.x = pt2.x = i; pt3.x = pt4.x = i+1; pt1.y = pt3.y = 100; pt2.y = pt4.y = 100 - maxval; line(imHist, pt1, pt2, CV_RGB(220, 220, 220), 1, 8, 0); line(imHist, pt3, pt4, CV_RGB(34, 34, 34), 1, 8, 0); pt3.x = pt4.x = i+2; line(imHist, pt3, pt4, CV_RGB(44, 44, 44), 1, 8, 0); pt3.x = pt4.x =i + 3; line(imHist, pt3, pt4, CV_RGB(50, 50, 50), 1, 8, 0); } } return imHist; } void drawVisualFeatures(Mat charcter, Mat hhist, Mat vhist, Mat lowData, int count) { Mat img(121, 121, CV_8UC3, Scalar(0,0,0)); Mat ch; Mat ld; char res[20]; cvtColor(charcter, ch, CV_GRAY2BGR); resize(lowData, ld, Size(100, 100), 0, 0, INTER_NEAREST); //將ld從15*15擴大到100*100 cvtColor(ld, ld, CV_GRAY2BGR); Mat hh = getVisualHistogram(&hhist, HORIZONTAL); Mat hv = getVisualHistogram(&vhist, VERTICAL); Mat subImg = img(Rect(0, 101, 20, 20)); //ch:20*20 ch.copyTo(subImg); subImg = img(Rect(21, 101, 100, 20)); //hh:100*hist.cols hh.copyTo(subImg); subImg = img(Rect(0, 0, 20, 100)); //hv:hist.cols*100 hv.copyTo(subImg); subImg = img(Rect(21, 0, 100, 100)); //ld:100*100 ld.copyTo(subImg); line( img, Point(0, 100), Point(121, 100), Scalar(0,0,255) ); line( img, Point(20, 0), Point(20, 121), Scalar(0,0,255) ); stringstream ss(stringstream::in | stringstream::out); ss << "E://opencvcodetext//ANPR//"<<"hist"<< "_" << count <<" .jpg"; imwrite(ss.str(), img); imshow("visual feature",img); //顯示特徵 cvWaitKey(0); } Mat features(Mat in, int sizeData, int count) { //直方圖特徵 Mat vhist = ProjectedHistogram(in, VERTICAL); Mat hhist = ProjectedHistogram(in, HORIZONTAL); Mat lowdata; //低分辨圖像特徵 sizeData * sizeData resize(in, lowdata, Size(sizeData, sizeData)); drawVisualFeatures(in, hhist, vhist, lowdata, count); //畫出直方圖 int numCols = vhist.cols + hhist.cols + lowdata.cols * lowdata.cols; Mat out = Mat::zeros(1, numCols, CV_32F); int j = 0; for (int i =0; i <vhist.cols; i++) { out.at<float>(j) = vhist.at<float>(i); j++; } for (int i = 0; i < hhist.cols; i++) { out.at<float>(j) = hhist.at<float>(i); j++; } for (int x = 0; x <lowdata.cols; x++) { for (int y = 0; y < lowdata.rows; y++) { out.at<float>(j) = (float)lowdata.at<unsigned char>(x, y); j++; } } return out; } int main(int argc, char const *argv[]) { Mat input = imread("E://opencvcodetext//ANPR//img_2.jpg"); cvtColor(input,input,CV_RGB2GRAY); imshow("srcimg",input); Mat img_threshold; //存放二值化後的車牌 threshold(input, img_threshold, 60, 255, CV_THRESH_BINARY_INV); //CV_THRESH_BINARY_INV參數可將白色點變爲黑色,黑色點變爲白色 imshow("閾值化車牌",img_threshold); Mat img_contours ; //存放車牌號輪廓 img_threshold.copyTo(img_contours); //複製圖像 //查找字符的輪廓 vector < vector <Point> > contours; //使用向量格式存儲輪廓 findContours(img_contours, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); //把找到的輪廓畫出來 Mat result; input.copyTo(result); //先複製車牌圖像 cvtColor(result, result, CV_GRAY2BGR); //轉爲彩色圖像,方便看輪廓 vector <vector <Point> >::iterator itc = contours.begin();//定義一個迭代器訪問輪廓 int i = 0; while (itc != contours.end()) { Rect mr = boundingRect( Mat(* itc)); //建立框圖 rectangle(result, mr, Scalar(255, 0, 0), 2); Mat auxRoi(img_threshold, mr); //根據輪廓裁剪出字符 if (verifySizes(auxRoi)) //判斷是不是字符 { auxRoi = preprocessChar(auxRoi); //對字符進行處理 //sprintf(res, "train_data_%d,jpg",i); i++; stringstream ss(stringstream::in | stringstream::out); ss << "E://opencvcodetext//ANPR//"<<"train_data"<< "_" << i <<" .jpg"; imwrite(ss.str(), auxRoi); //imwrite(res,auxRoi); rectangle(result, mr, Scalar(0, 255, 0),2); Mat f = features(auxRoi, 15, i); //提取字符的直方圖特徵 } ++itc; } imwrite("E://opencvcodetext//ANPR//result1.jpg",result); imshow("car_plate",result); cvWaitKey(20); system("pause"); return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266

2.人工神經網絡(ANN) 
分類字符這一步將使用人工神經網絡,即便用多層感知器(Multi-Layer Perceptron, MLP). MLP 由一個輸入層、一個輸出層和一個或多個隱藏層的 神經網絡組成。每層有一個或多個神經元痛前一層和後一層相連。 
以下圖是一個3層的神經元感知器,有3個輸入和2個輸出,以及包含5個神經元的隱藏層。ui

每一個神經元經過輸入權重加上一個偏移項來計算輸出值,並由所選擇的激勵函數進行轉換。神經元結構爲:spa

這裏寫圖片描述

常見的激勵函數有S型、高斯型、上圖的hadrlim型。單層的單個神經元能夠將輸入向量分爲兩類,而一個有S個神經元的感知機,能夠將輸入向量分爲2^S類

神經網絡的詳細理論能夠參考:http://blog.csdn.net/zzwu/article/details/575050

3.特徵提取及訓練分類器

與SVM分類相似,使用ANN算法識別字符一樣須要創建分類器、訓練分類器,最後使用分類器識別字符。這裏咱們使用的特徵不是像素值,而是分割字符水平和豎直的累積直方圖與字符的低分辨率圖像。

對每個字符,經過使用countNonZero函數來按行或按列統計非零像素值個數,將其保存在mhist中,並對mhist進行歸一化處理。

獲得的特徵圖像以下圖所示:(左下角爲字符圖像原始大小20*20,由上角爲低分辨率採樣後放大的圖像100*100,右下角爲水平直方圖,左上角爲垂直直方圖)

這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述 這裏寫圖片描述

提取特徵完畢後,將特徵與對應的標註寫到xml文件中,code以下:

#include <iostream> #include <stdlib.h> #include <vector> #include <cv.h> #include <highgui.h> #include <ml.h> #include <cvaux.h> using namespace std; using namespace cv; #define HORIZONTAL 1 #define VERTICAL 0 //針對書本的西班牙車牌,一共有30個字符(10個數字和20個字母),下面的數組存儲的是每一個字符的圖片個數 const int numFilesChar[] = {35, 40, 42, 41, 42, 33, 30, 31, 49, 44, 30, 24, 21, 20, 34, 9, 10, 3, 11, 3, 15, 4, 9, 12, 10, 21, 18, 8, 15, 7}; const char strCharacters[] = {'0','1','2','3','4','5','6','7','8','9','B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z'}; const int numCharacters = 30; //下面這些參數是本身試驗的時候設置的一個較爲簡單的驗證 //const int numFilesChar[] = {1, 1, 1, 1, 1, 1, 1}; //const char strCharacters[] = {'1','2','5','7', 'D', 'T', 'Z'}; //const int numCharacters = 7; bool verifySizes(Mat r) //驗證框出來的區域是否爲字符 { //char sizes 45*77 float aspect = 45.0f / 77.0f; //字符的寬高比爲 45/77 float charAspect = (float) r.cols / (float) r.rows; float error = 0.35; float minHeight = 15; float maxHeight = 28; float minAspect = 0.2; float maxAspect = aspect + aspect * error; float area = countNonZero(r); //統計區域像素 float bbArea = r.cols * r.rows; //區域面積 float percPixels = area / bbArea; //像素比值 if(percPixels < 0.8 && charAspect > minAspect && charAspect < maxAspect && r.rows >= minHeight && r.rows < maxHeight) return true; else return false; } Mat preprocessChar(Mat in) { int h = in.rows; int w = in.cols; int charSize = 20; //統一字符大小 Mat transformMat = Mat :: eye(2, 3, CV_32F); int m = max (w, h); transformMat.at<float>(0,2) = m/2 -w/2; transformMat.at<float>(1,2) = m/2 -h/2; Mat warpImage(m, m, in.type()); warpAffine(in, warpImage, transformMat, warpImage.size(), INTER_LINEAR, BORDER_CONSTANT,Scalar(0)); Mat out; resize(warpImage, out, Size( charSize, charSize)); return out; } //計算累積直方圖 Mat ProjectedHistogram(Mat img, int t) { int sz = (t) ? img.rows :img.cols; Mat mhist = Mat :: zeros(1, sz, CV_32F); for (int j =0; j < sz; j++) { Mat data = (t)? img.row(j) : img.col(j); mhist.at<float>(j) = countNonZero(data); //統計這一行/列中的非零元素個數,保存到mhist中 } double min, max; minMaxLoc(mhist, &min, &max); if (max > 0) { mhist.convertTo(mhist, -1, 1.0f / max, 0); // 用mhist直方圖的最大值,歸一化直方圖 } return mhist; } Mat getVisualHistogram(Mat *hist, int type) { int size =100; Mat imHist; if(type == HORIZONTAL) imHist.create(Size(size, hist->cols), CV_8UC3 ); else imHist.create(Size(hist->cols, size), CV_8UC3); imHist = Scalar(55, 55, 55); for (int i = 0; i < hist->cols; i++) { float value = hist->at<float>(i); int maxval = (int) (value * size); Point pt1; Point pt2, pt3, pt4; if (type == HORIZONTAL) { pt1.x = pt3.x = 0; pt2.x = pt4.x = maxval; pt1.y = pt2.y = i; pt3.y = pt4.y = i+1; line(imHist, pt1, pt2, CV_RGB(220, 220, 220), 1, 8, 0); line(imHist, pt3, pt4, CV_RGB(34, 34, 34), 1, 8, 0); pt3.y = pt4.y = i+2; line(imHist, pt3, pt4, CV_RGB(44, 44, 44), 1, 8, 0); pt3.y = pt4.y = i+3; line(imHist, pt3, pt4, CV_RGB(50, 50, 50), 1, 8, 0); } else { pt1.x = pt2.x = i; pt3.x = pt4.x = i+1; pt1.y = pt3.y = 100; pt2.y = pt4.y = 100 - maxval; line(imHist, pt1, pt2, CV_RGB(220, 220, 220), 1, 8, 0); line(imHist, pt3, pt4, CV_RGB(34, 34, 34), 1, 8, 0); pt3.x = pt4.x = i+2; line(imHist, pt3, pt4, CV_RGB(44, 44, 44), 1, 8, 0); pt3.x = pt4.x =i + 3; line(imHist, pt3, pt4, CV_RGB(50, 50, 50), 1, 8, 0); } } return imHist; } void drawVisualFeatures(Mat charcter, Mat hhist, Mat vhist, Mat lowData, int count) { Mat img(121, 121, CV_8UC3, Scalar(0,0,0)); Mat ch; Mat ld; char res[20]; cvtColor(charcter, ch, CV_GRAY2BGR); resize(lowData, ld, Size(100, 100), 0, 0, INTER_NEAREST); //將ld從15*15擴大到100*100 cvtColor(ld, ld, CV_GRAY2BGR); Mat hh = getVisualHistogram(&hhist, HORIZONTAL); Mat hv = getVisualHistogram(&vhist, VERTICAL); Mat subImg = img(Rect(0, 101, 20, 20)); //ch:20*20 ch.copyTo(subImg); subImg = img(Rect(21, 101, 100, 20)); //hh:100*hist.cols hh.copyTo(subImg); subImg = img(Rect(0, 0, 20, 100)); //hv:hist.cols*100 hv.copyTo(subImg); subImg = img(Rect(21, 0, 100, 100)); //ld:100*100 ld.copyTo(subImg); line( img, Point(0, 100), Point(121, 100), Scalar(0,0,255) ); line( img, Point(20, 0), Point(20, 121), Scalar(0,0,255) ); stringstream ss(stringstream::in | stringstream::out); ss << "E://opencvcodetext//ANPR//"<<"hist"<< "_" << count <<" .jpg"; imwrite(ss.str(), img); /*sprintf(res, "hist%d.jpg",count); imwrite(res, img);*/ imshow("visual feature",img); cvWaitKey(0); } Mat features(Mat in, int sizeData, int count) { //直方圖特徵 Mat vhist = ProjectedHistogram(in, VERTICAL); Mat hhist = ProjectedHistogram(in, HORIZONTAL); Mat lowdata; //低分辨圖像特徵 sizeData * sizeData resize(in, lowdata, Size(sizeData, sizeData)); drawVisualFeatures(in, hhist, vhist, lowdata, count); //畫出直方圖 int numCols = vhist.cols + hhist.cols + lowdata.cols * lowdata.cols; Mat out = Mat::zeros(1, numCols, CV_32F); int j = 0; for (int i =0; i <vhist.cols; i++) { out.at<float>(j) = vhist.at<float>(i); j++; } for (int i = 0; i < hhist.cols; i++) { out.at<float>(j) = hhist.at<float>(i); j++; } for (int x = 0; x <lowdata.cols; x++) { for (int y = 0; y < lowdata.rows; y++) { out.at<float>(j) = (float)lowdata.at<unsigned char>(x, y); j++; } } return out; } Mat Features(Mat in, int sizeData) { Mat vhist = ProjectedHistogram(in, VERTICAL); Mat hhist = ProjectedHistogram(in, HORIZONTAL); Mat lowData; resize( in, lowData, Size (sizeData, sizeData)); int numCols = vhist.cols + hhist.cols + lowData.cols *lowData.cols; Mat out = Mat ::zeros(1, numCols, CV_32F); //將特徵寫到矩陣中 int j = 0; for (int i = 0; i < vhist.cols; i++) { out.at <float> (j) = vhist.at<float>(i); j++; } for (int i =0; i < hhist.cols; i++) { out.at<float>(j) = (float) hhist.at <float> (i); j++; } for (int x = 0; x < lowData.cols; x++) { for (int y = 0; y < lowData.rows; y++) { out.at<float>(j) = (float) lowData.at<unsigned char>(x,y); j++; } } return out; } int main(int argc, char const *argv[]) { //char *path = "E://opencvcodetext//ANPR//characters"; Mat classes; Mat trainingDataf5; Mat trainingDataf10; Mat trainingDataf15; Mat trainingDataf20; vector <int> trainingLabels; for (int i = 0; i < numCharacters; i++) { int numFiles = numFilesChar[i]; for (int j = 0; j < numFiles; j++) { cout << "Character " << strCharacters[i] << " files" << j <<"\n"; stringstream ss (stringstream::in |stringstream::out); ss << "E://opencvcodetext//ANPR//characters//" << strCharacters[i] <<"1.jpg"; Mat img = imread(ss.str(), 0); //Mat img = imread("E://opencvcodetext//ANPR//characters//21.jpg",0); imshow("char",img); Mat f5 = Features(img, 5); Mat f10 = Features(img, 10); Mat f15 = Features(img, 15); Mat f20 = Features(img, 20); trainingDataf5.push_back(f5); trainingDataf10.push_back(f10); trainingDataf15.push_back(f15); trainingDataf20.push_back(f20); trainingLabels.push_back(i); //每一幅字符圖片所對應的字符類別索引下標 } } //將矩陣轉換成浮點矩陣 trainingDataf5.convertTo(trainingDataf5, CV_32FC1); trainingDataf10.convertTo(trainingDataf10, CV_32FC1); trainingDataf15.convertTo(trainingDataf15,CV_32FC1); trainingDataf20.convertTo(trainingDataf20,CV_32FC1); Mat (trainingLabels).convertTo(classes, CV_32FC1); FileStorage fs("E://opencvcodetext//ANPR//characters//OCR.xml",FileStorage::WRITE); fs << "trainingDataF5" << trainingDataf5; fs << "trainingDataF10" << trainingDataf10; fs <<"trainingDataF15" << trainingDataf15; fs << "trainingDataF20" << trainingDataf20; fs <<"classes" <<classes; cvWaitKey(20); system("pause"); return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  1. 字符分類

(1) 獲得ANN訓練文件xml後,利用OpenCV中的CvANN_MLP類來使用ANN算法,識別字符。先經過create函數初始化該類,初始化時須要指定神經網絡的層數、神經元數、激勵函數、alpha和beta。

(2)訓練完ANN分類器後,可使用predict函數來對特徵向量分類,該函數返回一行,大小爲類的數量,該向量的每個元素安陽了輸入樣本屬於每一個類的機率。字符的類別有向量中的最大值肯定。 
分類的code:

#include <iostream> #include <stdlib.h> #include <vector> #include <cv.h> #include <highgui.h> #include <ml.h> #include <cvaux.h> using namespace std; using namespace cv; #define HORIZONTAL 1 #define VERTICAL 0 CvANN_MLP ann; //針對書本的西班牙車牌,一共有30個字符(10個數字和20個字母),下面的數組存儲的是每一個字符的圖片個數 const int numFilesChar[] = {35, 40, 42, 41, 42, 33, 30, 31, 49, 44, 30, 24, 21, 20, 34, 9, 10, 3, 11, 3, 15, 4, 9, 12, 10, 21, 18, 8, 15, 7}; const char strCharacters[] = {'0','1','2','3','4','5','6','7','8','9','B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z'}; const int numCharacters = 30; //const int numFilesChar[] = {1, 1, 1, 1, 1, 1, 1}; //const char strCharacters[] = {'1','2','5','7', 'D', 'T', 'Z'}; //const int numCharacters = 7; bool verifySizes(Mat r) //驗證框出來的區域是否爲字符 { //char sizes 45*77 float aspect = 45.0f / 77.0f; //字符的寬高比爲 45/77 float charAspect = (float) r.cols / (float) r.rows; float error = 0.35; float minHeight = 15; float maxHeight = 28; float minAspect = 0.2; float maxAspect = aspect + aspect * error; float area = countNonZero(r); //統計區域像素 float bbArea = r.cols * r.rows; //區域面積 float percPixels = area / bbArea; //像素比值 if(percPixels < 0.8 && charAspect > minAspect && charAspect < maxAspect && r.rows >= minHeight && r.rows < maxHeight) return true; else return false; } Mat preprocessChar(Mat in) { int h = in.rows; int w = in.cols; int charSize = 20; //統一字符大小 Mat transformMat = Mat :: eye(2, 3, CV_32F); int m = max (w, h); transformMat.at<float>(0,2) = m/2 -w/2; transformMat.at<float>(1,2) = m/2 -h/2; Mat warpImage(m, m, in.type()); warpAffine(in, warpImage, transformMat, warpImage.size(), INTER_LINEAR, BORDER_CONSTANT,Scalar(0)); Mat out; resize(warpImage, out, Size( charSize, charSize)); return out; } //計算累積直方圖 Mat ProjectedHistogram(Mat img, int t) { int sz = (t) ? img.rows :img.cols; Mat mhist = Mat :: zeros(1, sz, CV_32F); for (int j =0; j < sz; j++) { Mat data = (t)? img.row(j) : img.col(j); mhist.at<float>(j) = countNonZero(data); //統計這一行/列中的非零元素個數,保存到mhist中 } double min, max; minMaxLoc(mhist, &min, &max); if (max > 0) { mhist.convertTo(mhist, -1, 1.0f / max, 0); // 用mhist直方圖的最大值,歸一化直方圖 } return mhist; } Mat getVisualHistogram(Mat *hist, int type) { int size =100; Mat imHist; if(type == HORIZONTAL) imHist.create(Size(size, hist->cols), CV_8UC3 ); else imHist.create(Size(hist->cols, size), CV_8UC3); imHist = Scalar(55, 55, 55); for (int i = 0; i < hist->cols; i++) { float value = hist->at<float>(i); int maxval = (int) (value * size); Point pt1; Point pt2, pt3, pt4; if (type == HORIZONTAL) { pt1.x = pt3.x = 0; pt2.x = pt4.x = maxval; pt1.y = pt2.y = i; pt3.y = pt4.y = i+1; line(imHist, pt1, pt2, CV_RGB(220, 220, 220), 1, 8, 0); line(imHist, pt3, pt4, CV_RGB(34, 34, 34), 1, 8, 0); pt3.y = pt4.y = i+2; line(imHist, pt3, pt4, CV_RGB(44, 44, 44), 1, 8, 0); pt3.y = pt4.y = i+3; line(imHist, pt3, pt4, CV_RGB(50, 50, 50), 1, 8, 0); } else { pt1.x = pt2.x = i; pt3.x = pt4.x = i+1; pt1.y = pt3.y = 100; pt2.y = pt4.y = 100 - maxval; line(imHist, pt1, pt2, CV_RGB(220, 220, 220), 1, 8, 0); line(imHist, pt3, pt4, CV_RGB(34, 34, 34), 1, 8, 0); pt3.x = pt4.x = i+2; line(imHist, pt3, pt4, CV_RGB(44, 44, 44), 1, 8, 0); pt3.x = pt4.x =i + 3; line(imHist, pt3, pt4, CV_RGB(50, 50, 50), 1, 8, 0); } } return imHist; } void drawVisualFeatures(Mat charcter, Mat hhist, Mat vhist, Mat lowData, int count) { Mat img(121, 121, CV_8UC3, Scalar(0,0,0)); Mat ch; Mat ld; cvtColor(charcter, ch, CV_GRAY2BGR); resize(lowData, ld, Size(100, 100), 0, 0, INTER_NEAREST); //將ld從15*15擴大到100*100 cvtColor(ld, ld, CV_GRAY2BGR); Mat hh = getVisualHistogram(&hhist, HORIZONTAL); Mat hv = getVisualHistogram(&vhist, VERTICAL); Mat subImg = img(Rect(0, 101, 20, 20)); //ch:20*20 ch.copyTo(subImg); subImg = img(Rect(21, 101, 100, 20)); //hh:100*hist.cols hh.copyTo(subImg); subImg = img(Rect(0, 0, 20, 100)); //hv:hist.cols*100 hv.copyTo(subImg); subImg = img(Rect(21, 0, 100, 100)); //ld:100*100 ld.copyTo(subImg); line( img, Point(0, 100), Point(121, 100), Scalar(0,0,255) ); line( img, Point(20, 0), Point(20, 121), Scalar(0,0,255) ); stringstream ss(stringstream::in | stringstream::out); ss << "E://opencvcodetext//ANPR//"<<"hist"<< "_" << count <<" .jpg"; imwrite(ss.str(), img); /*sprintf(res, "hist%d.jpg",count); imwrite(res, img);*/ imshow("visual feature",img); cvWaitKey(0); } Mat features(Mat in, int sizeData, int count) { //直方圖特徵 Mat vhist = ProjectedHistogram(in, VERTICAL); Mat hhist = ProjectedHistogram(in, HORIZONTAL); Mat lowdata; //低分辨圖像特徵 sizeData * sizeData resize(in, lowdata, Size(sizeData, sizeData)); drawVisualFeatures(in, hhist, vhist, lowdata, count); //畫出直方圖 int numCols = vhist.cols + hhist.cols + lowdata.cols * lowdata.cols; Mat out = Mat::zeros(1, numCols, CV_32F); int j = 0; for (int i =0; i <vhist.cols; i++) { out.at<float>(j) = vhist.at<float>(i); j++; } for (int i = 0; i < hhist.cols; i++) { out.at<float>(j) = hhist.at<float>(i); j++; } for (int x = 0; x <lowdata.cols; x++) { for (int y = 0; y < lowdata.rows; y++) { out.at<float>(j) = (float)lowdata.at<unsigned char>(x, y); j++; } } return out; } Mat Features(Mat in, int sizeData) { Mat vhist = ProjectedHistogram(in, VERTICAL); Mat hhist = ProjectedHistogram(in, HORIZONTAL); Mat lowData; resize( in, lowData, Size (sizeData, sizeData)); int numCols = vhist.cols + hhist.cols + lowData.cols *lowData.cols; Mat out = Mat ::zeros(1, numCols, CV_32F); //將特徵寫到矩陣中 int j = 0; for (int i = 0; i < vhist.cols; i++) { out.at <float> (j) = vhist.at<float>(i); j++; } for (int i =0; i < hhist.cols; i++) { out.at<float>(j) = (float) hhist.at <float> (i); j++; } for (int x = 0; x < lowData.cols; x++) { for (int y = 0; y < lowData.rows; y++) { out.at<float>(j) = (float) lowData.at<unsigned char>(x,y); j++; } } return out; } void train(Mat TrainData, Mat classes, int nlayers) { Mat layerSizes(1, 3, CV_32SC1); layerSizes.at< int > (0) = TrainData.cols; layerSizes.at <int> (1) = nlayers; layerSizes.at < int > (2) = numCharacters; ann.create(layerSizes, CvANN_MLP :: SIGMOID_SYM, 1, 1); Mat trainClasses; trainClasses.create(TrainData.rows, numCharacters, CV_32FC1); for (int i =0; i < trainClasses.rows; i++) { for (int k = 0; k < trainClasses.cols; k++) { if( k == classes.at< int> (i)) trainClasses.at <float>(i,k)=1; else trainClasses.at<float>(i, k) = 0; } } Mat weights( 1, TrainData.rows, CV_32FC1, Scalar::all(1)); ann.train( TrainData, trainClasses, weights); //trained = true; } int Classify (Mat f) { int result = -1; Mat output( 1, numCharacters, CV_32FC1); ann.predict(f, output); Point maxLoc; double maxVal; minMaxLoc(output, 0, &maxVal, 0, &maxLoc); return maxLoc.x; } int main(int argc, char const *argv[]) { //char *path = "E://opencvcodetext//ANPR//characters"; Mat classes; Mat trainingData; FileStorage fs; fs.open("E:/opencvcodetext/ANPR/OCR.xml",FileStorage::READ); fs [ "TrainingDataF10"] >> trainingData; fs ["classes" ]>> classes; train(trainingData, classes, 10); //訓練神經網絡 Mat input = imread("E:/opencvcodetext/ANPR/img_2.jpg",CV_LOAD_IMAGE_GRAYSCALE); Mat img_threshold ; threshold( input, img_threshold, 60, 255, CV_THRESH_BINARY_INV); Mat img_contours; img_threshold.copyTo(img_contours); vector < vector <Point> > contours; findContours( img_contours, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); vector < vector <Point> > :: iterator itc = contours.begin(); while (itc != contours.end()) { Rect mr = boundingRect( Mat (*itc)); Mat auxRoi (img_threshold, mr); if (verifySizes(auxRoi)) { auxRoi = preprocessChar(auxRoi); Mat f = Features(auxRoi, 10); int charcter = Classify(f); printf("%c", strCharacters[charcter]); } ++itc; } printf("\n"); cvWaitKey(20); system("pause"); return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345

實驗結果:這裏的順序改變了,應該要還原字符的位置。。並且識別也不是百分百的準確,出現了錯誤:將 7 識別爲 T 了。 
原圖:這裏寫圖片描述

識別:這裏寫圖片描述

最後,寫一下調試程序的錯誤總結: 
1. 二值黑白圖像不等同於灰度圖像 
2. 圖像的像素值是unsight char的 
3. 在測試時,注意提取特徵的一一對應,注意TrainingDataF10以及後面的 Features(auxRoi, 10) 的關係。 4. 另外,檢測出的字符與原車牌的順序有亂,應該進行調整(待續)

相關文章
相關標籤/搜索