精华内容
下载资源
问答
  • 原理简单介绍:使用OpenCV中svm训练英文字符图片,进而识别。 资源包括完整代码,训练图像,测试图片
  • Python+OpenCV实实现现车车牌牌字字符符分分割割和和识识别别 这篇文章主要为大家详细介绍了Python+OpenCV实现车牌字符分割和识别文中示例代码介绍的非常详细具有 一定的参考价值感兴 的小伙伴们可以参考一下 最近做...
  • 自己做车牌识别用的字符模板,可用于以字符相减的方法识别字符使用。也是自己东拼西凑后筛选出来的,还是比较好用的。
  • 主要为大家详细介绍了Python+OpenCV实现车牌字符分割和识别,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 基于qt5.1.1与opencv2.4.7车牌字符切割与字符识别demo,内有注释详解,适合新手学习,需要这方面资料的同学可以在此处下载
  • opencv 车牌 字符识别

    2015-02-13 13:42:50
    基于opencv实现的车牌号做字符识别
  • 想通过svm实现多字符的分类,可以通过一对其它的方式,例如1,2,3,4,5个数,创造出四个向量机,分别是1对2-5,2对3-5,3对4和5,4对5。 注意事项: 1.对训练对象进行图像的预处理,使大小保持一致且都已经二值化...

    想通过svm实现多字符的分类,可以通过一对其它的方式,例如1,2,3,4,5个数,创造出四个向量机,分别是1对2-5,2对3-5,3对4和5,4对5。
    注意事项:
    1.对训练对象进行图像的预处理,使大小保持一致且都已经二值化。
    2.因为车牌中不含有英文字母I和O,可以直接用contious跳过当前循环。

    void CancelSamples()
    {
        for (int j = 0; j <=36;j++)
        {
            if(j==10||char(j+54)=='O'||char(j+54)=='I')
            {
                cout<<"skip cancelling "<< j<< "samples"<<endl;
                continue;
            }
            for(int i=0;i<=13;i++)
            {
                string imgName;
                if(j<10)
                    imgName=format("samples/sample_%d/%d.jpg",j,(i+1));
                else
                    imgName=format("samples/sample_%c/%d.jpg",(j+54),(i+1));
                Mat srcImage=imread(imgName);
                if(srcImage.empty())
                {
                    cout<<"failed to get the Image"<<imgName<<endl;
                }
                    
                else {
                    Mat resized;
                    resize(srcImage,resized,Size(80,150));
                    blur(resized,resized,Size(3,3));
                    cvtColor(resized,resized,CV_BGR2GRAY);
                    threshold(resized,resized,140,255,CV_THRESH_BINARY);
                    vector<Mat> channels(3);
                    for(int i=0;i<3;i++)
                    {
                        resized.copyTo(channels[i]);
                    }
                    Mat resultImage=Mat::zeros(resized.size(),CV_8UC3);
                    merge(channels,resultImage);
                    if(ResizeImage(resultImage,i,j))
                    {
                        cout<<"keep resized "<<format("ROI%d.jpg",i+1)<<endl;
                    }
                    else
                    {
                        cout<<"keep resized "<<format("ROI%d.jpg",i+1)<<" failed"<<endl;
                        continue;
                    }
    
                }
            }
        }
    
    }
    

    处理好了训练素材就可以开始了

    void SvmTraining()
    {
        for (int i = 0; i <=35 ; ++i) {
            if(i==10||char(i+54)=='O'||char(i+54)=='I')
            {
                cout<<"skip the number"<<endl;
                continue;
            }
            Mat classes;
            Mat trainingData;
            Mat trainingImages;
            vector<int> trainingLabels;
            GetPositive(trainingImages,trainingLabels,i);
            GetNegative(trainingImages,trainingLabels,i);
            trainingImages.copyTo(trainingData);
            trainingData.convertTo(trainingData,CV_32FC1);
            Mat(trainingLabels).copyTo(classes);
    
            Ptr<SVM> SVM_params=SVM::create();
            SVM_params->setType(SVM::C_SVC);
            SVM_params->setKernel(SVM::LINEAR);
            SVM_params->setDegree(0);
            SVM_params->setGamma(1);
            SVM_params->setCoef0(0);
            SVM_params->setC(1);
            SVM_params->setNu(0);
    
            SVM_params->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 1000, 0.01));
    
            Ptr<TrainData> tdata=TrainData::create(trainingData,ROW_SAMPLE,classes);
            cout<<"start"<<endl;
    
            clock_t start,end;
            start =clock();
            SVM_params->train(tdata);
            end=clock();
    
            cout<<float(end-start)/CLOCKS_PER_SEC<<"s"<<endl;
            string dstCorner;
            if(i<10)
                SVM_params->save(format("trained_model/trainedmModel_%d.xml",i));
            else
                SVM_params->save(format("trained_model/trainedmModel_%c.xml",(i+54)));
            cout<<"succeed"<<endl;
        }
    }
    

    在这里插入图片描述

    void ClassifyTraget() {
        for (int i = 1; i <= 6; i++) {
            string character = format("cut_%d.jpg", i);
            Mat srcImage = imread(character);
            resize(srcImage, srcImage, Size(64, 128));
            cvtColor(srcImage, srcImage, CV_BGR2GRAY);
    
            HOGDescriptor hog(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 3);
            Mat featureMat;
            vector<float> descriptors;
    
            hog.compute(srcImage, descriptors, Size(0, 0), Size(0, 0));
            featureMat = Mat::zeros(1, descriptors.size(), CV_32FC1);
            for (int j = 0; j < descriptors.size(); j++) {
                featureMat.at<float>(0, j) = descriptors[j];
            }
    
            int judge = IdentifyChar(featureMat,0);
            if (judge)
                cout << "recognition of the cut_" << i << " succeeded" << endl;
            else
                cout << "recognition of the cut_" << i << " failed" << endl;
    
    
        }
    }
    
    //在这里用递归就不用写一堆循环了,方便快捷又实用。
    int  IdentifyChar(Mat &featureMat,int num) {
        if (num >= 36) {
            cout << "failed to identify the character!" << endl;
            return 0;
        } else if (num == 10 || char(num + 54) == 'O' || char(num + 54) == 'I') {
            return IdentifyChar(featureMat, num + 1);
        } else
        {   string dstCorner;
            if (num < 10)
                dstCorner = format("trained_model/trainedmModel_%d.xml", num);
            else
                dstCorner = format("trained_model/trainedmModel_%c.xml", (num + 54));
            Ptr<ml::SVM> svm = cv::ml::SVM::load(dstCorner);
            int judge = svm->predict(featureMat);
            if (judge == 1 && num < 10) {
                cout << num << endl;
                return 1;
            } else if (judge == 1 && num > 10) {
                char a = char(num + 54);
                cout << a << endl;
                return 1;
            }
            else
                return IdentifyChar(featureMat, num + 1);
        }
    }
    

    结果运行图在这里插入图片描述
    这里没有识别省份是因为找训练图片太费时间了而且做这个的主要目的是为了练习,就这一个字却需要收集大量的图片,毕竟这些图都是一个一个百度图片扣下来的。
    如果想要识别的话我觉得用enum一个一个对应就可。

    展开全文
  • openCV字符识别样本

    2018-05-05 13:03:01
    0~9,A~Z 34类字符模版 每类50个,一共是1700个图片,比网上大多数的样本都要多
  • OpenCV字符识别

    2020-10-16 15:58:08
    光学字符识别英文全称为 optical Character Recognition(简称OCR)。 一、印刷体识别 图像预处理,版面处理,图像切分,特征提取,模板匹配,识别后处理。 图像预处理一般包括灰度化、二值化、倾斜和校正,行、字...

    光学字符识别,英文全称为 optical Character Recognition(简称OCR)。
    一、印刷体识别
    图像预处理,版面处理,图像切分,特征提取,模板匹配,识别后处理。
    图像预处理一般包括灰度化、二值化、倾斜和校正,行、字切分,平滑和规范化等等。
    切斜与校正常用的方法分为:基于投影图的方法,基于霍夫变换的方法,基于交叉相关性的方法,基于傅里叶变换的方法和基于最近邻方法。
    规范化包括位置规范化、大小规范化以及笔画粗细规范化。
    二,应用案例
    车牌识别
    银行卡号识别
    基本步骤:
    1对模板图像进行处理
    1.1读取模板图片
    1.2模板图片转换为灰度图像
    1.3转化为二值图像
    1.4计算轮廓
    2对信用卡进行处理
    2.1初始化卷积核
    2.2读取信用卡
    2.3对图像进行预处理操作
    2.4对图像礼帽操作
    2.5用sobel算子边缘检测
    2.6对图像闭操作
    2.7计算轮廓
    2.8模板匹配
    文档识别
    1预处理
    1.1转为灰度图
    1.2高斯滤波
    1.3边缘检测
    1.4获取轮廓
    1.5透视变换

    展开全文
  • opencv 车牌字符分割 ANN网络识别字符

    千次阅读 2018-11-16 23:20:36
    opencv 车牌字符分割 ANN网络识别字符   原文参考:https://www.cnblogs.com/chenzhefan/p/7629441.html 最近在复习OPENCV的知识,学习caffe的深度神经网络,正好想起以前做过的车牌识别项目,可以拿出来研究下...

                              opencv 车牌字符分割 ANN网络识别字符  

     

    原文参考:https://www.cnblogs.com/chenzhefan/p/7629441.html

    最近在复习OPENCV的知识,学习caffe的深度神经网络,正好想起以前做过的车牌识别项目,可以拿出来研究下

     

      以前的环境是VS2013和OpenCV2.4.9,感觉OpenCV2.4.9是个经典版本啊!不过要使用caffe模型的话,还是要最新的OpenCV3.3更合适!

      一、车牌图片库

      以前也是网上下的,如果找不到的小伙伴可以从我这儿下: 链接:http://pan.baidu.com/s/1hrQF92G 密码:43jl

      里面有数字 “0-9”,字母“A-Z”的训练图片各50张。

      

      测试车牌图片当时是从他人得到已经定位到车牌的图片,类似如下:

      目标当然就是对这些车牌图片进行预处理,单字符分割,单字符识别!

     

      二、预处理

      图像的预处理做来做去就是滤波去噪,光照补偿,灰度/二值化,形态学基本操作等等。这些图片都是自然场景得到所以基本的去噪操作可以做一下,然后为了单字符分割,灰度化和形态学可以结合效果调整。

      光照补偿其实一直是个问题,大多数有直方图均衡化,亮度参考白,利用公式统计补偿图片。这方面也可以结合图像增强方法来做!笔者当时觉得前两者对大多数场景已经适用。

      二值化可以使用 cv::threshold函数,如:

    Mat t1=imread("2.png",1);
    cvtColor(inimg, gimg, CV_BGR2GRAY);
    threshold(gimg, gimg, 100, 255, CV_THRESH_BINARY);
    imshow("gimg", gimg);

      第一行imread(),由于flag设为1所以读的是彩图,采用cvtColor函数转化为灰度图。如果你读入就是灰度图可以省略第二行代码。第三行就是转化为二值化函数,阈值100可以修改,在灰度对比不明显是有必要!

      效果:

      如果预处理做的好,某些小的白色区域是可以去掉的。这个效果也可以识别。

      同时可以发现车牌外围被一圈白色包围,如若能去除外围白色,对于单字符分割更有益。但其实通过寻找列像素之间的变化,白色区域只是影响了阈值不会对结果太大影响。

      想要去除白色外圈可以参考:http://blog.csdn.net/u011630458/article/details/43733057

      如果想要使用直方图均衡化,OPENCV有equalizeHist(inputmat, outputmat);非常方便,但是效果不好。

    使用直方图均衡化后的上述车牌二值化图片:

      

    效果更惨烈了,因为均衡化就是让直方图的像素分布更加平衡,上图黑色多,均衡之后自然白色多了,反而不好!

     

      二、单字符分割

      单字符分割主要策略就是检测列像素的总和变化,因为没有字符的区域基本是黑色,像素值低;有字符的区域白色较多,列像素和就变大了!

      列像素变化的阈值是个问题,看到很多博客是固定的阈值进行检测,除非你处理后的二值化图像非常完美,不然有的图片混入了白色区域就会分割错误!而且对于得到分割宽度如果太小也应该使用策略进行剔除,没有一定的宽度限制分割后的图片可能是很多个窄窄的小区域。。。  

    int getColSum(Mat& bimg, int col)
    {
        int height = bimg.rows;
        int sum = 0;
        for (int i = 1; i < height; i++)
        {
            sum += bimg.at<uchar>(i, col);
        }
        cout << sum << endl;
        return sum;
    }
    
    int cutLeft(Mat& src, int Tsum, int right)//左右切割  
    {
        int left;
        left = 0;
    
        int i;
        for (i=0; i < src.cols; i++)
        {
            int colValue = getColSum(src, i);  
            if (colValue> Tsum)
            {
                left = i;
                break;
            }
        }
        int roiWidth=src.cols/7;
        for (; i < src.cols; i++)
        {
            int colValue = getColSum(src, i);
            if (colValue < Tsum)
            {
                right = i;
                if ((right - left) < (src.cols/7))
                    continue;
                else
                {
                    roiWidth = right - left;
                    break;
                }
                
            }
        }
        return roiWidth;
    }
    
    int getOne(Mat& inimg)
    {
        Mat gimg,histimg;
        cvtColor(inimg, gimg, CV_BGR2GRAY);
        equalizeHist(gimg,histimg);
        //imshow("histimg", histimg);
        threshold(gimg, gimg, 100, 255, CV_THRESH_BINARY);
        imshow("gimg", gimg);
        waitKey(0);
    
        int psum=0;
        for (int i = 0; i < gimg.cols; i++)
        {
            psum+=getColSum(gimg, i);
        }
        cout <<"psum/col:"<< psum/gimg.cols << endl;
        int Tsum = 0.6*(psum / gimg.cols);
        int roiWid= cutLeft(gimg, Tsum, 0);
    
        return roiWid;
    }
     

     

    笔者思路也很简单:

      首先统计所有列像素的总和,取其列像素的均值作为参考标准之一(也可以选用其他数学指标参考),列像素的阈值Tsum设置为列像素均值的百分比(如60%,是情景定)。

      利用cutLeft()函数对图片进行列扫描,将列像素超过阈值的列标记为左边,再继续寻找右边,将满足阈值的右边进行标记。左右相减即可得到宽度分割字符。

      考虑到车牌中只有7个字符,所以先判断得到宽度大小,如果小于总宽的七分之一视为干扰放弃;其实也可以加大到总宽的8分之一(因为车牌中间可能有连接符)。

      getColSum()函数是求一列的像素和,这里用到了.at<> 方式,其实还有别的方法也可以,只要获得当前的像素值,并累加整列即可!

      上图车牌的分割效果:

                 

      因为第三张有车牌的连接符,所以导致第三张和第四张稍有瑕疵,但总体分割还是满意的!

     

      三、单字符识别

      只论字符识别其实有不少选择方案,一开始笔者尝试了ORB特征,想利用特征匹配计算相似度来判断最优的字符结果。ORB特征相比SURF/SIFT更加快速,而且特征不变性也不错。但是在匹配时发现单字符的图片像素点太少,提取的特征点数极少,无法得到较好的匹配结果,只能放弃!

      其实也有模板匹配来做字符识别的,但是OPENCV提供的模板匹配对于从同一副图片提取的模板图去匹配样本图效果很好,不是同一副图片时效果很一般。因为笔者用OPENCV的模板匹配一般用来找重复区域。

      OCR识别是可以完全用在此处的,OCR识别甚至可以识别汉字,安装OCR的库之后就可以尝试一番!

      笔者最后选择了神经网络ANN来做字符分类识别,利用SVM也可以都是分类器之一。使用神经网络可以和caffe的mnist模型有所对比的感觉!  

    void ann10(Mat& testroi)
    {
        const string fileform = "*.png";
        const string perfileReadPath = "E:\\vswork\\charSamples";
    
        const int sample_mun_perclass = 50;//训练字符每类数量  
        const int class_mun = 34;//训练字符类数 0-9 A-Z 除了I、O  
    
        const int image_cols = 8;
        const int image_rows = 16;
        string  fileReadName,fileReadPath;
        char temp[256];
    
        float trainingData[class_mun*sample_mun_perclass][image_rows*image_cols] = { { 0 } };//每一行一个训练样本  
        float labels[class_mun*sample_mun_perclass][class_mun] = { { 0 } };//训练样本标签  
    
        for (int i = 0; i <= class_mun - 1; i++)//不同类  
        {
            //读取每个类文件夹下所有图像  
            int j = 0;//每一类读取图像个数计数  
    
            if (i <= 9)//0-9  
            {
                sprintf(temp, "%d", i);
                //printf("%d\n", i);  
            }
            else//A-Z  
            {
                sprintf(temp, "%c", i + 55);
                //printf("%c\n", i+55);  
            }
    
            fileReadPath = perfileReadPath + "/" + temp + "/" + fileform;
            cout << "文件夹" << fileReadPath << endl;
    
            HANDLE hFile;
            LPCTSTR lpFileName = StringToWchar(fileReadPath);//指定搜索目录和文件类型,如搜索d盘的音频文件可以是"D:\\*.mp3"  
            WIN32_FIND_DATA pNextInfo;  //搜索得到的文件信息将储存在pNextInfo中;  
            hFile = FindFirstFile(lpFileName, &pNextInfo);//请注意是 &pNextInfo , 不是 pNextInfo;  
            if (hFile == INVALID_HANDLE_VALUE)
            {
                continue;//搜索失败  
            }
            //do-while循环读取  
            do
            {
                if (pNextInfo.cFileName[0] == '.')//过滤.和..  
                    continue;
                j++;//读取一张图  
                //wcout<<pNextInfo.cFileName<<endl;  
                //printf("%s\n",WcharToChar(pNextInfo.cFileName));  
                //对读入的图片进行处理  
                Mat srcImage = imread(perfileReadPath + "/" + temp + "/" + WcharToChar(pNextInfo.cFileName), CV_LOAD_IMAGE_GRAYSCALE);
                Mat resizeImage;
                Mat trainImage;
                Mat result;
    
                resize(srcImage, resizeImage, Size(image_cols, image_rows), (0, 0), (0, 0), CV_INTER_AREA);//使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现  
                threshold(resizeImage, trainImage, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
    
                for (int k = 0; k<image_rows*image_cols; ++k)
                {
                    trainingData[i*sample_mun_perclass + (j - 1)][k] = (float)trainImage.data[k];
                    //trainingData[i*sample_mun_perclass+(j-1)][k] = (float)trainImage.at<unsigned char>((int)k/8,(int)k%8);//(float)train_image.data[k];  
                    //cout<<trainingData[i*sample_mun_perclass+(j-1)][k] <<" "<< (float)trainImage.at<unsigned char>(k/8,k%8)<<endl;  
                }
    
            } while (FindNextFile(hFile, &pNextInfo) && j<sample_mun_perclass);//如果设置读入的图片数量,则以设置的为准,如果图片不够,则读取文件夹下所有图片  
    
        }
    
        // Set up training data Mat  
        Mat trainingDataMat(class_mun*sample_mun_perclass, image_rows*image_cols, CV_32FC1, trainingData);
        cout << "trainingDataMat——OK!" << endl;
    
        // Set up label data   
        for (int i = 0; i <= class_mun - 1; ++i)
        {
            for (int j = 0; j <= sample_mun_perclass - 1; ++j)
            {
                for (int k = 0; k < class_mun; ++k)
                {
                    if (k == i)
                        if (k == 18)
                        {
                            labels[i*sample_mun_perclass + j][1] = 1;
                        }
                        else if (k == 24)
                        {
                            labels[i*sample_mun_perclass + j][0] = 1;
                        }
                        else
                        {
                            labels[i*sample_mun_perclass + j][k] = 1;
                        }
                    else
                        labels[i*sample_mun_perclass + j][k] = 0;
                }
            }
        }
        Mat labelsMat(class_mun*sample_mun_perclass, class_mun, CV_32FC1, labels);
        cout << "labelsMat:" << endl;
        ofstream outfile("out.txt");
        outfile << labelsMat;
        //cout<<labelsMat<<endl;  
        cout << "labelsMat——OK!" << endl;
    
        //训练代码  
    
        cout << "training start...." << endl;
        CvANN_MLP bp;
        // Set up BPNetwork's parameters  
        CvANN_MLP_TrainParams params;
        params.train_method = CvANN_MLP_TrainParams::BACKPROP;
        params.bp_dw_scale = 0.001;
        params.bp_moment_scale = 0.1;
        params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 10000, 0.0001);  //设置结束条件  
        //params.train_method=CvANN_MLP_TrainParams::RPROP;  
        //params.rp_dw0 = 0.1;  
        //params.rp_dw_plus = 1.2;  
        //params.rp_dw_minus = 0.5;  
        //params.rp_dw_min = FLT_EPSILON;  
        //params.rp_dw_max = 50.;  
    
        //Setup the BPNetwork  
        Mat layerSizes = (Mat_<int>(1, 5) << image_rows*image_cols, 128, 128, 128, class_mun);
        bp.create(layerSizes, CvANN_MLP::SIGMOID_SYM, 1.0, 1.0);//CvANN_MLP::SIGMOID_SYM  
        //CvANN_MLP::GAUSSIAN  
        //CvANN_MLP::IDENTITY  
        cout << "training...." << endl;
        bp.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
    
        bp.save("../bpcharModel.xml"); //save classifier  
        cout << "training finish...bpModel.xml saved " << endl;
        return;
    }
    
    ann10

      ann10函数主要完成读取图片训练ANN网络的功能。

      注意点:

      修改图片文件类型  fileform;

      修改训练图片路径  perfileReadPath等;

      修改训练图片数量  sample_mun_perclass;

      修改训练类别数  class_mun;(34类是因为IO与10很像,所以少了两类);

      image_cols和image_rows根据自己图片情况修改;

      观察代码发现训练文件在工程目录的  bpcharModel.xml;之后调用该网络模型即可,网上有很多网络调用和网络训练没有分开,这样你每预测分类一个字符都要重新训练网络会相当浪费时间的,笔者的渣电脑训练一次就要几分钟,每次分类都训练时间有点伤不起。。。真正的实际应用也是用训练好的网络参数直接调用,速度很快。就像caffe中的深度神经网络,使用网络分类时也只是调用生成好的caffemodel和标签、solver文件就行了,如果还要重新训练一小时根本没有实用性。  

    void predictann(Mat testroi)
    {
        //测试神经网络 
        CvANN_MLP bp;
        bp.load("E:\\vswork\\CarNumRecog\\bpcharModel.xml");
        const int image_cols = 8;
        const int image_rows = 16;
    
        cout << "测试:" << endl;
        //Mat test_image = imread("E:\\vswork\\charSamples\\3.png", CV_LOAD_IMAGE_GRAYSCALE);
        Mat test_temp;
        resize(testroi, test_temp, Size(image_cols, image_rows), (0, 0), (0, 0), CV_INTER_AREA);//使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现  
        threshold(test_temp, test_temp, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
        Mat_<float>sampleMat(1, image_rows*image_cols);
        for (int i = 0; i<image_rows*image_cols; ++i)
        {
            sampleMat.at<float>(0, i) = (float)test_temp.at<uchar>(i / 8, i % 8);
        }
    
        Mat responseMat;
        bp.predict(sampleMat, responseMat);
        Point maxLoc;
        double maxVal = 0;
        minMaxLoc(responseMat, NULL, &maxVal, NULL, &maxLoc);
        char temp[256];
    
        if (maxLoc.x <= 9)//0-9  
        {
            sprintf(temp, "%d", maxLoc.x);
            //printf("%d\n", i);  
        }
        else//A-Z  
        {
            sprintf(temp, "%c", maxLoc.x + 55);
            //printf("%c\n", i+55);  
        }
    
        cout << "识别结果:" << temp << "    相似度:" << maxVal * 100 << "%" << endl;
        imshow("test_image", testroi);
        waitKey(0);
    
        return;
    }
    
    predictann
     

     

      predictann函数就是调用ann10函数生成的网络模型文件,进行预测分类的功能。

      上述车牌的单字符识别效果如下:

          

      可以看到有的相似度很高,有的却很低,也有一些识别错误的,我不再显示。。。

      相比之前使用的caffe  mnist识别率真的是差距有点大,以后有机会将mnist的模型来识别车牌字符试试~~

     

      度盘失效了,附上我的github地址,里面会传数据集和完整代码!欢迎大家star 和 fork 我~~

          https://github.com/chenzhefan/CarNumRecognize.git (原文博主)

     

     

     

    展开全文
  • 应用OpenCV进行OCR字符识别

    千次阅读 2013-12-27 09:42:49
    opencv自带一个字符识别的例子,它的重点不是OCR字符识别,而主要是演示机器学习的应用。它应用的是UCI提供的字符数据(特征数据)。 DAMILES在网上发布了一个应用OpenCV进行OCR的例子, ...

    opencv自带一个字符识别的例子,它的重点不是OCR字符识别,而主要是演示机器学习的应用。它应用的是UCI提供的字符数据(特征数据)。

    DAMILES在网上发布了一个应用OpenCV进行OCR的例子, http://blog.damiles.com/2008/11/basic-ocr-in-opencv/

    这些例子都只能用于学习OpenCV或熟悉OCR的简单流程,因为它们与当前比较专业的OCR引擎的识别率相去甚远。

     

    这里写下OpenCV下OCR的流程:

    1. 特征提取

    2. 训练

    3. 识别

     

    特征提取

    1. 在图像预处理后,提取出字符相关的ROI图像,并且大小归一化,整个图像的像素值序列可以直接作为特征。damiles是直接将整个字符图像转换化为vector向量特征作为特征输入的。

     

    2. 但直接将整个图像作为特征数据维度太高,计算量太大,所以也可以进行一些降维处理,减少输入的数据量。拿到字符的ROI图像,二值化。将图像分块,然后统计每个小块中非0像素的个数,这样就形成了一个较小的矩阵,这矩阵就是新的特征了。

    UCI就是这么处理,详见其说明http://archive.ics.uci.edu/ml/datasets/Optical+Recognition+of+Handwritten+Digits

    OpenCV中letter_recog例子就是使用的其特征数据。

     

    训练与识别

    训练与识别一般都采用同一种机器学习方法:

    DAMILES应用了KNearest方法,对输入数据进行训练和识别。

    1. 数据输入:

    getData()函数中:

    为trainData和trainClasses设置数据。

     

    2. 初始化机器学习算法,及其训练

    knn=new CvKNearest( trainData, trainClasses, 0, false, K );

    trainData, trainClasses数据已得到。

    而K是分类的数目。

     

    训练在CvKNearest算法初始化中已经完成

     

    3. 识别

    获取识别测试的数据,testData

    result=knn->find_nearest(testData,K,0,0,nearest,0);

    result为识别的结果。

     

     

    而OpenCV自带例子中,提供了boost,mlp,knearest,nbayes,svm,rtrees这些机器学习方法,进行训练和识别。

    处理的步骤和方式都类似。

     

    这些例子的识别率不是很高,OCR识别率在90%以上才有较好的使用意义,所以,OCR还需要更多特征和分析方法,来提高识别率,tesseract是一个不错的开源OCR引擎。

     

    -------------------

    在tesseract最初的字体库里,一种字体的字符样本库包括:94个字符,8种大小,4种字体(正常,粗体,斜体,斜粗体),每种20个样本,共60160个样本。

    与UIC提供的字体库不同的是,tesseract提供的是标准印刷体字体库的识别,而UIC提供是手写体handwriting的特征数据。

     

    数据之美提到,G公司(应该就是google了)的研究结果表明,在自然语言与机器翻译领域,简单模型加上大量有效样本数据,比复杂模型加上小样本数据,有效的多。 这个结论应该适用机器学习的很多领域。运算足够快,样本足够大,即使简单的模型,效果可能会出人意料。

    由此可见,收集有效的、大量的样本库是多么的重要。

    展开全文
  • OpenCV OpenGL手写字符识别

    千次阅读 2014-12-10 16:43:00
    Description: 模式识别部分,提取特征数据,训练模型,预测结果 Others: Function List: History: 1. Date: Author: Modification: 2. ... ************************************************/ ...
  • opencv实现车牌识别字符识别

    千次阅读 2015-02-13 13:41:06
     在前面已经讲了车牌的定位和对车牌字符的分割,这里继续是最后对车牌的识别字符识别  主要是用了两张办法,第一个是前面 这一篇中用到过的,opencv自带的getPSNR函数,这里不再对它进行讲解。 另一种方法是...
  • opencv 人工神经网络 ANN OCR 字符识别
  • opencv_contrib自带的OCR处理用例共有6个,其中end_to_end_recognition、segmented_word...01 资源OpenCV自带的字符识别用例,opencv_contrib\modules\text\samples\character_recognition.cpp。character_recognition.
  • 基于opencv的手写数字字符识别

    千次下载 热门讨论 2013-11-29 17:36:00
    实现了基于opencv 的手写数字字符识别 主要参照文章: http://blog.damiles.com/2008/11/basic-ocr-in-opencv/ 基本上就是按着人家的代码来配置的,完后小改动了几个参数,写了一个文档,方便大家学习吧。
  • 本程序主要参照论文,《基于OpenCV的脱机手写字符识别技术》实现了,对于手写阿拉伯数字的识别工作。识别工作分为三大步骤:预处理,特征提取,分类识别。预处理过程主要找到图像的ROI部分子图像并进行大小的归一化...
  • https://m.jb51.net/article/137487.htm车牌识别总体分成两个大的步骤:一、车牌定位:从照片中圈出车牌二、车牌字符识别这里只说第二个步骤,字符识别包括两个步骤:1、图像处理原本的图像每个像素点都是RGB定义的...
  • 使用OpenCV识别字符的Python代码: (Python code for recognizing characters using OpenCV:) This code can be downloaded for your easy understanding of approach to the recognition. 可以下载此代码,以方便...
  • 基于OpenCV的脱机手写字符识别技术 学习OpenCV字符识别的好资料~
  • Opencv识别单行数字

    千次阅读 2016-09-21 16:50:34
    通过Opencv识别当行数字!
  • C++ ---- 基于OpenCV的OCR字符识别

    万次阅读 2018-10-25 17:44:14
    OpenCV 简介: OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,540
精华内容 4,216
关键字:

opencv识别英文字符