自动车牌识别(Automatic Number Plate Recognition,ANPR),使用一种光学字符识别(O菩提差了Character Recognition, OCR)和其他方法(如图像分割与检测)来获取车辆牌照的监控方法。
对于一个ANPR系统,最好的是使用一个红外(IR)摄像机来获得车辆牌照,因为在分割这一步,对检测和OCR分割很简单、干净,误差小。这由光学的一下基本原理决定的。光滑表面,入射角等于反射角,但是粗糙的表面则是导致反射的漫射或者散射。多数车牌还有一个成为回射的特性,如下图所示。这里我们使用普通的图像。
ANPR有两个主要步骤:车牌检测与车牌识别。前者的目的是在整个视频中检测到车牌的位置。当在图像中检测到车牌时,分割的车牌被传到第二个步骤,即车牌识别,它用OCR算法来识别车牌上的字母和数字。
上图展示了项目的整个步骤,下面还将定义模式识别中的三个额外的步骤。
1).分割:检测并裁剪图像中每个感兴趣的块/区域。
2).特征提取:对字符图像集的每个部分进行提取。
3).分类:这一步会从车牌识别那一步的结果中得到每个字符,或从车牌检测那一步中将所得图像块分为“是车牌”或“不是车牌”。
该步骤如下:
一,车牌检测
这一步分为两步:图像分割和对分割的图像进行分类。
图像分割:使用各种滤波器、形态学算子,以及轮廓算法验证所获取图像中有车牌的部分。
图像分类:对每个图像块(即特征)采用支持向量机作为分类器进行分类。
车牌检测的整个过程如下:
1. sobel滤波器
2. 阈值算子
3. 闭形态学算子
4. 一个填充区域掩码
5. 用红色标记(特征图像中)可能检测到的车牌
6. 在执行SVM分类器后检测车牌
车牌分割有一个重要的特征:假定从汽车前面拍摄图像,会在车牌上有大量竖直边。可用来删除没有任何竖直边的区域。
主要步骤的结果:
原图像
sobel 图像
阈值化图像
闭操作图像
最后分割的图片,包括车牌区域与非车牌区域。
这里使用裁剪代码将检测的区域裁剪出来:
//针对每个检测区域,用一个向量来存储裁剪的图像与它的位置。
stringstream ss(stringstream::in | stringstream::out);
ss << "e:/opencvcodetext/ANPR/img"<< "_" << i << ".jpg";
imwrite(ss.str(), grayResult);
裁剪之后的图片:
二、SVM训练文件
在预处理和分割完图像之后,需要决定每部分是不是车牌号,可使用支持向量机(support vector machine,SVM)来分类车牌号与非车牌号。
在开始分类之前,需要训练分类器,这里主要使用图像的像素特征来训练分类器。当然还有其他一些更好的图像特征,比如说,主成分分析PCA, 傅里叶变换,纹理分析等。为了处理方便,可将用于训练和测试的所有图像数据保存到XML文件中。
得到SVM训练文件:
#include "cv.h"
#include "highgui.h"
#include "opencv.hpp"
#include "stdio.h"
#include "stdlib.h"
using namespace cv;
using namespace std;
int main()
{
Mat SVM_TrainningData;
Mat SVM_Classes;
int numPlates = 75 ; //正样本数量,书本的正样本数量,但是我实验时设为1
int numNoPlates = 35; //负样本数量,书本的正样本数量,但是我实验时设为2
int imageWidth = 144;
int imageHeight = 33;
char *path_Plates = "E:\\ANPR\\plates\\"; //正样本路径
char *path_NoPlates = "E:\\ANPR\\noplates\\"; //负样本路径
Mat trainningImages;