Compare commits

...

1 Commits
main ... main

@ -1,148 +0,0 @@
#ifndef EASYPR_CONFIG_H_
#define EASYPR_CONFIG_H_
#define CV_VERSION_THREE_ZERO
namespace easypr {
enum Color { BLUE, YELLOW, WHITE, UNKNOWN };
enum LocateType { SOBEL, COLOR, CMSER, OTHER };
enum CharSearchDirection { LEFT, RIGHT };
enum
{
PR_MODE_UNCONSTRAINED,
PR_MODE_CAMERPOHNE,
PR_MODE_PARKING,
PR_MODE_HIGHWAY
};
enum
{
PR_DETECT_SOBEL = 0x01, /**Sobel detect type, using twice Sobel */
PR_DETECT_COLOR = 0x02, /**Color detect type */
PR_DETECT_CMSER = 0x04, /**Character detect type, using mser */
};
static const char* kDefaultSvmPath = "model/svm_hist.xml";
static const char* kLBPSvmPath = "model/svm_lbp.xml";
static const char* kHistSvmPath = "model/svm_hist.xml";
static const char* kDefaultAnnPath = "model/ann.xml";
static const char* kChineseAnnPath = "model/ann_chinese.xml";
static const char* kGrayAnnPath = "model/annCh.xml";
//This is important to for key transform to chinese
static const char* kChineseMappingPath = "model/province_mapping";
typedef enum {
kForward = 1, // correspond to "has plate"
kInverse = 0 // correspond to "no plate"
} SvmLabel;
static const int kPlateResizeWidth = 136;
static const int kPlateResizeHeight = 36;
static const int kShowWindowWidth = 1000;
static const int kShowWindowHeight = 800;
static const float kSvmPercentage = 0.7f;
static const int kCharacterInput = 120;
static const int kChineseInput = 440;
static const int kAnnInput = kCharacterInput;
static const int kCharacterSize = 10;
static const int kChineseSize = 20;
static const int kPredictSize = kCharacterSize;
static const int kNeurons = 40;
static const char *kChars[] = {
"0", "1", "2",
"3", "4", "5",
"6", "7", "8",
"9",
/* 10 */
"A", "B", "C",
"D", "E", "F",
"G", "H", /* {"I", "I"} */
"J", "K", "L",
"M", "N", /* {"O", "O"} */
"P", "Q", "R",
"S", "T", "U",
"V", "W", "X",
"Y", "Z",
/* 24 */
"zh_cuan" , "zh_e" , "zh_gan" ,
"zh_gan1" , "zh_gui" , "zh_gui1" ,
"zh_hei" , "zh_hu" , "zh_ji" ,
"zh_jin" , "zh_jing" , "zh_jl" ,
"zh_liao" , "zh_lu" , "zh_meng" ,
"zh_min" , "zh_ning" , "zh_qing" ,
"zh_qiong", "zh_shan" , "zh_su" ,
"zh_sx" , "zh_wan" , "zh_xiang",
"zh_xin" , "zh_yu" , "zh_yu1" ,
"zh_yue" , "zh_yun" , "zh_zang" ,
"zh_zhe"
/* 31 */
};
static const int kCharactersNumber = 34;
static const int kChineseNumber = 31;
static const int kCharsTotalNumber = 65;
static bool kDebug = false;
static const int kGrayCharWidth = 20;
static const int kGrayCharHeight = 32;
static const int kCharLBPGridX = 4;
static const int kCharLBPGridY = 4;
static const int kCharLBPPatterns = 16;
static const int kCharHiddenNeurans = 64;
static const int kCharsCountInOnePlate = 7;
static const int kSymbolsCountInChinesePlate = 6;
static const float kPlateMaxSymbolCount = 7.5f;
static const int kSymbolIndex = 2;
// Disable the copy and assignment operator for this class.
#define DISABLE_ASSIGN_AND_COPY(className) \
private:\
className& operator=(const className&); \
className(const className&)
// Display the image.
#define SET_DEBUG(param) \
kDebug = param
// Display the image.
#define SHOW_IMAGE(imgName, debug) \
if (debug) { \
namedWindow("imgName", WINDOW_AUTOSIZE); \
moveWindow("imgName", 500, 500); \
imshow("imgName", imgName); \
waitKey(0); \
destroyWindow("imgName"); \
}
// Load model. compatitable withe 3.0, 3.1 and 3.2
#ifdef CV_VERSION_THREE_TWO
#define LOAD_SVM_MODEL(model, path) \
model = ml::SVM::load(path);
#define LOAD_ANN_MODEL(model, path) \
model = ml::ANN_MLP::load(path);
#else
#define LOAD_SVM_MODEL(model, path) \
model = ml::SVM::load<ml::SVM>(path);
#define LOAD_ANN_MODEL(model, path) \
model = ml::ANN_MLP::load<ml::ANN_MLP>(path);
#endif
}
#endif // EASYPR_CONFIG_H_

@ -0,0 +1,39 @@
**I'm submitting a ...** (check one with "x")
```
[ ] bug report
[ ] help wanted
[ ] feature request
```
**Current behavior**
**Expected/desired behavior**
**Reproduction of the problem**
If the current behavior is a bug or you can illustrate your feature request better with an example, please provide the steps to reproduce.
**What is the expected behavior?**
**What is the motivation / use case for changing the behavior?**
**Please tell us about your environment:**
* **System:** CentOS
* **Compiler version/IDE:** gcc4.8
* **CMake version:** 3.5.1
* **OpenCV version:** [2.4.9 | 2.4.10 | 2.4.11 | 2.4.12 | 2.4.13 | 3.0 ALPHA | 3.0 BETA | 3.0 RC1 | 3.0 | 3.1 ]

44
src/.gitignore vendored

@ -0,0 +1,44 @@
.idea/
_build/
resources/image/tmp/
*.lib
*.suo
*.sdf
*.opensdf
*.exe
*.dll
*.ilk
*.pdb
experi
/tmp
resources/image/native_test/*.jpg
resources/image/native_test/cars
resources/image/native_test/*.py
resources/image/phone_test
*.vsp
*.psess
*.DS_Store
#ignore thumbnails created by windows
Thumbs.db
#Ignore files build by Visual Studio
*.user
*.aps
*.pch
*.vspscc
*_i.c
*_p.c
*.ncb
*.tlb
*.tlh
*.bak
[Dd]ebug*/
*.sbr
obj/
[Rr]elease*/
_ReSharper*/
[Tt]est[Rr]esult*
*.obj
*.cache
*.log

