zoukankan      html  css  js  c++  java
  • ann

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

    这篇文章接着之前的车牌识别,从输入的车图片中分割识别出车牌之后,将进行下一步:车牌号的识别,这里主要使用光学字符识别车牌字符。对每个检测到的车牌,将其每个字符分割出来,然后使用人工神经网络(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个神经元的隐藏层。

    每个神经元通过输入权重加上一个偏移项来计算输出值,并由所选择的激励函数进行转换。神经元结构为:

    这里写图片描述

    常见的激励函数有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 <<"
    ";
                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("
    ");
        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. 另外,检测出的字符与原车牌的顺序有乱,应该进行调整(待续)

  • 相关阅读:
    JS字符串去重
    svn回退到某一版本
    WebStorm格式化代码4个空格设置
    DevExpress中 的DataGrid每一行根据其类型显示控件的种类
    各大系统刷新DNS缓存方法
    Kali Linux中前十名的Wifi攻击工具
    CentOS远程执行漏洞
    判断是否移动端的几种方法
    笔记
    Linux常用命令
  • 原文地址:https://www.cnblogs.com/fdd566/p/6549661.html
Copyright © 2011-2022 走看看