#include "OCR.h"
const char OCR::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 OCR::numCharacters = 30;
CharSegment::CharSegment(){}
CharSegment::CharSegment(Mat i, Rect p)
{
img = i;
pos = p;
}
OCR::OCR()
{
DEBUG = false;
trained = false;
saveSegments = false;
charSize = 20;
}
OCR::OCR(string trainFile)
{
DEBUG = false;
trained = false;
saveSegments = false;
charSize = 20;
// 读取OCR.xml文件
FileStorage fs;
fs.open("OCR.xml", FileStorage::READ);
Mat TrainingData;
Mat Classes;
fs["TrainingDataF15"] >> TrainingData;
fs["classes"] >> Classes;
train(TrainingData, Classes, 10);
}
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;
}
bool OCR::verifySizes(Mat r){
// 正确的车牌字符宽高比为45/77
float aspect = 45.0f / 77.0f;
float charAspect = (float)r.cols / (float)r.rows;
float error = 0.35; // 允许误差达到35%
float minHeight = 15;
float maxHeight = 28;
// 最小比例
float minAspect = 0.2;
float maxAspect = aspect + aspect * error;
// 区域像素
float area = countNonZero(r);
// bb区域
float bbArea = r.cols * r.rows;
// 像素占区域的百分比
float percPixels = area / bbArea;
// 若一块区域的比率超过标准比率的80%,则认为该区域为黑色快,而不是一个字符
if (DEBUG)
cout << "Aspect: " << aspect << " [" << minAspect << "," << maxAspect << "] " << "Area " << percPixels << " Char aspect " << charAspect << " Height char " << r.rows << "\n";
if (percPixels < 0.8 && charAspect > minAspect && charAspect < maxAspect && r.rows >= minHeight && r.rows < maxHeight)
return true;
else
return false;
}
// 阈值分割
vector<CharSegment> OCR::segment(Plate plate){
Mat input = plate.plateImg;
vector<CharSegment> output;
Mat thresholdImage;
threshold(input, thresholdImage, 60, 255, CV_THRESH_BINARY_INV);
if (DEBUG)
imshow("Threshold plate", thresholdImage);
Mat img_contours;
thresholdImage.copyTo(img_contours);
// 找到可能的车牌的轮廓
vector< vector< Point> > contours;
findContours(img_contours,
contours, // 检测的轮廓数组,每一个轮廓用一个point类型的vector表示
CV_RETR_EXTERNAL, // 表示只检测外轮廓
CV_CHAIN_APPROX_NONE); // 轮廓的近似办法,这里存储所有的轮廓点
// 在白色的图上画出蓝色的轮廓
cv::Mat result;
thresholdImage.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();
char res[20];
int i = 0;
// 若没有达到设定的宽高比要求,移去该区域
while (itc != contours.end())
{
Rect mr = boundingRect(Mat(*itc));
rectangle(result, mr, Scalar(0, 255, 0));
// 裁剪图像
Mat auxRoi(thresholdImage, mr);
if (verifySizes(auxRoi)){
auxRoi = preprocessChar(auxRoi);
output.push_back(CharSegment(auxRoi, mr));
//保存每个字符图片
sprintf(res, "PlateNumber%d.jpg", i);
i++;
imwrite(res, auxRoi);
rectangle(result, mr, Scalar(0, 125, 255));
}
++itc;
}
if (DEBUG)
cout << "Num chars: " << output.size() << "\n";
if (DEBUG)
imshow("SEgmented Chars", result);
return output;
}
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);
}
// 归一化直方图
double min, max;
minMaxLoc(mhist, &min, &max);
if (max>0)
mhist.convertTo(mhist, -1, 1.0f / max, 0);
return mhist;
}
Mat OCR::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 OCR::drawVisualFeatures(Mat character, Mat hhist, Mat vhist, Mat lowData){
Mat img(121, 121, CV_8UC3, Scalar(0, 0, 0));
Mat ch;
Mat ld;
cvtColor(character, ch, CV_GRAY2RGB);
resize(lowData, ld, Size(100, 100), 0, 0, INTER_NEAREST);
cvtColor(ld, ld, CV_GRAY2RGB);
Mat hh = getVisualHistogram(&hhist, HORIZONTAL);
Mat hv = getVisualHistogram(&vhist, VERTICAL);
Mat subImg = img(Rect(0, 101, 20, 20));
ch.copyTo(subImg);
subImg = img(Rect(21, 101, 100, 20));
hh.copyTo(subImg);
subImg = img(Rect(0, 0, 20, 100));
hv.copyTo(subImg);
subImg = img(Rect(21, 0, 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));
imshow("Visual Features", img);
cvWaitKey(0);
}
// 特征提取
Mat OCR::features(Mat in, int sizeData){
//Histogram features
Mat vhist = ProjectedHistogram(in, VERTICAL);
Mat hhist = ProjectedHistogram(in, HORIZONTAL);
Mat lowData;
resize(in, lowData, Size(sizeData, sizeData));
if (DEBUG)
drawVisualFeatures(in, hhist, vhist, lowData);
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;
}
// 用于创建所有需要的矩阵并用训练数据、类标签矩
// 阵、在隐藏层的神经元数量来训练一个识别系统
void OCR::train(Mat TrainData, Mat classes, int nlayers){
Mat layers(1, 3, CV_32SC1);
layers.at<int>(0) = TrainData.cols;
layers.at<int>(1) = nlayers;
layers.at<int>(2) = numCharacters;
ann.create(layers, CvANN_MLP::SIGMOID_SYM, 1, 1);
// 创建一个矩阵,其中存放n个训练数据,并将其分为m类
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, train
没有合适的资源?快使用搜索试试~ 我知道了~
基于SVM与人工神经网络的车牌识别OpenCV&C++实现
共54个文件
jpg:20个
tlog:6个
cpp:4个
5星 · 超过95%的资源 需积分: 50 691 下载量 199 浏览量
2015-05-29
17:33:47
上传
评论 26
收藏 15.12MB ZIP 举报
温馨提示
基于SVM与人工神经网络的车牌识别算法,使用了OpenCV的图像处理函数,在VS2013 + OpenCV 2.4.9平台上实现
资源推荐
资源详情
资源评论
收起资源包目录
NumberPlateRecognition.zip (54个子文件)
NumberPlateRecognition
NumberPlateRecognition
NumberPlateRecognition.sdf 17.06MB
NumberPlateRecognition.v12.suo 40KB
NumberPlateRecognition.sln 1012B
NumberPlateRecognition
Plate.cpp 925B
Plate.h 351B
OCR.cpp 9KB
NumberPlateRecognition.vcxproj 5KB
ImageRecognition.cpp 7KB
OCR.h 1KB
NumberPlateRecognition.vcxproj.filters 1KB
ImageRecognition.h 508B
main.cpp 3KB
SVM.xml 2.44MB
NumberPlateRecognition.vcxproj.user 165B
Debug
vc120.pdb 1.86MB
ImageRecognition.obj 915KB
main.obj 469KB
Plate.obj 376KB
vc120.idb 1.01MB
OCR.obj 744KB
NumberPlateRecognition.log 2KB
NumberPl.62FE6B16.tlog
CL.write.1.tlog 10KB
CL.read.1.tlog 93KB
cl.command.1.tlog 4KB
link.write.1.tlog 2KB
link.command.1.tlog 3KB
link.read.1.tlog 6KB
NumberPlateRecognition.lastbuildstate 221B
OCR.xml 3.24MB
Debug
NumberPlateRecognition.ilk 3.82MB
PlateNumber3.jpg 701B
PlateNumber2.jpg 521B
test
3266CNT.JPG 312KB
DSC_0566.jpg 378KB
5445BSX.JPG 365KB
2715DTZ.jpg 192KB
DSC_0562.jpg 357KB
9588DWV.jpg 503KB
3028BYS.JPG 286KB
7215BGN.JPG 321KB
3732FWW.JPG 275KB
8995CCN.JPG 261KB
3154FFY.JPG 384KB
9773BNB.jpg 349KB
NumberPlateRecognition.pdb 4.78MB
PlateNumber0.jpg 684B
NumberPlateRecognition.exe 284KB
PlateNumber4.jpg 613B
SVM.xml 2.44MB
PlateNumber5.jpg 626B
PlateNumber1.jpg 709B
PlateNumber6.jpg 633B
OCR.xml 3.24MB
3154FFY.JPG 384KB
共 54 条
- 1
Herbert_Zero
- 粉丝: 2912
- 资源: 9
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
- 4
- 5
前往页