车牌识别系统
2017-08-21 18:18
176 查看
将车牌识别系统细分为三个部分:
1.车牌检测
2.字符分割
3.字符识别
1.src/core/plate_locate.cpp中注释掉int CPlateLocate::plateLocate(Mat src, vector &resultVec, int index)函数中的两行:
2.将test中全部删除,只保留chars.hpp和main.cpp
chars.hpp:
main.cpp:
这样处理后,终端在EasyPR根目录下输入
即可显示车牌分割后的字符
不同于检测,这次使用darknet的classfier函数进行训练和识别,并考虑到分割出来的字符很小,使用了很浅的网络。
利用EasyPR提供的字符识别训练集(即resource/train/ann.7z)进行训练。将数据集解压后,每个文件夹中都有着对应的字符数据,对每个文件夹进行重命名处理。每个图像的命名格式采用(图片序号)_(标签).(图片格式)的格式进行命名。
重命名方法可以参考自行准备深度学习训练数据中的第2点。
重命名完成后,在darknet/data文件夹下新建char文件夹,并在char文件夹下新建image文件夹,将重命名完成的图片统一复制到image文件夹中,再使终端进入char路径(即darknet/data/char),输入
会在char文件夹下自动生成train.list文件,其中包含每个图像的绝对路径。
在darknet/cfg文件夹下新建cifar.data(名字cifar可以自定义),并进行如下改写:
class 为识别类别数量,train为train.list路径,label为label文件路径。如果需要训练完后的评估,请参照train.list的方法生成val.list,然后再cifar中增加一行
然后在char文件夹下新建labels.txt:
每行一个类别标签。
标签的注意事项
1.不区分大小写
2.不能有包含关系,如ji和jin,不能出现这样的形式,可改为ji1和jin
最后,cfg文件夹下新建 cifar_small.cfg
avgpool上面那个convolutional中的filter为自己的类别数。max_batches和学习率之类的自己按照自己的需要来调整。
万事俱备,开始训练:
终端进入darknet根目录,输入
然后坐等结果吧
1.车牌检测
2.字符分割
3.字符识别
1.车牌检测
为实现更稳定的检测性能,使用yolo来对车牌进行识别。具体的训练方法见darknet用自己的数据进行训练。数据由EasyPR提供的200多张和自己从网上爬的几百张组成,爬虫脚本和数据标注方法见自行准备深度学习训练数据。最终得到的效果不错,下面是一些测试结果:2.字符分割
利用EasyPR开源的代码来实现字符分割,在源代码下修改如下:1.src/core/plate_locate.cpp中注释掉int CPlateLocate::plateLocate(Mat src, vector &resultVec, int index)函数中的两行:
int CPlateLocate::plateLocate(Mat src, vector<Mat> &resultVec, int index) { vector<CPlate> all_result_Plates; plateColorLocate(src, all_result_Plates, index); //plateSobelLocate(src, all_result_Plates, index); //plateMserLocate(src, all_result_Plates, index); for (size_t i = 0; i < all_result_Plates.size(); i++) { CPlate plate = all_result_Plates[i]; resultVec.push_back(plate.getPlateMat()); } return 0; }
2.将test中全部删除,只保留chars.hpp和main.cpp
chars.hpp:
#ifndef EASYPR_CHARS_HPP #define EASYPR_CHARS_HPP namespace easypr { namespace demo { int test_chars_segment() { cv::Mat src = cv::imread("resources/image/try_3.jpg"); std::vector<cv::Mat> resultVec; CPlateLocate plate; int result = plate.plateLocate(src, resultVec); if(result==0) { size_t num = resultVec.size(); for(size_t j=0;j<num;j++) { std::vector<cv::Mat> resultVec2; cv::Mat resultMat = resultVec[j]; CCharsSegment plate2; int result2 = plate2.charsSegment(resultMat, resultVec2); if(result2==0) { size_t num2=resultVec2.size(); for(size_t i=0;i<num2;i++) { cv::Mat resultMat2 = resultVec2[i]; cv::imshow("chars_segment", resultMat2); cv::waitKey(0); } cv::destroyWindow("chars_segment"); } } } return result; } } } #endif // EASYPR_CHARS_HPP
main.cpp:
#include "easypr.h" #include "chars.hpp" namespace easypr { namespace demo { int testMain() { assert(test_chars_segment() == 0); return 0; } } // namespace demo } // namespace easypr int main(int argc, const char* argv[]) { easypr::demo::testMain(); return 0; }
这样处理后,终端在EasyPR根目录下输入
./demo
即可显示车牌分割后的字符
3.字符识别
依然使用darknet来进行字符识别。不同于检测,这次使用darknet的classfier函数进行训练和识别,并考虑到分割出来的字符很小,使用了很浅的网络。
利用EasyPR提供的字符识别训练集(即resource/train/ann.7z)进行训练。将数据集解压后,每个文件夹中都有着对应的字符数据,对每个文件夹进行重命名处理。每个图像的命名格式采用(图片序号)_(标签).(图片格式)的格式进行命名。
重命名方法可以参考自行准备深度学习训练数据中的第2点。
重命名完成后,在darknet/data文件夹下新建char文件夹,并在char文件夹下新建image文件夹,将重命名完成的图片统一复制到image文件夹中,再使终端进入char路径(即darknet/data/char),输入
find `pwd`/image -name \*.jpg > train.list
会在char文件夹下自动生成train.list文件,其中包含每个图像的绝对路径。
在darknet/cfg文件夹下新建cifar.data(名字cifar可以自定义),并进行如下改写:
classes=65 train = data/char/train.list labels = data/char/labels.txt backup = backup/ top=2
class 为识别类别数量,train为train.list路径,label为label文件路径。如果需要训练完后的评估,请参照train.list的方法生成val.list,然后再cifar中增加一行
valid=(your path)
然后在char文件夹下新建labels.txt:
每行一个类别标签。
标签的注意事项
1.不区分大小写
2.不能有包含关系,如ji和jin,不能出现这样的形式,可改为ji1和jin
最后,cfg文件夹下新建 cifar_small.cfg
[net] batch=128 subdivisions=1 height=28 width=28 channels=3 max_crop=32 min_crop=32 hue=.1 saturation=.75 exposure=.75 learning_rate=0.01 policy=poly power=4 max_batches = 5000000 momentum=0.9 decay=0.0005 [convolutional] batch_normalize=1 filters=32 size=3 stride=1 pad=1 activation=leaky [maxpool] size=2 stride=2 [convolutional] batch_normalize=1 filters=64 size=3 stride=1 pad=1 activation=leaky [maxpool] size=2 stride=2 [convolutional] batch_normalize=1 filters=128 size=3 stride=1 pad=1 activation=leaky [convolutional] filters=65 size=1 stride=1 pad=1 activation=leaky [avgpool] [softmax] groups=1 [cost] type=sse
avgpool上面那个convolutional中的filter为自己的类别数。max_batches和学习率之类的自己按照自己的需要来调整。
万事俱备,开始训练:
终端进入darknet根目录,输入
./darknet classifier train cfg/cifar.data cfg/cifar_small.cfg
然后坐等结果吧
相关文章推荐
- 从零使用OpenCV快速实现简单车牌识别系统
- EasyPR--一个开源的中文车牌识别系统—的简介
- 基于模板匹配的车牌识别系统实例
- 车牌识别停车计费系统性能表现二 计费系统功能强大
- 基于opencv的车牌识别系统
- 解析车牌识别相机在称重系统中的应用方案
- 从零使用OpenCV快速实现简单车牌识别系统
- Java编写的车牌识别系统
- 汽车车牌定位识别系统的设计实现
- 基于模板匹配的车牌识别系统实例
- 车牌识别系统 opencv
- 车牌识别计费系统 优越表现三 LED显示和语音播报
- 车牌识别api接口—移动端安卓、iOS系统的OCR技术
- 车牌识别一体机与4S店CRM系统结合
- 浅谈嵌入式车牌识别一体机的地磅管理系统方案
- EasyPR-开源的车牌识别系统
- OCR算法:车牌识别在停车系统中的工作原理
- 车牌识别计费系统 优越表现四 高速智能道闸
- 车牌识别LPR系统系列文章汇总
- 从零使用OpenCV快速实现简单车牌识别系统