@ -0,0 +1,64 @@
cmake_minimum_required(VERSION 3.0.0)
project(easypr)
# c++11 required
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/local/opt/opencv-3.2.0")
endif ()
# OpenVC3 required
find_package(OpenCV 3.2.0 REQUIRED)
# where to find header files
include_directories(.)
include_directories(include)
include_directories(${OpenCV_INCLUDE_DIRS})
# sub directories
add_subdirectory(thirdparty)
# sources to be compiled
set(SOURCE_FILES
src/core/core_func.cpp
src/core/chars_identify.cpp
src/core/chars_recognise.cpp
src/core/chars_segment.cpp
src/core/feature.cpp
src/core/plate_detect.cpp
src/core/plate_judge.cpp
src/core/plate_locate.cpp
src/core/plate_recognize.cpp
src/core/params.cpp
src/train/ann_train.cpp
src/train/annCh_train.cpp
src/train/svm_train.cpp
src/train/train.cpp
src/train/create_data.cpp
src/util/util.cpp
src/util/program_options.cpp
src/util/kv.cpp
)
# pack objects to static library
add_library(easypr STATIC ${SOURCE_FILES})
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
set(EXECUTABLE_NAME "demo")
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
set(EXECUTABLE_NAME "demo")
endif ()
# set to be releas mode
# set(CMAKE_BUILD_TYPE Release)
# test cases
add_executable(${EXECUTABLE_NAME} test/main.cpp)
# link opencv libs
target_link_libraries(${EXECUTABLE_NAME} easypr thirdparty ${OpenCV_LIBS})
# MESSAGE(${CMAKE_BINARY_DIR}/../)
SET_TARGET_PROPERTIES(${EXECUTABLE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/../")

@ -0,0 +1,226 @@
EasyPR版本更新
======
本次更新版本是1.6alpha版本,主要改进如下:
1. 采用灰度字符训练以及新的特征使中文字符正确率上升到了86%比上个版本提升了近14个百分点。
2. 借助于字符分割与识别算法的优化在general_test上的完整识别率(0-error)从原先的59%首次上升到现在的70%1-error则提升到了82%,提升巨大。
3. 在车牌判断模块中使用了新的SVM特征颜色+投影从而在保持鲁棒性的同时提升了正确率。定位指标中FScore从76%提升到82%.
4. 新增一种新的字符分割方法groundMSER字符分割方法。
5. 提供了近万张中文字符灰度图数据供训练并且在主界面中提供了一个方法从free大神的车牌集里提取中文与英文字符。
6. 提供了两万两千张的字符灰度图数据,供训练灰度字符模型使用。
7. 代码优化与升级许多bug修复。
8. Opencv3.2版本的支持编译前仅需要将config.h中将#define CV_VERSION_THREE_ZERO改为#define CV_VERSION_THREE_TWO即可。
9. 更加友好的linux与mac版本支持使用CMake即可顺利编译单独的utf-8与gbk的文件供分别的系统使用。
======
本次更新是EasyPR 1.5正式版本相比beta版本有以下几点更新
1.修正了SVM训练异常的问题现在1.5版本也可以自由的使用SVM训练了。这个问题确实是opencv的bug详见[讨论](https://github.com/opencv/opencv/issues/5054),在此感谢 @tka 同学的告知。
注意3.2的opencv也修正了这个问题如果你用3.2版本的话也可以。但是不清楚3.2版本是否会引入其他的问题在目前的EasyPR版本里即便用3.0或者3.1版本也可以规避训练异常的问题。
2.支持linux和mac编译如果碰到问题请在issue里提问。
3.增加一个无需配置opencv的[懒人版](http://git.oschina.net/easypr/EasyPR/attach_files)。仅仅支持vs2013也只能在debug和x86下运行其他情况的话还是得配置opencv。感谢范文捷同学的帮助。页面里的两个文件都要下载下载后用[7zip](http://www.7-zip.org/)解压。
其他的主要改进如下:
1.增加了一种新的基于文字定位的定位方法 (MSER), 在面对低对比度,低光照以及大图像上有较强的鲁棒性。
* 夜间的车牌图像
![夜间的车牌图像](resources/doc/res/night_1.jpg)
* 对比度非常低的图像
![对比度非常低的图像](resources/doc/res/contrast_1.jpg)
* 近距离的图像
![近距离的图像](resources/doc/res/near_1.jpg)
* 高分辨率的图像
![高分辨率的图像](resources/doc/res/big_1.jpg)
2.更加合理的评价协议。结合新增的GroundTruth文件与ICDAR2003的协议使得整体评价指标更为合理。通用数据集里同时增加了近50张新图片。文字定位方法在面对这些复杂图片时比先前的SOBEL+COLOR的方法定位率提升了27个百分点。
实际运行时使用了文字定位与颜色定位的结合最终对256张的测试图片的测试结果如下
![v1.5版运行结果](resources/doc/res/v1.5_result.jpg)
3.使用了非极大值抑制算法去除相邻的车牌,使得最终输出变的合理。即便使用多个定位方法,最终也只会输出一个车牌,而且是可能性最大的车牌。
4.基于局部空间的大津阈值算法与自适应阈值算法,提升了文字分割与分子识别的准确率。
* 车牌图像
![车牌图像](resources/doc/res/not_avg_contrast.jpg)
* 普通大津阈值结果
![普通大津阈值结果](resources/doc/res/normal_ostu.jpg)
* 空间大津阈值结果
![空间大津阈值结果](resources/doc/res/spatial_ostu.jpg)
5.新的SVM模型与特征LBP提升了车牌判断的鲁棒性新的中文ANN识别模型提升了中文识别的整体准确率近15个百分点。
6.增加了Grid Search方法可以进行自动调参。
7.首次增加了多线程支持基于OpenMP的文字定位方法在最终的识别速度上比原先的单线程方法提高了接近2倍。
8.替换了一部分中文注释使得windows下的visual studio在面对全部以LF结尾的文件时也能成功通过编译。目前的程序只要opencv配置正确gitosc上通过zip下载下来的程序可以直接通过编译并运行。
关于本次改动的具体内容可以看博客中的[介绍](http://www.cnblogs.com/subconscious/p/5637735.html)。
======
本次更新是1.4 正式版,主要改进在于几个方面:
1.代码统一为UTF-8格式多平台的Shell不再出现乱码。
2.支持opencv3.0与3.1注意这与opencv2.x不兼容要想支持的话请下载1.3版本。
3.ANN训练开放。
4.修正了SVM训练异常的问题。
5.代码优化。
不知道怎么下载以前的版本的小伙伴可以在github或gitosc的"branch"里选择"tags",然后点击"v1.3",再然后点击"download zip"。当然如果直接git clone的话可以随时方便切换。
在后面的版本中计划做以下几点改善:
1.新的评价框架,更加合理的评估数据。
2.新的车牌定位算法。
======
本次更新是1.3beta版,主要改进在于提升了字符识别模块的准确性:
平均字符差距从0.7降低到0.4完整匹配度从68%左右上升到目前的81%平均执行时间从2秒降低到1.5秒。见下图:
![1.3版综合效果](resources/doc/res/testresult_1.3beta.png)
主要改动如下:
* 改进了字符识别算法重新训练了ANN模型从而使得字符识别准确率大幅度提升。
* 使用了更鲁棒性的办法提升了车牌定位模块的准确率。
目前版本的问题是处理时间还是偏高1.3正式版本中会对这个问题进行fix。
======
本次更新是1.3alpha版,主要改进在于提升了字符识别模块的准确性:
平均字符差距从2.0降低到0.7完整匹配度从25%左右上升到目前的68%。
同时车牌定位模块准确率进一步提升从上一个版本的94%上升到现在的99%。见下图:
![1.3版综合效果](resources/doc/res/testresult_1.3alpha.png)
主要改动如下:
* 改进了字符识别算法重新训练了ANN模型从而使得字符识别准确率大幅度提升。
* 使用了更鲁棒性的办法提升了车牌定位模块的准确率。
目前版本的问题是处理时间大幅度上升1.3正式版本中会对这个问题进行fix。
======
本次更新是1.2版主要改进在于提升了车牌定位模块的准确性从70%左右到目前的94%,见下图:
![1.2版综合效果](resources/doc/res/testresult.png)
主要改动如下:
* 车牌定位使用了“颜色信息”+“二次Sobel”的综合搜索方法。在下面的window中红框代表Sobel定位结果黄框代表颜色定位结果。
* “批量测试”增加了一个结果查看window这个窗口可以用SetDebug()方法开闭(true开false关)。
![查看结果](resources/doc/res/window.png)
* 基本攻克了“大角度定位”问题,下图的车牌被定位并转到了正确的视角。
![大角度定位](resources/doc/res/bigangle.png)
* GDTS里新增了若干张新测试图包括数张大角度图。
* “批量测试”结果现在同时会保存在“run_accuracy”文件中可以查询历史信息。
* 与Linux版本做了整合可以实现跨平台编译。
======
目前EasyPR的版本是1.1相比上一个版本1.0,有以下更新(这次的更新内容较多,为了跟你现有的项目和代码不冲突,请
谨慎选择全部更新,最好新起一个目录试试新增的功能和内容):
* 新的SVM模型。新模型使用rbf核替代了liner核在车牌判断的准确率提升了8个百分点。
![svm准确率改进](resources/doc/res/svm_upgragde.png)
* 新增两个特征提取方法。并提供了相关的回调函数接口供二次开发。
![fetures](resources/doc/res/fetures.png)
* 新增Debug模式。可以在image/tmp文件夹下看到所有输出的中间图片。
![Debug模式](resources/doc/res/debug.jpg)
* 增加了LifeMode模式相比默认模式更适合在生活场景下定位车牌。
![LifeMode模式](resources/doc/res/lifemode.jpg)
* 增加了批量测试功能这个功能可供测试EasyPR在多幅图片上的整体表现效果。
![批量测试](resources/doc/res/batch_operation.jpg) ![批量测试结果](res/batch_result.png)
* 引入了GDTS(General Data Test Set通用数据测试集)这个概念作为EasyPR准确率的评测数据集。
![GDTS](resources/doc/res/general_test.jpg)
* 为了确保GDTS的数据仅用于非商业目的引入了新的[GDSL协议](../image/GDSL.txt)。
![GDSL](resources/doc/res/gdsl.jpg)
* 完善SVM训练功能。提供了一个方便简单的训练窗口。这些增加的功能是为了配合即将推出的SVM开发详解这篇文章。
![SVM训练](resources/doc/res/svm_train.jpg)
* 强化SVM模型验证。使用了三个新的数据集概念即learn datatrain datatest data。
![SVM训练集](resources/doc/res/svm_data.jpg)
* 新增评价指标。引入PreciseRecallFSocre三个指标这三个指标作为SVM模型准确率评判的参数与改善的依据。
![SVM指标](resources/doc/res/svm_rate.jpg)
* 新增整体指标。引入levenshtein距离作为EasyPR整体识别准确率误差的评判参数与改善依据。
![levenshtein1](resources/doc/res/levenshtein1.jpg) ![levenshtein2](resources/doc/res/levenshtein2.jpg) ![levenshtein3](resources/doc/res/levenshtein3.jpg)
![levenshteinAll](resources/doc/res/levenshteinAll.JPG)
* 大幅增加训练数据。SVM训练数据中增加了近千张新数据(未经直方图均衡化的车牌图片和非车牌图片)。
请自行解压train/data/plate_detect_svm/learn下的压缩文件查看相关信息。
* 新增命令行窗口,作为测试与训练的辅助工具。
注意上一个版本中image文件下的test.jpg如果有同学下载了请删除。它的格式不符合新的GDSL协议的约定。
如果想使用测试图片可以使用1.1版本中新增的test.jpg替代。

@ -0,0 +1,43 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demo", "vcprojs\demo.vcxproj", "{FADCD7E1-8071-4F1C-8071-C469569C3B56}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libeasypr", "vcprojs\libeasypr.vcxproj", "{2791E339-04FB-44EF-9F92-C90131FE7772}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FA4945DA-3C0F-44C5-90DF-A492614B8B4D}"
ProjectSection(SolutionItems) = preProject
Usage.md = Usage.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FADCD7E1-8071-4F1C-8071-C469569C3B56}.Debug|Win32.ActiveCfg = Debug|Win32
{FADCD7E1-8071-4F1C-8071-C469569C3B56}.Debug|Win32.Build.0 = Debug|Win32
{FADCD7E1-8071-4F1C-8071-C469569C3B56}.Debug|x64.ActiveCfg = Debug|x64
{FADCD7E1-8071-4F1C-8071-C469569C3B56}.Debug|x64.Build.0 = Debug|x64
{FADCD7E1-8071-4F1C-8071-C469569C3B56}.Release|Win32.ActiveCfg = Release|Win32
{FADCD7E1-8071-4F1C-8071-C469569C3B56}.Release|Win32.Build.0 = Release|Win32
{FADCD7E1-8071-4F1C-8071-C469569C3B56}.Release|x64.ActiveCfg = Release|x64
{FADCD7E1-8071-4F1C-8071-C469569C3B56}.Release|x64.Build.0 = Release|x64
{2791E339-04FB-44EF-9F92-C90131FE7772}.Debug|Win32.ActiveCfg = Debug|Win32
{2791E339-04FB-44EF-9F92-C90131FE7772}.Debug|Win32.Build.0 = Debug|Win32
{2791E339-04FB-44EF-9F92-C90131FE7772}.Debug|x64.ActiveCfg = Debug|x64
{2791E339-04FB-44EF-9F92-C90131FE7772}.Debug|x64.Build.0 = Debug|x64
{2791E339-04FB-44EF-9F92-C90131FE7772}.Release|Win32.ActiveCfg = Release|Win32
{2791E339-04FB-44EF-9F92-C90131FE7772}.Release|Win32.Build.0 = Release|Win32
{2791E339-04FB-44EF-9F92-C90131FE7772}.Release|x64.ActiveCfg = Release|x64
{2791E339-04FB-44EF-9F92-C90131FE7772}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

@ -0,0 +1,254 @@
# EasyPR
EasyPR是一个开源的中文车牌识别系统其目标是成为一个简单、高效、准确的非限制场景(unconstrained situation)下的车牌识别库。
相比于其他的车牌识别系统EasyPR有如下特点
* 它基于openCV这个开源库。这意味着你可以获取全部源代码并且移植到opencv支持的所有平台。
* 它能够识别中文。例如车牌为苏EUK722的图片它可以准确地输出std:string类型的"苏EUK722"的结果。
* 它的识别率较高。图片清晰情况下车牌检测与字符识别可以达到80%以上的精度。
### 更新
本次更新版本是1.6正式版本,主要有以下几点更新:
1. 修正了多项readme的文本提示。
2. 增加了C#调用EasyPR的一个项目的链接感谢 @zhang-can 同学。
**注意**
1. 对于Opencv3.2或以上版本如果碰到编译问题例如“ANN_MLP”相关的错误尝试将config.h中将#define CV_VERSION_THREE_ZERO改为#define CV_VERSION_THREE_TWO试试.
2. linux系统推荐使用Opencv3.2以上版本。3.2以下的版本例如3.0和3.1在识别时可能会出现车牌识别结果为空的情况。稳妥起见建议都升级到最新的3.2版本。Windows版本没有这个问题。
## 待做的工作
- [ ] 完成一个CNN框架
- [ ] 替换ANN为CNN
- [ ] 增加新能源车的识别(待定)
- [ ] 增加两行车牌的识别(待定)
### 跨平台
目前除了windows平台以外还有以下其他平台的EasyPR版本。一些平台的版本可能会暂时落后于主平台。
现在有一个无需配置opencv的1.5版本的[懒人版](http://git.oschina.net/easypr/EasyPR/attach_files)。仅仅支持vs2013也只能在debug和x86下运行其他情况的话还是得配置opencv。感谢范文捷同学的帮助。页面里的两个文件都要下载下载后用[7zip](http://www.7-zip.org/)解压。
|版本 | 开发者 | 版本 | 地址
|------|-------|-------|-------
| C# | zhang-can | 1.5 | [zhang-can/EasyPR-DLL-CSharp](https://github.com/zhang-can/EasyPR-DLL-CSharp)
| android | goldriver | 1.4 | [linuxxx/EasyPR_Android](https://github.com/linuxxx/EasyPR_Android)
| linux | Micooz | 1.6 | 已跟EasyPR整合
| ios | zhoushiwei | 1.3 | [zhoushiwei/EasyPR-iOS](https://github.com/zhoushiwei/EasyPR-iOS)
| mac | zhoushiwei,Micooz | 1.6 | 已跟EasyPR整合
| java | fan-wenjie | 1.2 | [fan-wenjie/EasyPR-Java](https://github.com/fan-wenjie/EasyPR-Java)
| 懒人版 | fan-wenjie | 1.5 | [git/oschina](http://git.oschina.net/easypr/EasyPR/attach_files)
### 兼容性
当前EasyPR是基于opencv3.0版本开发的3.0及以上的版本应该可以兼容,以前的版本可能会存在不兼容的现象。
### 例子
假设我们有如下的原始图片,需要识别出中间的车牌字符与颜色:
![EasyPR 原始图片](resources/doc/res/plate_locate.jpg)
经过EasyPR的第一步处理车牌检测PlateDetect以后我们获得了原始图片中仅包含车牌的图块
![EasyPR 车牌](resources/doc/res/blue_plate.jpg)
接着我们对图块进行OCR过程在EasyPR中叫做字符识别CharsRecognize。我们得到了一个包含车牌颜色与字符的字符串
“蓝牌苏EUK722”
### 示例
EasyPR的调用非常简单下面是一段示例代码:
```c++
CPlateRecognize pr;
pr.setResultShow(false);
pr.setDetectType(PR_DETECT_CMSER);
vector<CPlate> plateVec;
Mat src = imread(filepath);
int result = pr.plateRecognize(src, plateVec);
```
我们首先创建一个CPlateRecognize的对象pr接着设置pr的属性。
```c++
pr.setResultShow(false);
```
这句话设置EasyPR是否打开结果展示窗口如下图。设置为true就是打开否则就是关闭。在需要观看定位结果时建议打开快速运行时关闭。
![EasyPR 输出窗口](resources/doc/res/window.png)
```c++
pr.setDetectType(PR_DETECT_CMSER);
```
这句话设置EasyPR采用的车牌定位算法。CMER代表文字定位方法SOBEL和COLOR分别代表边缘和颜色定位方法。可以通过"|"符号结合。
```c++
pr.setDetectType(PR_DETECT_COLOR | PR_DETECT_SOBEL);
```
除此之外,还可以有一些其他的属性值设置:
```c++
pr.setLifemode(true);
```
这句话设置开启生活模式这个属性在定位方法为SOBEL时可以发挥作用能增大搜索范围提高鲁棒性。
```c++
pr.setMaxPlates(4);
```
这句话设置EasyPR最多查找多少个车牌。当一副图中有大于n个车牌时EasyPR最终只会输出可能性最高的n个。
下面来看pr的方法。plateRecognize()这个方法有两个参数第一个代表输入图像第二个代表输出的车牌CPlate集合。
```c++
vector<CPlate> plateVec;
Mat src = imread(filepath);
int result = pr.plateRecognize(src, plateVec);
```
当返回结果result为0时代表识别成功否则失败。
CPlate类包含了车牌的各种信息其中重要的如下
```c++
CPlate plate = plateVec.at(i);
Mat plateMat = plate.getPlateMat();
RotatedRect rrect = plate.getPlatePos();
string license = plate.getPlateStr();
```
plateMat代表车牌图像rrect代表车牌的可旋转矩形位置license代表车牌字符串例如“蓝牌苏EUK722”。
这里说下如何去阅读如下图的识别结果。
![EasyPR DetectResults](resources/doc/res/one_image_detect.jpg)
第1行代表的是图片的文件名。
第2行代表GroundTruth车牌用后缀g表示。第3行代表EasyPR检测车牌用后缀d表示。两者形成一个配对第4行代表两者的字符差距。
下面同上。本图片中有3个车牌所有共有三个配对。最后的Recall等指标代表的是整幅图片的定位评价考虑了三个配对的结果。
有时检测车牌的部分会用“无车牌”与“No string”替代。“无车牌”代表“定位不成功”“No string”代表“定位成功但字符分割失败”。
### 版权
EasyPR的源代码与训练数据遵循Apache v2.0协议开源。
EasyPR的resources/image/general_test文件夹下的图片数据遵循[GDSL协议](image/GDSL.txt)(通用数据共享协议)进行开放。
请确保在使用前了解以上协议的内容。
### 目录结构
以下表格是本工程中所有目录的解释:
|目录 | 解释
|------|----------
| src | 所有源文件
| include | 所有头文件
| test | 测试程序
| model | 机器学习的模型
| resources/text | 中文字符映射表
| resources/train | 训练数据与说明
| resources/image | 测试用的图片
| resources/doc | 相关文档
| tmp | 训练数据读取目录,需要自建
以下表格是resources/image目录中子目录的解释:
|目录 | 解释
|------|----------
| general_test | GDTS通用数据测试集
| native_test | NDTS本地数据测试集
| tmp | Debug模式下EasyPR输出中间图片的目录需要自建
以下表格是src目录中子目录的解释:
|目录 | 解释
|------|----------
| core | 核心功能
| preprocess | SVM预处理
| train | 训练目录,存放模型训练的代码
| util | 辅助功能
以下表格是src目录下一些核心文件的解释与关系:
|文件 | 解释
|------|----------
| plate_locate | 车牌定位
| plate_judge | 车牌判断
| plate_detect | 车牌检测,是车牌定位与车牌判断功能的组合
| chars_segment | 字符分割
| chars_identify | 字符鉴别
| chars_recognise | 字符识别,是字符分割与字符鉴别功能的组合
| plate_recognize | 车牌识别,是车牌检测与字符识别的共有子类
| feature | 特征提取回调函数
| plate | 车牌抽象
| core_func.h | 共有的一些函数
以下表格是test目录下文件的解释:
|文件 | 解释
|------|----------
| main.cpp | 主命令行窗口
| accuracy.hpp | 批量测试
| chars.hpp | 字符识别相关
| plate.hpp | 车牌识别相关
以下表格是train目录下文件的解释:
|文件 | 解释
|------|----------
| ann_train.cpp | 训练二值化字符
| annCh_train.hpp | 训练中文灰度字符
| svm_train.hpp | 训练车牌判断
| create_data.hpp | 生成合成数据
### 使用
请参考[这里](Usage.md)
### 获取帮助
详细的开发与教程请见[介绍与开发教程](http://www.cnblogs.com/subconscious/p/3979988.html)。
如果你在使用过程中遇到任何问题,请在[这里](https://github.com/liuruoze/EasyPR/issues)告诉我们。
EasyPR讨论QQ群号是一群366392603二群583022188三群637614031四群548362608加前请注明EasyPR学习讨论。
### Contributors
* liuruoze1.0-1.21.5版作者
* 海豚嘎嘎(车主之家)1.3版算法贡献者,提升了车牌定位与字符识别的准确率
* Micooz1.3-1.4版架构重构linux与mac支持opencv3.0支持utf-8编码转换
* jsxyheludeface版本一
* zhoushiweideface版本二
* ahccom新的plateLocate函数
* 阿水1.3版整合,数据标注等工作
* fan-wenjie1.5版opencv整合版提供者
* Free1.6版数据提供者
### 鸣谢
taotao1233邱锦山唐大侠jsxyhelu如果有一天(zhoushiwei)学习奋斗袁承志圣城小石匠goldriverMicooz梦里时光Rain Wang任薛纪ahccom星夜落尘海豚嘎嘎(车主之家)刘超Free大神以及所有对EasyPR贡献数据的热心同学。

@ -0,0 +1,200 @@
# 使用
### 获取源代码
可以访问我们的项目主页获取代码:
* [github](https://github.com/liuruoze/EasyPR)
* [oschina](https://git.oschina.net/easypr/EasyPR)
如果你熟悉git版本控制工具可以使用下面的命令从 Github 克隆代码:
$ git clone https://github.com/liuruoze/EasyPR
### 准备工作
1. 安装OpenCV
从 [OpenCV官方网站](http://opencv.org/) 获取对应平台的 `OpenCV3.1.0`
EasyPR支持当前主流的操作系统通常不需要对源代码进行更改就可以编译运行尽管如此不同平台上IDE的配置也是有很大差异的下面主要说明WindowsLinux以及Mac OS下的编译方法。
#### Windows
对于使用 Windows 的同学建议的IDE是Visual Studio如果使用的不是VS请自行配置也欢迎分享你的配置方案。
|环境 | 需求
|------|----------
| 操作系统 | 64位Windows7 sp1 / Windows 8 及以上
| Visual Studio | vs2013 / vs2015
| Python可选 | Python3.*
**Note**: 预编译的 **OpenCV3.1** 已经不支持较低版本的Visual Studio请选择vs2013及以上的版本。
**方法一**
**注意**: python方法仅针对v1.5以下的版本。在1.6及以上版本中,由于架构变化,不推荐使用。可以加群看群里的配置方法。
1. 确保将Python的安装目录添加到系统环境变量PATH中。
2. 执行 `python configure.py` ,根据提示填写相关信息。
3. 打开解决方案文件 `EasyPR.sln`,直接编译运行即可。
**方法二**
打开解决方案文件 `EasyPR.sln`,该解决方案会加载两个项目:
* `EasyPR`用于编译src/下的源文件生成静态库`libeasypr.lib`
* `Demo`用来编译test/下的main.cpp并链接libeasypr.lib生成可执行程序。
**配置OpenCV**
OpenCV for Windows 通常会将使用VS编译好二进制文件放到 `opencv\build\` 目录下。
解决方案自动加载的两个项目配置不符合你的环境,请依次手动配置:
**demo**
| 配置项 | 值
|-------------|-----------
| `C/C++`-`附加包含目录` | **[opencv的include目录]**;$(SolutionDir)include
| `链接器`-`附加库目录` | **[opencv的lib目录]**
| `链接器`-`输入`-`附加依赖项` | **opencv_world310d.lib**;%(AdditionalDependencies)
*Note*Debug版本为**opencv_world310d.lib**Release版本为**opencv_world310.lib**
**libeasypr**
| 配置项 | 值
|-------------|-----------
| `C/C++`-`附加包含目录` | **[opencv的include目录]**;$(SolutionDir)include
**编译**
默认情况下,生成的 `demo.exe` 会放在项目根目录下。
**Note**: 直接双击运行程序会出现找不到opencv动态库的情况这个时候有两个办法
* 在`opencv\build\x64\vc(..)\bin`下找到缺失的dll放到执行目录下。
* 将上述bin目录添加到系统环境变量**PATH**中,然后重新运行程序。
**参考**windows平台下的opencv的手动配置可以参考这份[博客](http://my.phirobot.com/blog/2014-02-opencv_configuration_in_vs.html)。
#### Linux & Mac OS
EasyPR使用CMake在Linux及Mac OS下进行构建确保系统安装了最新版本的[CMake](http://cmake.org)。
为了避免系统中安装的老版本opencv对编译的影响需要在 `CMakeLists.txt` 中修改:
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/local/opt/opencv3")
路径指向opencv3的安装目录该目录下应该有OpenCV的CMake配置文件。
项目提供了一键编译shell在项目根目录下执行
```
$ ./build.sh
```
即可。
----
**Note**: *你可以直接利用 EasyPR/include 和编译生成的静态库来调用EasyPR提供的函数接口编写自己的程序。*
运行Demo
```
$ ./demo // 进入菜单交互界面
$ ./demo ? // 查看CLI帮助
```
### 如何开始
当进入交互界面以后,首先是主目录,下面是主目录各个功能的解释:
| 名称 | 说明
|-------------|-----------
| 测试 | 分别测试车牌识别中每个环节。要想更改测试的图片可以替换resources/image下的图片
| 批量测试 | 跑完整个general_test下所有图片输出准确率等指标用于评估EasyPR的效果
| SVM训练 | 用SVM训练车牌判断模型
| ANN训练 | 用ANN训练字符识别和中文识别模型对应ann.xml和ann_chinese.xml
| 中文训练 | 1.6版新增用ANN模型训练灰度中文字符生成annCh.xml
| 生成字符 | 需要配合plates_200k这个数据集才能作用
当成功运行EasyPR后首先运行批量测试功能。如果最后的指标跟readme一致说明EasyPR安装成功。
可以在accuracy.hpp中修改 `pr.setResultShow(false)``pr.setResultShow(true)` 让批量测试显示出车牌定位的效果。
**Note**:
在批量测试下有一个选项native_test。可以把自己的图片放到resources/image/native_test下测试用的。如果你自己的图片没有ground_truth无法计算准确率指标。但是可以打开车牌定位的效果。
如果想评估车牌定位的指标。需要生成GroundTruth_windows.xml和GroundTruth_others.xml。可以参考general_test下的同名文件来了解下这个文件的格式该如何定义。例如下面的一个xml节点
```xml
<taggedRectangle x="170" y="184" width="96" height="27" rotation="-1" locateType="1">蓝牌:京A88731</taggedRectangle>
```
taggedRectangle对应一个车牌属性x和y表示的是车牌外接矩形的中心点的坐标。width和height是宽度和高度。另外两个属性目前没用到。
GroundTruth_windows.xml的编码需要设置为ANSI而GroundTruth_others.xml的编码要设置为UTF-8否则会出现乱码。
### 命令行示例
可以向 `demo[.exe]` 传递命令行参数来完成你想要的工作目前Demo支持5个子命令。对于每个子命令的帮助信息可以传入 `-h` 参数来获取。
**车牌识别**
# 利用提供的SVM和ANN模型来识别一张图片里面的所有车牌
$ ./demo recognize -p resources/image/plate_recognize.jpg --svm model/svm.xml --ann model/ann.xml
# 或者更简单一些(注意模型路径)
$ ./demo recognize -p resources/image/plate_recognize.jpg
**SVM训练**
新版本的EasyPR大大简化了SVM训练
# 首先准备好车牌图片集合plates/
# 是车牌的放在plates/has/
# 不是车牌的放在plates/no/
# 车牌可从项目resources/train/svm.7z中解压得到。
$ ./demo svm --plates=path/to/your/plates --svm=save/to/svm.xml
# 该命令将70%的车牌作为训练数据另外30%的车牌作为测试数据,
# 这个只可在 include/easypr/config.h 修改。
# 将训练好的模型存放在 save/to/svm.xml。
首先在easypr的主目录下面新建了一个tmp文件夹并且把svm.7z解压得到的svm文件夹移动到tmp文件夹下面
执行 $ demo svm --plates=tmp/svm --svm=tmp/svm.xml生成得到的tmp文件夹下面的svm.xml就是训练好的模型
替换model/svm.xml就可以达到替换新模型的目的替换前请先备份原始模型。
**ANN训练**
先准备好字符图片集合可从项目resources/train/ann.7z中解压得到。
每类字符都存放在以其名称命名的子文件夹中,命名规则请参考 `resources/text/province_mapping`
一切准备就绪后,运行下面这条命令即可:
$ ./demo ann --chars=path/to/chars --ann=save/to/ann.xml
首先在easypr的主目录下面新建了一个tmp文件夹并且把ann.7z解压得到的ann文件夹移动到tmp文件夹下面
执行 $ demo ann --chars=tmp/ann --ann=tmp/ann.xml生成得到的tmp文件夹下面的svm.xml就是训练好的模型
替换model/ann.xml就可以达到替换新模型的目的替换前请先备份原始模型。
**注意**
train文件夹下有3个ann压缩包解释一下
| 文件 | 用途
|-------------|-----------
| ann.7z | 包括黑白的字符和中文数据ann以及ann_chinese.xml由这个训练得到
| annCh.7z | 仅仅包括中文的灰度数据annCh.xml由这个训练得到
| annGray.7z | 包括了灰度的字符数据目前没有任何模型由这个训练得到主要是为未来的CNN做准备

@ -0,0 +1,7 @@
#!/usr/bin/env bash
rm -rf build
mkdir build
cd build
cmake ..
make -j8

@ -0,0 +1,158 @@
# -*- coding: utf-8 -*-
# --------------------------------------------------------------------
# EasyPR auto configure script
# --------------------------------------------------------------------
#
# This script configures OpenCV3.1 for Visual Studio
# on Windows.
#
# You are required to have Python3.* installed, and python.exe must
# be added to your PATH (C:\Python34 for example).
#
# You can use it by executing:
#
# C:\> cd path\to\EasyPR
# C:\> python configure.py
#
# Note: compatible with python3, haven't been tested on python2.
#
# --------------------------------------------------------------------
import os
import re
kProjectDir = "vcprojs"
kProjects = ["libeasypr.vcxproj", "demo.vcxproj"]
kProjectTemplates = ["libeasypr.vcxproj.template", "demo.vcxproj.template"]
kOpenCVConfig = "OpenCVConfig-version.cmake"
kConfig = {
"build": "",
"include": "",
"library": "",
"link": ["opencv_world310"],
"bit": "",
"vs": ""
}
kPatterns = {
"include": "(<AdditionalIncludeDirectories>)(.*?)(</AdditionalIncludeDirectories>)",
"library": "(<AdditionalLibraryDirectories>)(.*?)(</AdditionalLibraryDirectories>)",
"link": "(<AdditionalDependencies>)(.*?)(</AdditionalDependencies>)"
}
kReplacements = {
"include": r"\1%s;\2\3",
"library": r'\1%s\3',
"link": r'\1%s;\2\3'
}
def configure():
for i in range(2):
print(">> creating %s" % kProjects[i])
tpath = os.path.join(kProjectDir, kProjectTemplates[i])
fp = open(tpath, encoding="utf-8")
try:
# read from disk
original = fp.read()
nstring = ""
if 0 == i:
nstring = configure_libeasypr(original)
elif 1 == i:
nstring = configure_demo(original)
# write to disk
wpath = os.path.join(kProjectDir, kProjects[i])
writer = open(wpath, mode="wb")
try:
writer.write(nstring.encode())
finally:
writer.close()
finally:
fp.close()
print(">> all done! Open EasyPR.sln and have fun!")
def configure_libeasypr(buffer):
# additional include dir
pattern = re.compile(kPatterns["include"])
return pattern.sub(kReplacements["include"] %
(kConfig["include"][:2] + re.escape(kConfig["include"][2:])),
buffer)
def configure_demo(buffer):
# additional include dir
pattern = re.compile(kPatterns["include"])
nstring = pattern.sub(kReplacements["include"] %
(kConfig["include"][:2] + re.escape(kConfig["include"][2:])),
buffer)
# additional library dir
pattern = re.compile(kPatterns["library"])
nstring = pattern.sub(kReplacements["library"] %
(kConfig["library"][:2] + re.escape(kConfig["library"][2:])),
nstring)
# additional dependencies
#lib_string = ""
#for lib in kConfig["link"]:
# lib_string += (lib + "d.lib")
#pattern = re.compile(kPatterns["link"])
#return pattern.sub(kReplacements["link"] % lib_string, nstring)
return nstring
def check_opencv_version():
file = os.path.join(kConfig["build"], kOpenCVConfig)
print(">> Checking ", file)
fp = open(file)
opencv_version = 0
try:
fline = fp.readline()
match = re.search(r"OpenCV_VERSION (\d)\.(\d)\.(\d{,2})", fline)
if match is not None:
opencv_version = match.group(1) + "." + match.group(2)
finally:
fp.close()
return opencv_version
def cli():
while True:
root_ = input(r"Where is your opencv root path? (e.g, C:\path\to\opencv3): ")
if os.path.exists(root_):
kConfig["build"] = os.path.join(root_, "build")
kConfig["include"] = os.path.join(kConfig["build"], "include")
break
else:
print("Invalid path")
if check_opencv_version() != "3.1":
print("requires opencv 3.1")
exit()
kConfig["bit"] = "x64"
while True:
vc = input("Which Visual Studio you are using? (vs2013 or vs2015): ")
if vc == "vs2013":
kConfig["vs"] = "vc12"
break
elif vc == "vs2015":
kConfig["vs"] = "vc14"
break
else:
print("Please type vs2013 or vs2015")
kConfig["library"] = os.path.normpath("%s/%s/%s/lib/" % (kConfig["build"], kConfig["bit"], kConfig["vs"]))
if __name__ == "__main__":
cli()
configure()

@ -1,58 +1,83 @@
#ifndef EASYPR_CORE_CHARSIDENTIFY_H_
#define EASYPR_CORE_CHARSIDENTIFY_H_
#include <memory>
#include "opencv2/opencv.hpp"
#include "easypr/util/kv.h"
#include "easypr/core/character.hpp"
#include "easypr/core/feature.h"
//////////////////////////////////////////////////////////////////////////
// Name: chars_recognise Header
// Version: 1.0
// Date: 2014-09-28
// Author: liuruoze
// Copyright: liuruoze
// Reference: Mastering OpenCV with Practical Computer Vision Projects
// Reference: CSDN Bloger taotao1233
// Desciption:
// Defines CCharsRecognise
//////////////////////////////////////////////////////////////////////////
#ifndef EASYPR_CORE_CHARSRECOGNISE_H_
#define EASYPR_CORE_CHARSRECOGNISE_H_
#include "easypr/core/chars_segment.h"
#include "easypr/core/chars_identify.h"
#include "easypr/core/core_func.h"
#include "easypr/util/util.h"
#include "easypr/core/plate.hpp"
#include "easypr/config.h"
namespace easypr {
class CharsIdentify {
public:
static CharsIdentify* instance();
int classify(cv::Mat f, float& maxVal, bool isChinses = false, bool isAlphabet = false);
void classify(cv::Mat featureRows, std::vector<int>& out_maxIndexs,
std::vector<float>& out_maxVals, std::vector<bool> isChineseVec);
void classify(std::vector<CCharacter>& charVec);
void classifyChinese(std::vector<CCharacter>& charVec);
void classifyChineseGray(std::vector<CCharacter>& charVec);
std::pair<std::string, std::string> identify(cv::Mat input, bool isChinese = false, bool isAlphabet = false);
int identify(std::vector<cv::Mat> inputs, std::vector<std::pair<std::string, std::string>>& outputs,
std::vector<bool> isChineseVec);
std::pair<std::string, std::string> identifyChinese(cv::Mat input, float& result, bool& isChinese);
std::pair<std::string, std::string> identifyChineseGray(cv::Mat input, float& result, bool& isChinese);
bool isCharacter(cv::Mat input, std::string& label, float& maxVal, bool isChinese = false);
void LoadModel(std::string path);
void LoadChineseModel(std::string path);
void LoadGrayChANN(std::string path);
void LoadChineseMapping(std::string path);
private:
CharsIdentify();
annCallback extractFeature;
static CharsIdentify* instance_;
// binary character classifer
cv::Ptr<cv::ml::ANN_MLP> ann_;
// binary character classifer, only for chinese
cv::Ptr<cv::ml::ANN_MLP> annChinese_;
// gray classifer, only for chinese
cv::Ptr<cv::ml::ANN_MLP> annGray_;
// used for chinese mapping
std::shared_ptr<Kv> kv_;
class CCharsRecognise {
public:
CCharsRecognise();
~CCharsRecognise();
int charsRecognise(cv::Mat plate, std::string& plateLicense);
int charsRecognise(CPlate& plate, std::string& plateLicense);
inline std::string getPlateColor(cv::Mat input) const {
std::string color = "未知";
Color result = getPlateType(input, true);
if (BLUE == result) color = "蓝牌";
if (YELLOW == result) color = "黄牌";
if (WHITE == result) color = "白牌";
#ifdef OS_WINDOWS
color = utils::utf8_to_gbk(color.c_str());
#endif
return color;
}
inline std::string getPlateColor(Color in) const {
std::string color = "未知";
if (BLUE == in) color = "蓝牌";
if (YELLOW == in) color = "黄牌";
if (WHITE == in) color = "白牌";
#ifdef OS_WINDOWS
color = utils::utf8_to_gbk(color.c_str());
#endif
return color;
}
inline void setLiuDingSize(int param) {
m_charsSegment->setLiuDingSize(param);
}
inline void setColorThreshold(int param) {
m_charsSegment->setColorThreshold(param);
}
inline void setBluePercent(float param) {
m_charsSegment->setBluePercent(param);
}
inline float getBluePercent() const {
return m_charsSegment->getBluePercent();
}
inline void setWhitePercent(float param) {
m_charsSegment->setWhitePercent(param);
}
inline float getWhitePercent() const {
return m_charsSegment->getWhitePercent();
}
private:
//!字符分割
CCharsSegment* m_charsSegment;
};
}
#endif // EASYPR_CORE_CHARSIDENTIFY_H_
} /* \namespace easypr */
#endif // EASYPR_CORE_CHARSRECOGNISE_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,31 @@
zh_cuan 川
zh_gan1 甘
zh_hei 黑
zh_jin 津
zh_liao 辽
zh_min 闽
zh_qiong 琼
zh_sx 晋
zh_xin 新
zh_yue 粤
zh_zhe 浙
zh_e 鄂
zh_gui 贵
zh_hu 沪
zh_jing 京
zh_lu 鲁
zh_ning 宁
zh_shan 陕
zh_wan 皖
zh_yu 豫
zh_yun 云
zh_gan 赣
zh_gui1 桂
zh_ji 冀
zh_jl 吉
zh_meng 蒙
zh_qing 青
zh_su 苏
zh_xiang 湘
zh_yu1 渝
zh_zang 藏

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -0,0 +1,7 @@
EasyPR使用的是Apache V2开源协议是一个对商用友好的协议。
你可以使用EasyPR进行后续开发并用做商业目的。
如果你的产品中引用了EasyPR的代码请明确说明代码修改自EasyPR谢谢
EasyPR中image目录下的general_test和extreme_test文件夹下的所有数据属于GDTS(General Data Test Set通用数据测试集)中的一部分,
那个数据集里的所有数据都不遵循Apache V2协议Apache V2所针对的仅仅是EasyPR中的代码与相关模型。
GDTS里任何的数据都遵循GDSL(General Data Share License)请阅读image/GPSL.txt获取更多信息。

@ -0,0 +1,94 @@
General Data Share License
通用数据共享协议
Version 0.1, 2015-01-25
当您开始使用EasyPR中的GDTS(General Data Test Set通用数据测试集)也就是image/general_test文件夹里的任一数据时您必须遵守以下协议的条款。
EasyPR只允许对GDTS里的数据进行非商业性目的的使用任何商业行为(售卖或者随产品附赠等)都属于违反本协议约定的行为。
EasyPR保留任何权利。
本协议的起草参考了以下两个协议GPL v2.0与ODL(Open Database License)。其核心思想与这两个协议基本相同,但也有许多相异的地方。
本协议与GPL协议相同的地方在于本协议与GPL协议都是“传染性”协议。
当您使用拷贝转移了GDTS中数据(或其中一部分时),您务必要保证这个协议随数据同行。
同时假若您把GDTS中数据(或其中一部分时)进行修改或与其他数据进行合并时那您需要确保新的数据集也必须遵循此GDSL协议的约定条款。
与GPL协议不同的地方在于GPL协议保护的是代码(code)以及基于代码的工作(work),而本协议保护的是数据(data)。
注意,本协议中所保护的数据仅保护这些原始的图片数据,并不针对于您通过这些图片数据训练出的模型,
以及您通过这些图片数据截取出的仅包含车牌的图片,您可以将这些训练模型或车牌图片按照非本协议约定的条款进行操作。
本协议与ODL协议相同的地方在于本协议与ODL协议都是保护数据(data)的协议,并且也提倡数据的开放,共享。
但ODL协议针对的主要是结构化数据而本协议针对的主要是图片数据。
另外ODL协议强调的开放不限制对数据的商业性使用。但本协议规定了数据仅仅只能用于进行非商业性的目的行为
包括学习与研究,但不包括商业性行为,例如销售与随产品赠送等等。
目前本协议的版本为0.1修正稿,任何对本协议的修改与建议都可以跟本协议的组织方联系(easypr_dev@163.com) 。
本协议主要分为三个部分:
1.版权声明:约定了对GDTS数据使用的规范。
2.捐赠说明:说明了如何对GDTS数据进行捐赠的方法。
3.免责声明:声明免责条款。
如果您仅仅是使用EasyPR进行开发与研究那您仅需要读完第一部分。如果您愿意对EasyPR进行捐赠那您需要读完第二部分。
第三部分声明了EasyPR在各个部分的免责条款。
一.版权声明
EasyPR中GDTS(通用数据测试集)的数据仅用作学习与研究之用。尽管EasyPR遵循的是商业友好的开源协议Acache2.0,但那个协议仅适用于您对代码的修改权。
这些测试数据集并不在您可以修改并且出卖的范围之内请确保这些数据集仅仅作为您进行EasyPR图像测试效率的验证与参考。
这些图片是用来测试EasyPR的效果与指标的仅仅用于开源学习目的。任何商业化的使用这些数据例如出卖数据或者将这些数据作为产品的附赠都是不允许的。
为了保证EasyPR中使用的测试数据不有任何侵犯权利的可能性每个在GDTS(通用数据测试集)上上传的数据都具有以下几个特征:
1.年代久远,不具有时效性的数据(例如,至少半年以前的数据)或者已经处理过相关版权事宜的数据。
2.在上传前使用EasyPR提供的函数对图片进行模糊化裁剪性处理确保图片不透露任何可能关于地点时间位置等相关信息。
3.在上传前使用EasyPR提供的反人脸识别工具进行处理确保图片不侵犯到任何人的隐私权和肖像权。
如果您发现EasyPR中存在任何侵犯您可能权利的图片时请跟我们联系(easypr_dev@163.com) 。我们的工作人员会跟您协商,将这些图片修改或做删除处理。
二.捐赠说明
EasyPR里的数据来源广泛部分来自于网络公开途径也有好心的网友以及匿名人士对EasyPR的捐赠。通过这些数据
有效地改善了EasyPR的识别效果与准确率为推广车牌识别技术在中国的开源发展做出了贡献。如果您愿意您也可以向EasyPR捐赠。
在一般的开源与众包软件中捐赠的方式一般是金钱等物质性财产。但EasyPR的捐赠略有不同我们不接受财物的捐赠相反我们接受的是数据的捐赠。
如果您有车牌的图片符合以下三个条件并且您愿意捐赠给EasyPR作为研究与开发的帮助那么您可以跟我们联系(easypr_dev@163.com)
一般选择捐赠的图片在5-30张之间最好每张图片有足够不同的特点我们非常高兴能够接受您对我们开发与研究的支持。
捐赠方式可以选择公开或匿名并且您可以选择捐赠后的数据是纳入GDTS作为通用测试集或者保持私密性仅仅作为EasyPR核心团队训练与测试的图片。
捐赠的图片数据不需要太多我们建议您不要捐赠超过30张以上的图片。感谢您为中国开源软件的发展与数据开源运动所做出的贡献
为了保证EasyPR中使用的测试数据不有任何侵犯权利的可能性每个在GDTS(通用数据测试集)上上传的数据都具有以下几个特征:
1.年代久远,不具有时效性的数据(例如,至少半年以前的数据)或者已经处理过相关版权事宜的数据
2.在上传前使用EasyPR提供的函数对图片进行模糊化裁剪性处理确保图片不透露任何可能关于地点时间位置等相关信息
3.在上传前使用EasyPR提供的反人脸识别工具进行处理确保图片不侵犯到任何人的隐私权和肖像权
只有经过以上处理满足以上三个条件的数据EasyPR才会纳入到GDTS里作为车牌识别的准确率衡判依据。
任何不满足以上三个条件的数据EasyPR都会保持这些数据的隐秘不公开等特性并且确保这些数据处于保密状态。
EasyPR团队保证这些研究仅仅作为开源社区学习机器学习、深度学习、图像识别以及计算机视觉的相关资料与参考不会用作任何商用或者恶意行为。
三.免责声明
EasyPR中GDTS(通用数据测试集)的使用仅仅是为了研究与学习目的。
任何使用这些数据进行商用或者恶意窥探目的的行为都违反EasyPR所遵循的开源法则以及研究目的。EasyPR不对这些恶意后果负有任何责任。
EasyPR谴责这些行为但EasyPR不为这些违反开源原则行为的后果负有责任。
当恶意使用者以及用数据牟利者违反了EasyPR约定的这些条款时也就意味着EasyPR不会对他们所造成的任何行为负有责任。
当您使用这些数据时就意味着您已经同意EasyPR的这些约定您对EasyPR通用测试数据集的滥用以及恶意窥探目行为的后果需要您自己承担
EasyPR及其开源团队与贡献者不承担任何相关的责任。
EasyPR团队保留所有权利。
联系方式
EasyPR开发团队的官方邮箱
(easypr_dev@163.com)
###当您复制了EasyPR声明权利的这些数据(或者其中一部分)的同时,您也必须将这份协议复制一份,并保持协议随数据时刻同行。

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save