车牌识别系统开发记录(三) 字符识别

标签: 车牌 系统 开发 | 发表时间:2014-04-15 18:33 | 作者:Linoi
出处:http://blog.csdn.net

这篇博文来谈谈车牌的字符识别。

目前,车牌字符识别算法主要是基于模板匹配、特征匹配或神经网络的方法。

在本文中我们主要来说说基于神经网络的字符识别方法,采用的是OpenCV中的CvANN_MLP。关于神经网络的具体细节,可以参考我以前的博文:

BP神经网络解析及Matlab实现

更加细节的东西可以查看如下参考文献:

Neural Networks【OpenCV Documentation】

BackPropWikipedia【Wikipedia】


现在我们确定了字符识别的总体框架,那么先来说说字符的特征提取问题。这里我们主要考虑的是:

垂直方向、水平方向的数据统计特征提取法:

这种特征提取法就是自左向右对图像进行逐列的扫描,统计每列黑色像素的个数,然后,自上往下逐行扫描,统计每行的黑色像素的个数,将统计结果作为字符的特征向量,如果字符的宽度为w,高度为h,则特征向量维数是w+h。


同时,为了能够提取更多的特征用于识别,还将输入字符每个点的值引入特征向量。

Code:

Mat OCR::features(Mat in, int sizeData){
    // 直方图特征,
    Mat vhist=ProjectedHistogram(in,VERTICAL);
    Mat hhist=ProjectedHistogram(in,HORIZONTAL);
    
    // 将输入字符resize为15*15大小
    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)=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++;
        }
    }
    if(DEBUG)
        cout << out << "\n===========================================\n";
    return out;
}
Mat OCR::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);
    }

    //Normalize histogram
    double min, max;
    minMaxLoc(mhist, &min, &max);
    
    if(max>0)
        mhist.convertTo(mhist,-1 , 1.0f/max, 0);

    return mhist;
}

不过,在上面的特征提取之前,我们其实还需要做几步预处理:

首先,就是字符分割。在字符分割里面,我们首先将输入车牌二值化,然后利用findContours寻找出每个字符的轮廓,再利用boundingRect定位出每个轮廓的矩形区域,然后割取出每个字符的区域。

Code:

vector<CharSegment> OCR::segment(Plate plate){
    
	Mat input=plate.plateImg;
    vector<CharSegment> output;

    Mat img_threshold;
    threshold(input, img_threshold, 60, 255, CV_THRESH_BINARY_INV);
    
	if(DEBUG)
        imshow("Threshold plate", 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); 
    
    
    cv::Mat result;
    img_threshold.copyTo(result);
    cvtColor(result, result, CV_GRAY2RGB);
    cv::drawContours(result,contours,
            -1, 
            cv::Scalar(255,0,0), 
            1); 

    vector<vector<Point> >::iterator itc= contours.begin();
       
    while (itc!=contours.end()) {
        
        Rect mr= boundingRect(Mat(*itc));
        rectangle(result, mr, Scalar(0,255,0));

        Mat auxRoi(img_threshold, mr);
        if(verifySizes(auxRoi)){
            auxRoi=preprocessChar(auxRoi);
            output.push_back(CharSegment(auxRoi, mr));
            rectangle(result, mr, Scalar(0,125,255));
        }
        ++itc;
    }
    if(DEBUG)
        cout << "Num chars: " << output.size() << "\n";

    if(DEBUG)
        imshow("SEgmented Chars", result);

    return output;
}

效果:



然后,就是对字符进行预处理(统一大小)。




Code:

// 这个函数主要是对输入图片归一化到统一的大小20×20
Mat OCR::preprocessChar(Mat in){
    int h=in.rows;
    int w=in.cols;

    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;
}





作者:Linoi 发表于2014-4-15 10:33:28 原文链接
阅读:57 评论:0 查看评论

相关 [车牌 系统 开发] 推荐:

车牌识别系统开发记录(三) 字符识别

- - CSDN博客综合推荐文章
这篇博文来谈谈车牌的字符识别. 目前,车牌字符识别算法主要是基于模板匹配、特征匹配或神经网络的方法. 在本文中我们主要来说说基于神经网络的字符识别方法,采用的是OpenCV中的CvANN_MLP. 关于神经网络的具体细节,可以参考我以前的博文:. BP神经网络解析及Matlab实现. 更加细节的东西可以查看如下参考文献:.

Mozilla将开发独立操作系统

- ccyuling - Solidot
Mozilla宣布了一个新项目“Boot to Gecko”,旨在为开放互联网开发一种完整独立的操作系统,成为ChromeOS或Android的某种竞争对手. 源代码将发布在Github上(暂时只有README). Mozilla此举是为了推广开放Web技术,Boot to Gecko针对的不是笔记本,而是智能手机,为Android兼容设备提供基质.

这篇论文开源的车牌识别系统打败了目前最先进的商业软件

- - IT瘾-dev
(欢迎关注“我爱计算机视觉”公众号,一个有价值有深度的公众号~). 来自巴西阿雷格里港大学的学者发表于ECCV2018的论文《License Plate Detection and Recognition in Unconstrained Scenarios》,给出了一整套完整的车牌识别系统设计,着眼于解决在非限定场景有挑战的车牌识别应用,其性能优于目前主流的商业系统,代码已经开源,非常值得参考.

分布式系统的工程化开发方法

- cgeek - 陈硕的Blog
以下是我在珠三角技术沙龙 2010Q4 上的演讲投影片.

官方报道透露了军方开发的攻击系统

- 微笑!?~ - Solidot
7月16日CCTV《军事科技》栏目播出了“网络风暴来了”,主讲网络攻击. 在节目进行到11分钟左右,节目演示了网络攻击方法,演示工具是“攻击系统-中国人民解放军电子工程学院-1.0版”,攻击方法是对某一IP地址发动拒绝服务攻击(DDoS). 整个系统UI非常简陋,看起来就像是很多年前用VB搭建起来.

VCMS 发布1.1版——用 web2py 开发的开源 CMS 系统

- Ken - python.cn(jobs, news)
VCMS是用Python Web开发框架web2py开发的开源CMS系统. VCMS于9月21日发布了1.1版本,更新内容包括:文章列表分页、. RSS订阅入口、按考试日期查询考试资讯等. 用web2py开发Web应用是一种享受,欢迎感兴趣的童鞋加入开发:). VCMS是一个简单的用web2py开发的内容管理系统(CMS),适用于个人或中小企业发布资讯.

Nomovok公司计划开发整合Qt的Tizen系统

- Darth Noctis - cnBeta.COM
自Linux基金会宣布开发新移动操作系统Tizen,业界议论最多的话题莫过于Tizen是否将丢弃Qt. 虽然现在还没有明确的答案,但是Nomovok公司已宣布将开发整合Qt的Nomovok Tizen版本.

Mozilla拟开发移动操作系统 将火狐押宝Android

- fid - cnBeta.COM
据国外媒体报道,Mozilla基金会加大了Android版火狐浏览器的开发力度,以进一步提高其性能,降低能耗,使之适合在平板电脑上运行. 另外还在尝试移动操作系统项目Boot to Gecko,旨在打造一款能直接启动到浏览器的手机操作系统.

开发者寄望Android 4.0缓解系统分化问题

- 中雨 - cnBeta.COM
美国IT网站PCWorld今天撰文称,开发者希望最新的“冰淇淋三明治”系统能够从一定程度上缓解Android目前的平台分化问题,并修复一些漏洞.