Revert "Merge pull request #1 from Micooz/master"

This reverts commit ae88928c18, reversing
changes made to bdaae0b59b.
1.3
Fenix 10 years ago
parent ae88928c18
commit 8072d12a49

1
.gitignore vendored

@ -78,7 +78,6 @@ ipch/
*.psess
*.vsp
*.vspx
*.suo
# TFS 2012 Local Workspace
$tf/

@ -1,35 +0,0 @@
cmake_minimum_required(VERSION 2.6)
project (EasyPR)
list(APPEND CMAKE_CXX_FLAGS "-std=c++0x")
find_package(OpenCV REQUIRED)
aux_source_directory(./src SOURCE_FILES)
set(SOURCE_FILES
src/main.cpp
src/core/chars_identify.cpp
src/core/chars_recognise.cpp
src/core/chars_segment.cpp
src/core/features.cpp
src/core/plate_detect.cpp
src/core/plate_judge.cpp
src/core/plate_locate.cpp
src/core/plate_recognize.cpp
src/test/accuracy_test.cpp
src/test/test.cpp
src/train/ann_train.cpp
src/train/svm_train.cpp
src/util/deface.cpp
src/util/general_test_prepare.cpp
src/util/generate_gdts.cpp
src/util/learn_prepare.cpp
src/util/mc_data_prepare.cpp
src/util/util.cpp
)
add_executable(EasyPR ${SOURCE_FILES})
target_link_libraries(EasyPR ${OpenCV_LIBS})

@ -1,128 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{62ADD040-59C5-4D8E-A065-8C5D0CD777BE}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>EasyPR</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="opencv248.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="opencv248.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>D:\libs\opencv\build\x86\vc12\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opencv_calib3d249d.lib;opencv_contrib249d.lib;opencv_core249d.lib;opencv_features2d249d.lib;opencv_flann249d.lib;opencv_gpu249d.lib;opencv_highgui249d.lib;opencv_imgproc249d.lib;opencv_legacy249d.lib;opencv_ml249d.lib;opencv_nonfree249d.lib;opencv_objdetect249d.lib;opencv_ocl249d.lib;opencv_photo249d.lib;opencv_stitching249d.lib;opencv_superres249d.lib;opencv_ts249d.lib;opencv_video249d.lib;opencv_videostab249d.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="image\使用说明.txt" />
<None Include="image\免责声明.txt" />
<None Include="image\图片捐赠.txt" />
<None Include="image\版权声明.txt" />
<None Include="model\ann.xml" />
<None Include="model\svm.xml" />
<None Include="关于版权.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\core\chars_identify.cpp" />
<ClCompile Include="src\core\chars_recognise.cpp" />
<ClCompile Include="src\core\chars_segment.cpp" />
<ClCompile Include="src\core\features.cpp" />
<ClCompile Include="src\test\accuracy_test.cpp" />
<ClCompile Include="src\train\ann_train.cpp" />
<ClCompile Include="src\train\svm_train.cpp" />
<ClCompile Include="src\util\deface.cpp" />
<ClCompile Include="src\util\general_test_prepare.cpp" />
<ClCompile Include="src\util\generate_gdts.cpp" />
<ClCompile Include="src\util\mc_data_prepare.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\test\test.cpp" />
<ClCompile Include="src\core\plate_detect.cpp" />
<ClCompile Include="src\core\plate_judge.cpp" />
<ClCompile Include="src\core\plate_locate.cpp" />
<ClCompile Include="src\core\plate_recognize.cpp" />
<ClCompile Include="src\util\learn_prepare.cpp" />
<ClCompile Include="src\util\util.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\include\chars_identify.h" />
<ClInclude Include="src\include\chars_recognise.h" />
<ClInclude Include="src\include\chars_segment.h" />
<ClInclude Include="src\include\features.h" />
<ClInclude Include="src\include\plate_detect.h" />
<ClInclude Include="src\include\plate_judge.h" />
<ClInclude Include="src\include\plate_locate.h" />
<ClInclude Include="src\include\plate_recognize.h" />
<ClInclude Include="src\include\prep.h" />
<ClInclude Include="src\include\util.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -1,123 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="model\ann.xml">
<Filter>资源文件</Filter>
</None>
<None Include="model\svm.xml">
<Filter>资源文件</Filter>
</None>
<None Include="关于版权.txt">
<Filter>资源文件</Filter>
</None>
<None Include="image\图片捐赠.txt" />
<None Include="image\免责声明.txt" />
<None Include="image\使用说明.txt" />
<None Include="image\版权声明.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\util\util.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\util\mc_data_prepare.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\util\learn_prepare.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\core\chars_identify.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\core\chars_recognise.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\core\chars_segment.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\core\plate_detect.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\core\plate_judge.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\core\plate_locate.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\core\plate_recognize.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\core\features.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\test\test.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\test\accuracy_test.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\util\deface.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\main.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\train\ann_train.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\train\svm_train.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\util\generate_gdts.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="src\util\general_test_prepare.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\include\chars_identify.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\include\chars_recognise.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\include\chars_segment.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\include\plate_detect.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\include\plate_judge.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\include\plate_locate.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\include\plate_recognize.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\include\prep.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\include\util.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="src\include\features.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
</Project>

@ -49,32 +49,6 @@ EasyPR是基于opencv2.4.8版本开发的2.4.8以上的版本应该可以兼
“蓝牌苏EUK722”
### 编译(Linux)
#### 依赖
* gcc 4.8 或以上
* cmake 2.6 或以上
* opencv 2.4.8 或以上
##### 编译opencv
此过程需要较长时间,请耐心等待。
```
$ cd opencv/
$ cmake .
$ make
$ make install
```
##### 编译EasyPR
```
$ cd EasyPR/
$ cmake .
$ make
```
### 安装

@ -9,20 +9,20 @@ namespace easypr{
#define VERTICAL 0
#define NDEBUG
//中国车牌
//中国车牌
const char strCharacters[] = {'0','1','2','3','4','5',\
'6','7','8','9','A','B', 'C', 'D', 'E','F', 'G', 'H', /* 没有I */\
'J', 'K', 'L', 'M', 'N', /* 没有O */ 'P', 'Q', 'R', 'S', 'T', \
'6','7','8','9','A','B', 'C', 'D', 'E','F', 'G', 'H', /* 没有I */\
'J', 'K', 'L', 'M', 'N', /* 没有O */ 'P', 'Q', 'R', 'S', 'T', \
'U','V', 'W', 'X', 'Y', 'Z'};
const int numCharacter = 34; /* 没有I和0,10个数字与24个英文字符之和 */
const int numCharacter = 34; /* 没有I和0,10个数字与24个英文字符之和 */
//以下都是我训练时用到的中文字符数据,并不全面,有些省份没有训练数据所以没有字符
const string strChinese[] = {"zh_cuan" /* 川 */, "zh_e" /* 鄂 */, "zh_gan" /* 赣*/, \
"zh_hei" /* 黑 */, "zh_hu" /* 沪 */, "zh_ji" /* 冀 */, \
"zh_jl" /* 吉 */, "zh_jin" /* 津 */, "zh_jing" /* 京 */, "zh_shan" /* 陕 */, \
"zh_liao" /* 辽 */, "zh_lu" /* 鲁 */, "zh_min" /* 闽 */, "zh_ning" /* 宁 */, \
"zh_su" /* 苏 */, "zh_sx" /* 晋 */, "zh_wan" /* 皖 */,\
"zh_yu" /* 豫 */, "zh_yue" /* 粤 */, "zh_zhe" /* 浙 */};
//以下都是我训练时用到的中文字符数据,并不全面,有些省份没有训练数据所以没有字符
const string strChinese[] = {"zh_cuan" /* 川 */, "zh_e" /* 鄂 */, "zh_gan" /* 赣*/, \
"zh_hei" /* 黑 */, "zh_hu" /* 沪 */, "zh_ji" /* 冀 */, \
"zh_jl" /* 吉 */, "zh_jin" /* 津 */, "zh_jing" /* 京 */, "zh_shan" /* 陕 */, \
"zh_liao" /* 辽 */, "zh_lu" /* 鲁 */, "zh_min" /* 闽 */, "zh_ning" /* 宁 */, \
"zh_su" /* 苏 */, "zh_sx" /* 晋 */, "zh_wan" /* 皖 */,\
"zh_yu" /* 豫 */, "zh_yue" /* 粤 */, "zh_zhe" /* 浙 */};
const int numChinese = 20;
const int numAll = 54; /* 34+20=54 */
@ -36,26 +36,26 @@ CCharsIdentify::CCharsIdentify()
if (m_map.empty())
{
m_map.insert(pair<string, string>("zh_cuan",""));
m_map.insert(pair<string, string>("zh_e",""));
m_map.insert(pair<string, string>("zh_gan",""));
m_map.insert(pair<string, string>("zh_hei",""));
m_map.insert(pair<string, string>("zh_hu",""));
m_map.insert(pair<string, string>("zh_ji",""));
m_map.insert(pair<string, string>("zh_jl",""));
m_map.insert(pair<string, string>("zh_jin",""));
m_map.insert(pair<string, string>("zh_jing",""));
m_map.insert(pair<string, string>("zh_shan",""));
m_map.insert(pair<string, string>("zh_liao",""));
m_map.insert(pair<string, string>("zh_lu",""));
m_map.insert(pair<string, string>("zh_min",""));
m_map.insert(pair<string, string>("zh_ning",""));
m_map.insert(pair<string, string>("zh_su",""));
m_map.insert(pair<string, string>("zh_sx",""));
m_map.insert(pair<string, string>("zh_wan",""));
m_map.insert(pair<string, string>("zh_yu",""));
m_map.insert(pair<string, string>("zh_yue",""));
m_map.insert(pair<string, string>("zh_zhe",""));
m_map.insert(pair<string, string>("zh_cuan",""));
m_map.insert(pair<string, string>("zh_e",""));
m_map.insert(pair<string, string>("zh_gan",""));
m_map.insert(pair<string, string>("zh_hei",""));
m_map.insert(pair<string, string>("zh_hu",""));
m_map.insert(pair<string, string>("zh_ji",""));
m_map.insert(pair<string, string>("zh_jl",""));
m_map.insert(pair<string, string>("zh_jin",""));
m_map.insert(pair<string, string>("zh_jing",""));
m_map.insert(pair<string, string>("zh_shan",""));
m_map.insert(pair<string, string>("zh_liao",""));
m_map.insert(pair<string, string>("zh_lu",""));
m_map.insert(pair<string, string>("zh_min",""));
m_map.insert(pair<string, string>("zh_ning",""));
m_map.insert(pair<string, string>("zh_su",""));
m_map.insert(pair<string, string>("zh_sx",""));
m_map.insert(pair<string, string>("zh_wan",""));
m_map.insert(pair<string, string>("zh_yu",""));
m_map.insert(pair<string, string>("zh_yue",""));
m_map.insert(pair<string, string>("zh_zhe",""));
}
}
@ -72,7 +72,7 @@ void CCharsIdentify::LoadModel(string s)
ann.load(s.c_str(), "ann");
}
//create the accumulation histograms,img is a binary image, t is 水平或垂直
//create the accumulation histograms,img is a binary image, t is 水平或垂直
Mat CCharsIdentify::ProjectedHistogram(Mat img, int t)
{
int sz=(t)?img.rows:img.cols;
@ -80,7 +80,7 @@ Mat CCharsIdentify::ProjectedHistogram(Mat img, int t)
for(int j=0; j<sz; j++){
Mat data=(t)?img.row(j):img.col(j);
mhist.at<float>(j)=countNonZero(data); //统计这一行或一列中非零元素的个数并保存到mhist中
mhist.at<float>(j)=countNonZero(data); //统计这一行或一列中非零元素的个数并保存到mhist中
}
//Normalize histogram
@ -88,12 +88,12 @@ Mat CCharsIdentify::ProjectedHistogram(Mat img, int t)
minMaxLoc(mhist, &min, &max);
if(max>0)
mhist.convertTo(mhist,-1 , 1.0f/max, 0);//用mhist直方图中的最大值归一化直方图
mhist.convertTo(mhist,-1 , 1.0f/max, 0);//用mhist直方图中的最大值归一化直方图
return mhist;
}
//! 获得字符的特征图
//! 获得字符的特征图
Mat CCharsIdentify::features(Mat in, int sizeData)
{
//Histogram features
@ -109,7 +109,7 @@ Mat CCharsIdentify::features(Mat in, int sizeData)
Mat out = Mat::zeros(1, numCols, CV_32F);
//Asign values to feature,ANN的样本特征为水平、垂直直方图和低分辨率图像所组成的矢量
//Asign values to feature,ANN的样本特征为水平、垂直直方图和低分辨率图像所组成的矢量
int j=0;
for(int i=0; i<vhist.cols; i++)
{
@ -133,7 +133,7 @@ Mat CCharsIdentify::features(Mat in, int sizeData)
}
//! 利用神经网络做识别
//! 利用神经网络做识别
int CCharsIdentify::classify(Mat f, bool isChinses){
int result = -1;
Mat output(1, numAll, CV_32FC1);
@ -173,7 +173,7 @@ int CCharsIdentify::classify(Mat f, bool isChinses){
}
//输入当个字符Mat,生成字符的string
//输入当个字符Mat,生成字符的string
string CCharsIdentify::charsIdentify(Mat input, bool isChinese)
{
Mat f = features(input, m_predictSize);

@ -19,7 +19,7 @@ void CCharsRecognise::LoadANN(string s)
int CCharsRecognise::charsRecognise(Mat plate, string& plateLicense)
{
//车牌字符方块集合
//车牌字符方块集合
vector<Mat> matVec;
string plateIdentify = "";
@ -33,7 +33,7 @@ int CCharsRecognise::charsRecognise(Mat plate, string& plateLicense)
Mat charMat = matVec[j];
bool isChinses = false;
//默认首个字符块是中文字符
//默认首个字符块是中文字符
if (j == 0)
isChinses = true;

@ -14,7 +14,7 @@ CCharsSegment::CCharsSegment()
m_LiuDingSize = DEFAULT_LIUDING_SIZE;
m_theMatWidth = DEFAULT_MAT_WIDTH;
//!车牌颜色判断参数
//!车牌颜色判断参数
m_ColorThreshold = DEFAULT_COLORTHRESHOLD;
m_BluePercent = DEFAULT_BLUEPERCEMT;
m_WhitePercent = DEFAULT_WHITEPERCEMT;
@ -22,7 +22,7 @@ CCharsSegment::CCharsSegment()
m_debug = DEFAULT_DEBUG;
}
//! 字符尺寸验证
//! 字符尺寸验证
bool CCharsSegment::verifySizes(Mat r){
//Char sizes 45x90
float aspect=45.0f/90.0f;
@ -46,12 +46,12 @@ bool CCharsSegment::verifySizes(Mat r){
return false;
}
//! 字符预处理
//! 字符预处理
Mat CCharsSegment::preprocessChar(Mat in){
//Remap image
int h=in.rows;
int w=in.cols;
int charSize=CHAR_SIZE; //统一每个字符的大小
int charSize=CHAR_SIZE; //统一每个字符的大小
Mat transformMat=Mat::eye(2,3,CV_32F);
int m=max(w,h);
transformMat.at<float>(0,2)=m/2 - w/2;
@ -66,7 +66,7 @@ Mat CCharsSegment::preprocessChar(Mat in){
return out;
}
//! 直方图均衡,为判断车牌颜色做准备
//! 直方图均衡,为判断车牌颜色做准备
Mat CCharsSegment::histeq(Mat in)
{
Mat out(in.size(), in.type());
@ -88,8 +88,8 @@ Mat CCharsSegment::histeq(Mat in)
}
//getPlateType
//判断车牌的类型1为蓝牌2为黄牌0为未知默认蓝牌
//通过像素中蓝色所占比例的多少来判断大于0.3为蓝牌,否则为黄牌
//判断车牌的类型1为蓝牌2为黄牌0为未知默认蓝牌
//通过像素中蓝色所占比例的多少来判断大于0.3为蓝牌,否则为黄牌
int CCharsSegment::getPlateType(Mat input)
{
Mat img;
@ -129,9 +129,9 @@ int CCharsSegment::getPlateType(Mat input)
}
//clearLiuDing
//去除车牌上方的钮钉
//计算每行元素的阶跃数如果小于X认为是柳丁将此行全部填0涂黑
//X的推荐值为可根据实际调整
//去除车牌上方的钮钉
//计算每行元素的阶跃数如果小于X认为是柳丁将此行全部填0涂黑
//X的推荐值为可根据实际调整
Mat CCharsSegment::clearLiuDing(Mat img)
{
const int x = m_LiuDingSize;
@ -159,13 +159,13 @@ Mat CCharsSegment::clearLiuDing(Mat img)
return img;
}
//! 字符分割与排序
//! 字符分割与排序
int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
{
if( !input.data )
{ return -3; }
//判断车牌颜色以此确认threshold方法
//判断车牌颜色以此确认threshold方法
int plateType = getPlateType(input);
cvtColor(input, input, CV_RGB2GRAY);
@ -183,7 +183,7 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
imwrite(ss.str(), img_threshold);
}
//去除车牌上方的柳钉以及下方的横线等干扰
//去除车牌上方的柳钉以及下方的横线等干扰
clearLiuDing(img_threshold);
@ -209,7 +209,7 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
vector<Rect> vecRect;
//Remove patch that are no inside limits of aspect ratio and area.
//将不符合特定尺寸的图块排除出去
//将不符合特定尺寸的图块排除出去
while (itc != contours.end())
{
Rect mr = boundingRect(Mat(*itc));
@ -225,11 +225,11 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
return -3;
vector<Rect> sortedRect;
//对符合尺寸的图块按照从左到右进行排序
//对符合尺寸的图块按照从左到右进行排序
SortRect(vecRect, sortedRect);
int specIndex = 0;
//获得指示城市的特定Rect,如苏A的"A"
//获得指示城市的特定Rect,如苏A的"A"
specIndex = GetSpecificRect(sortedRect);
if(m_debug)
@ -243,9 +243,9 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
}
}
//根据特定Rect向左反推出中文字符
//这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect因此仅能
//退过特定算法来指定
//根据特定Rect向左反推出中文字符
//这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect因此仅能
//退过特定算法来指定
Rect chineseRect;
if (specIndex < sortedRect.size())
chineseRect = GetChineseRect(sortedRect[specIndex]);
@ -261,9 +261,9 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
}
//新建一个全新的排序Rect
//将中文字符Rect第一个加进来因为它肯定是最左边的
//其余的Rect只按照顺序去6个车牌只可能是7个字符这样可以避免阴影导致的“1”字符
//新建一个全新的排序Rect
//将中文字符Rect第一个加进来因为它肯定是最左边的
//其余的Rect只按照顺序去6个车牌只可能是7个字符这样可以避免阴影导致的“1”字符
vector<Rect> newSortedRect;
newSortedRect.push_back(chineseRect);
RebuildRect(sortedRect, newSortedRect, specIndex);
@ -292,7 +292,7 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
return 0;
}
//! 将Rect按位置从左到右进行排序
//! 将Rect按位置从左到右进行排序
int CCharsSegment::SortRect(const vector<Rect>& vecRect, vector<Rect>& out)
{
vector<int> orderIndex;
@ -336,7 +336,7 @@ int CCharsSegment::SortRect(const vector<Rect>& vecRect, vector<Rect>& out)
return 0;
}
//! 根据特殊车牌来构造猜测中文字符的位置和大小
//! 根据特殊车牌来构造猜测中文字符的位置和大小
Rect CCharsSegment::GetChineseRect(const Rect rectSpe)
{
int height = rectSpe.height;
@ -352,7 +352,7 @@ Rect CCharsSegment::GetChineseRect(const Rect rectSpe)
return a;
}
//! 找出指示城市的字符的Rect例如苏A7003X就是"A"的位置
//! 找出指示城市的字符的Rect例如苏A7003X就是"A"的位置
int CCharsSegment::GetSpecificRect(const vector<Rect>& vecRect)
{
vector<int> xpositions;
@ -379,7 +379,7 @@ int CCharsSegment::GetSpecificRect(const vector<Rect>& vecRect)
Rect mr = vecRect[i];
int midx = mr.x + mr.width/2;
//如果一个字符有一定的大小并且在整个车牌的1/7到2/7之间则是我们要找的特殊车牌
//如果一个字符有一定的大小并且在整个车牌的1/7到2/7之间则是我们要找的特殊车牌
if ((mr.width > maxWidth * 0.8 || mr.height > maxHeight * 0.8) &&
(midx < int(m_theMatWidth / 7) * 2 && midx > int(m_theMatWidth / 7) * 1))
{
@ -390,17 +390,17 @@ int CCharsSegment::GetSpecificRect(const vector<Rect>& vecRect)
return specIndex;
}
//! 这个函数做两个事情
// 1.把特殊字符Rect左边的全部Rect去掉后面再重建中文字符的位置。
// 2.从特殊字符Rect开始依次选择6个Rect多余的舍去。
//! 这个函数做两个事情
// 1.把特殊字符Rect左边的全部Rect去掉后面再重建中文字符的位置。
// 2.从特殊字符Rect开始依次选择6个Rect多余的舍去。
int CCharsSegment::RebuildRect(const vector<Rect>& vecRect, vector<Rect>& outRect, int specIndex)
{
//最大只能有7个Rect,减去中文的就只有6个Rect
//最大只能有7个Rect,减去中文的就只有6个Rect
int count = 6;
for (int i = 0; i < vecRect.size(); i++)
{
//将特殊字符左边的Rect去掉这个可能会去掉中文Rect不过没关系我们后面会重建。
//将特殊字符左边的Rect去掉这个可能会去掉中文Rect不过没关系我们后面会重建。
if (i < specIndex)
continue;

@ -1,6 +1,6 @@
// 这个文件定义了EasyPR里所有特征生成的函数
// 所属命名空间为easypr
// 这个部分中的特征由easypr的开发者修改
// 这个文件定义了EasyPR里所有特征生成的函数
// 所属命名空间为easypr
// 这个部分中的特征由easypr的开发者修改
#include "../include/prep.h"
#include "../include/features.h"
@ -10,7 +10,7 @@
*/
namespace easypr {
//! 直方图均衡
//! 直方图均衡
Mat histeq(Mat in)
{
Mat out(in.size(), in.type());
@ -31,7 +31,7 @@ Mat histeq(Mat in)
return out;
}
// !获取垂直和水平方向直方图
// !获取垂直和水平方向直方图
Mat ProjectedHistogram(Mat img, int t)
{
int sz=(t)?img.rows:img.cols;
@ -39,7 +39,7 @@ Mat ProjectedHistogram(Mat img, int t)
for(int j=0; j<sz; j++){
Mat data=(t)?img.row(j):img.col(j);
mhist.at<float>(j)=countNonZero(data); //统计这一行或一列中非零元素的个数并保存到mhist中
mhist.at<float>(j)=countNonZero(data); //统计这一行或一列中非零元素的个数并保存到mhist中
}
//Normalize histogram
@ -47,13 +47,13 @@ Mat ProjectedHistogram(Mat img, int t)
minMaxLoc(mhist, &min, &max);
if(max>0)
mhist.convertTo(mhist,-1 , 1.0f/max, 0);//用mhist直方图中的最大值归一化直方图
mhist.convertTo(mhist,-1 , 1.0f/max, 0);//用mhist直方图中的最大值归一化直方图
return mhist;
}
//! 获得车牌的特征数
//! 获得车牌的特征数
Mat getTheFeatures(Mat in)
{
const int VERTICAL = 0;
@ -68,7 +68,7 @@ Mat getTheFeatures(Mat in)
Mat out = Mat::zeros(1, numCols, CV_32F);
//Asign values to feature,样本特征为水平、垂直直方图
//Asign values to feature,样本特征为水平、垂直直方图
int j=0;
for(int i=0; i<vhist.cols; i++)
{
@ -84,15 +84,15 @@ Mat getTheFeatures(Mat in)
return out;
}
// ! EasyPR的getFeatures回调函数
// !本函数是生成直方图均衡特征的回调函数
// ! EasyPR的getFeatures回调函数
// !本函数是生成直方图均衡特征的回调函数
void getHisteqFeatures(const Mat& image, Mat& features)
{
features = histeq(image);
}
// ! EasyPR的getFeatures回调函数
// !本函数是获取垂直和水平的直方图图值
// ! EasyPR的getFeatures回调函数
// !本函数是获取垂直和水平的直方图图值
void getHistogramFeatures(const Mat& image, Mat& features)
{
Mat grayImage;
@ -104,20 +104,20 @@ void getHistogramFeatures(const Mat& image, Mat& features)
}
// ! EasyPR的getFeatures回调函数
// 本函数是获取SITF特征子
// ! EasyPR的getFeatures回调函数
// 本函数是获取SITF特征子
// !
void getSIFTFeatures(const Mat& image, Mat& features)
{
//待完善
//待完善
}
// ! EasyPR的getFeatures回调函数
// 本函数是获取HOG特征子
// ! EasyPR的getFeatures回调函数
// 本函数是获取HOG特征子
void getHOGFeatures(const Mat& image, Mat& features)
{
//待完善
//待完善
}
} /* \namespace easypr */

@ -19,7 +19,7 @@ void CPlateDetect::LoadSVM(string s)
int CPlateDetect::plateDetect(Mat src, vector<Mat>& resultVec)
{
//可能是车牌的图块集合
//可能是车牌的图块集合
vector<Mat> matVec;
int resultLo = m_plateLocate->plateLocate(src, matVec);

@ -27,7 +27,7 @@ void CPlateJudge::LoadModel(string s)
svm.load(s.c_str(), "svm");
}
//! 直方图均衡
//! 直方图均衡
Mat CPlateJudge::histeq(Mat in)
{
Mat out(in.size(), in.type());
@ -49,7 +49,7 @@ Mat CPlateJudge::histeq(Mat in)
}
//! 对单幅图像进行SVM判断
//! 对单幅图像进行SVM判断
int CPlateJudge::plateJudge(const Mat& inMat,int& result)
{
if (m_getFeatures == NULL)
@ -58,7 +58,7 @@ int CPlateJudge::plateJudge(const Mat& inMat,int& result)
Mat features;
m_getFeatures(inMat, features);
//通过直方图均衡化后的彩色图进行预测
//通过直方图均衡化后的彩色图进行预测
Mat p = features.reshape(1, 1);
p.convertTo(p, CV_32FC1);
@ -69,7 +69,7 @@ int CPlateJudge::plateJudge(const Mat& inMat,int& result)
}
//! 对多幅图像进行SVM判断
//! 对多幅图像进行SVM判断
int CPlateJudge::plateJudge(const vector<Mat>& inVec,
vector<Mat>& resultVec)
{

@ -25,8 +25,8 @@ CPlateLocate::CPlateLocate()
m_debug = DEFAULT_DEBUG;
}
//! 生活模式与工业模式切换
//! 如果为真,则设置各项参数为定位生活场景照片(如百度图片)的参数,否则恢复默认值。
//! 生活模式与工业模式切换
//! 如果为真,则设置各项参数为定位生活场景照片(如百度图片)的参数,否则恢复默认值。
void CPlateLocate::setLifemode(bool param)
{
if(param == true)
@ -52,12 +52,12 @@ void CPlateLocate::setLifemode(bool param)
}
//! 对minAreaRect获得的最小外接矩形用纵横比进行判断
//! 对minAreaRect获得的最小外接矩形用纵横比进行判断
bool CPlateLocate::verifySizes(RotatedRect mr)
{
float error = m_error;
//Spain car plate size: 52x11 aspect 4,7272
//China car plate size: 440mm*140mmaspect 3.142857
//China car plate size: 440mm*140mmaspect 3.142857
float aspect = m_aspect;
//Set a min and max area. All other patchs are discarded
//int min= 1*aspect*1; // minimum area
@ -85,7 +85,7 @@ bool CPlateLocate::verifySizes(RotatedRect mr)
}
}
//! 显示最终生成的车牌图像,便于判断是否成功进行了旋转。
//! 显示最终生成的车牌图像,便于判断是否成功进行了旋转。
Mat CPlateLocate::showResultMat(Mat src, Size rect_size, Point2f center, int index)
{
Mat img_crop;
@ -113,10 +113,10 @@ Mat CPlateLocate::showResultMat(Mat src, Size rect_size, Point2f center, int ind
return resultResized;
}
//! 定位车牌图像
//! src 原始图像
//! resultVec 一个Mat的向量存储所有抓取到的图像
//! 成功返回0否则返回-1
//! 定位车牌图像
//! src 原始图像
//! resultVec 一个Mat的向量存储所有抓取到的图像
//! 成功返回0否则返回-1
int CPlateLocate::plateLocate(Mat src, vector<Mat>& resultVec)
{
Mat src_blur, src_gray;
@ -129,7 +129,7 @@ int CPlateLocate::plateLocate(Mat src, vector<Mat>& resultVec)
if( !src.data )
{ return -1; }
//高斯模糊。Size中的数字影响车牌定位的效果。
//高斯模糊。Size中的数字影响车牌定位的效果。
GaussianBlur( src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize),
0, 0, BORDER_DEFAULT );
@ -199,11 +199,11 @@ int CPlateLocate::plateLocate(Mat src, vector<Mat>& resultVec)
imwrite(ss.str(), img_threshold);
}
//Find 轮廓 of possibles plates
//Find 轮廓 of possibles plates
vector< vector< Point> > contours;
findContours(img_threshold,
contours, // a vector of contours
CV_RETR_EXTERNAL, // 提取外部轮廓
CV_RETR_EXTERNAL, // 提取外部轮廓
CV_CHAIN_APPROX_NONE); // all pixels of each contours
Mat result;
@ -252,10 +252,10 @@ int CPlateLocate::plateLocate(Mat src, vector<Mat>& resultVec)
{
// rotated rectangle drawing
// Get rotation matrix
// 旋转这部分代码确实可以将某些倾斜的车牌调整正,
// 但是它也会误将更多正的车牌搞成倾斜!所以综合考虑,还是不使用这段代码。
// 2014-08-14,由于新到的一批图片中发现有很多车牌是倾斜的,因此决定再次尝试
// 这段代码。
// 旋转这部分代码确实可以将某些倾斜的车牌调整正,
// 但是它也会误将更多正的车牌搞成倾斜!所以综合考虑,还是不使用这段代码。
// 2014-08-14,由于新到的一批图片中发现有很多车牌是倾斜的,因此决定再次尝试
// 这段代码。
if(m_debug)
{
Point2f rect_points[4];
@ -272,7 +272,7 @@ int CPlateLocate::plateLocate(Mat src, vector<Mat>& resultVec)
angle = 90 + angle;
swap(rect_size.width, rect_size.height);
}
//如果抓取的方块旋转超过m_angle角度则不是车牌放弃处理
//如果抓取的方块旋转超过m_angle角度则不是车牌放弃处理
if (angle - m_angle < 0 && angle + m_angle > 0)
{
//Create and rotate image

@ -12,13 +12,13 @@ CPlateRecognize::CPlateRecognize()
//m_charsRecognise = new CCharsRecognise();
}
////! 装载SVM模型
////! 装载SVM模型
//void CPlateRecognize::LoadSVM(string strSVM)
//{
// m_plateDetect->LoadModel(strSVM.c_str());
//}
//
////! 装载ANN模型
////! 装载ANN模型
//void CPlateRecognize::LoadANN(string strANN)
//{
// m_charsRecognise->LoadModel(strANN.c_str());
@ -38,7 +38,7 @@ CPlateRecognize::CPlateRecognize()
int CPlateRecognize::plateRecognize(Mat src, vector<string>& licenseVec)
{
//车牌方块集合
//车牌方块集合
vector<Mat> plateVec;
int resultPD = plateDetect(src, plateVec);
@ -51,10 +51,10 @@ int CPlateRecognize::plateRecognize(Mat src, vector<string>& licenseVec)
{
Mat plate = plateVec[j];
//获取车牌颜色
//获取车牌颜色
string plateType = getPlateType(plate);
//获取车牌号
//获取车牌号
string plateIdentify = "";
int resultCR = charsRecognise(plate, plateIdentify);
if (resultCR == 0)

@ -24,39 +24,39 @@ class CCharsIdentify
public:
CCharsIdentify();
//! 字符分割
//! 字符分割
string charsIdentify(Mat, bool);
//! 字符分类
//! 字符分类
int classify(Mat, bool);
//create the accumulation histograms,img is a binary image, t is 水平或垂直
//create the accumulation histograms,img is a binary image, t is 水平或垂直
Mat ProjectedHistogram(Mat img, int t);
//! 获得字符的特征图
//! 获得字符的特征图
Mat features(Mat in, int sizeData);
//! 装载ANN模型
//! 装载ANN模型
void LoadModel();
//! 装载ANN模型
//! 装载ANN模型
void LoadModel(string s);
//! 设置与读取模型路径
//! 设置与读取模型路径
inline void setModelPath(string path){ m_path = path; }
inline string getModelPath() const{ return m_path; }
private:
//使用的ANN模型
//使用的ANN模型
CvANN_MLP ann;
//! 模型存储路径
//! 模型存储路径
string m_path;
//! 特征尺寸
//! 特征尺寸
int m_predictSize;
//! 省份对应map
//! 省份对应map
map<string, string> m_map;
};

@ -27,32 +27,32 @@ class CCharsRecognise
public:
CCharsRecognise();
//! 字符分割与识别
//! 字符分割与识别
int charsRecognise(Mat, String&);
//! 装载ANN模型
//! 装载ANN模型
void LoadANN(string s);
//! 是否开启调试模式
//! 是否开启调试模式
inline void setCRDebug(int param){ m_charsSegment->setDebug(param);}
//! 获取调试模式状态
//! 获取调试模式状态
inline int getCRDebug(){ return m_charsSegment->getDebug();}
//! 获得车牌颜色
//! 获得车牌颜色
inline string getPlateType(Mat input) const
{
string color = "未知";
string color = "未知";
int result = m_charsSegment->getPlateType(input);
if (1 == result)
color = "蓝牌";
color = "蓝牌";
if (2 == result)
color = "黄牌";
color = "黄牌";
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);}
@ -61,10 +61,10 @@ public:
inline float getWhitePercent() const { return m_charsSegment->getWhitePercent();}
private:
//!字符分割
//!字符分割
CCharsSegment* m_charsSegment;
//! 字符识别
//! 字符识别
CCharsIdentify* m_charsIdentify;
};

@ -24,45 +24,45 @@ class CCharsSegment
public:
CCharsSegment();
//! 字符分割
//! 字符分割
int charsSegment(Mat, vector<Mat>& );
//! 字符尺寸验证
//! 字符尺寸验证
bool verifySizes(Mat r);
//! 字符预处理
//! 字符预处理
Mat preprocessChar(Mat in);
//! 生成直方图
//! 生成直方图
Mat ProjectedHistogram(Mat img, int t);
//! 生成字符的特定特征
//! 生成字符的特定特征
Mat features(Mat in, int sizeData);
//! 直方图均衡,为判断车牌颜色做准备
//! 直方图均衡,为判断车牌颜色做准备
Mat histeq(Mat in);
//! 获得车牌颜色
//! 获得车牌颜色
int getPlateType(Mat input);
//! 去除影响字符识别的柳钉
//! 去除影响字符识别的柳钉
Mat clearLiuDing(Mat img);
//! 根据特殊车牌来构造猜测中文字符的位置和大小
//! 根据特殊车牌来构造猜测中文字符的位置和大小
Rect GetChineseRect(const Rect rectSpe);
//! 找出指示城市的字符的Rect例如苏A7003X就是A的位置
//! 找出指示城市的字符的Rect例如苏A7003X就是A的位置
int GetSpecificRect(const vector<Rect>& vecRect);
//! 这个函数做两个事情
// 1.把特殊字符Rect左边的全部Rect去掉后面再重建中文字符的位置。
// 2.从特殊字符Rect开始依次选择6个Rect多余的舍去。
//! 这个函数做两个事情
// 1.把特殊字符Rect左边的全部Rect去掉后面再重建中文字符的位置。
// 2.从特殊字符Rect开始依次选择6个Rect多余的舍去。
int RebuildRect(const vector<Rect>& vecRect, vector<Rect>& outRect, int specIndex);
//! 将Rect按位置从左到右进行排序
//! 将Rect按位置从左到右进行排序
int SortRect(const vector<Rect>& vecRect, vector<Rect>& out);
//! 设置变量
//! 设置变量
inline void setLiuDingSize(int param){ m_LiuDingSize = param;}
inline void setColorThreshold(int param){ m_ColorThreshold = param;}
@ -71,38 +71,38 @@ public:
inline void setWhitePercent(float param){ m_WhitePercent = param;}
inline float getWhitePercent() const { return m_WhitePercent;}
//! 是否开启调试模式常量默认0代表关闭
//! 是否开启调试模式常量默认0代表关闭
static const int DEFAULT_DEBUG = 0;
//! preprocessChar所用常量
//! preprocessChar所用常量
static const int CHAR_SIZE = 20;
static const int HORIZONTAL = 1;
static const int VERTICAL = 0;
//! preprocessChar所用常量
//! preprocessChar所用常量
static const int DEFAULT_LIUDING_SIZE = 7;
static const int DEFAULT_MAT_WIDTH = 136;
static const int DEFAULT_COLORTHRESHOLD = 150;
//! 是否开启调试模式
//! 是否开启调试模式
inline void setDebug(int param){ m_debug = param;}
//! 获取调试模式状态
//! 获取调试模式状态
inline int getDebug(){ return m_debug;}
private:
//!柳钉判断参数
//!柳钉判断参数
int m_LiuDingSize;
//!车牌大小参数
//!车牌大小参数
int m_theMatWidth;
//!车牌颜色判断参数
//!车牌颜色判断参数
int m_ColorThreshold;
float m_BluePercent;
float m_WhitePercent;
//! 是否开启调试模式0关闭非0开启
//! 是否开启调试模式0关闭非0开启
int m_debug;
};

@ -6,31 +6,31 @@
*/
namespace easypr {
//! 直方图均衡
//! 直方图均衡
Mat histeq(Mat in);
// !获取垂直和水平方向直方图
// !获取垂直和水平方向直方图
Mat ProjectedHistogram(Mat img, int t);
//! 获得车牌的特征数
//! 获得车牌的特征数
Mat getTheFeatures(Mat in);
// ! EasyPR的getFeatures回调函数
// 用于从车牌的image生成svm的训练特征features
// ! EasyPR的getFeatures回调函数
// 用于从车牌的image生成svm的训练特征features
typedef void(*svmCallback)(const Mat& image, Mat& features);
// ! EasyPR的getFeatures回调函数
// !本函数是生成直方图均衡特征的回调函数
// ! EasyPR的getFeatures回调函数
// !本函数是生成直方图均衡特征的回调函数
void getHisteqFeatures(const Mat& image, Mat& features);
// ! EasyPR的getFeatures回调函数
// !本函数是获取垂直和水平的直方图图值
// ! EasyPR的getFeatures回调函数
// !本函数是获取垂直和水平的直方图图值
void getHistogramFeatures(const Mat& image, Mat& features);
// 本函数是获取SIFT特征子
// 本函数是获取SIFT特征子
void getSIFTFeatures(const Mat& image, Mat& features);
// 本函数是获取HOG特征子
// 本函数是获取HOG特征子
void getHOGFeatures(const Mat& image, Mat& features);

@ -27,22 +27,22 @@ class CPlateDetect
public:
CPlateDetect();
//! 车牌检测:车牌定位与判断
//! 车牌检测:车牌定位与判断
int plateDetect(Mat, vector<Mat>&);
//! 装载SVM模型
//! 装载SVM模型
void LoadSVM(string s);
//! 生活模式与工业模式切换
//! 生活模式与工业模式切换
inline void setPDLifemode(bool param){m_plateLocate->setLifemode(param);}
//! 是否开启调试模式
//! 是否开启调试模式
inline void setPDDebug(int param){ m_plateLocate->setDebug(param);}
//! 获取调试模式状态
//! 获取调试模式状态
inline int getPDDebug(){ return m_plateLocate->getDebug();}
//! 设置与读取变量
//! 设置与读取变量
inline void setGaussianBlurSize(int param){ m_plateLocate->setGaussianBlurSize(param);}
inline int getGaussianBlurSize() const{ return m_plateLocate->getGaussianBlurSize();}
@ -63,10 +63,10 @@ public:
inline void setJudgeAngle(int param){m_plateLocate->setJudgeAngle(param);}
private:
//!车牌定位
//!车牌定位
CPlateLocate* m_plateLocate;
//! 车牌判断
//! 车牌判断
CPlateJudge* m_plateJudge;
};

@ -25,34 +25,34 @@ class CPlateJudge
public:
CPlateJudge();
//! 车牌判断
//! 车牌判断
int plateJudge(const vector<Mat>&, vector<Mat>&);
//! 车牌判断(一副图像)
//! 车牌判断(一副图像)
int plateJudge(const Mat& inMat, int& result);
//! 直方图均衡
//! 直方图均衡
Mat histeq(Mat);
//! 装载SVM模型
//! 装载SVM模型
void LoadModel();
//! 装载SVM模型
//! 装载SVM模型
void LoadModel(string s);
//! 设置与读取模型路径
//! 设置与读取模型路径
inline void setModelPath(string path){ m_path = path; }
inline string getModelPath() const{ return m_path; }
private:
//使用的SVM模型
//使用的SVM模型
CvSVM svm;
// ! EasyPR的getFeatures回调函数
// 用于从车牌的image生成svm的训练特征features
// ! EasyPR的getFeatures回调函数
// 用于从车牌的image生成svm的训练特征features
svmCallback m_getFeatures;
//! 模型存储路径
//! 模型存储路径
string m_path;
};

@ -25,19 +25,19 @@ class CPlateLocate
public:
CPlateLocate();
//! 车牌定位
//! 车牌定位
int plateLocate(Mat, vector<Mat>& );
//! 车牌的尺寸验证
//! 车牌的尺寸验证
bool verifySizes(RotatedRect mr);
//! 结果车牌显示
//! 结果车牌显示
Mat showResultMat(Mat src, Size rect_size, Point2f center, int index);
//! 生活模式与工业模式切换
//! 生活模式与工业模式切换
void setLifemode(bool param);
//! 设置与读取变量
//! 设置与读取变量
inline void setGaussianBlurSize(int param){ m_GaussianBlurSize = param;}
inline int getGaussianBlurSize() const{ return m_GaussianBlurSize;}
@ -57,13 +57,13 @@ public:
inline void setJudgeAngle(int param){ m_angle = param;}
//! 是否开启调试模式
//! 是否开启调试模式
inline void setDebug(int param){ m_debug = param;}
//! 获取调试模式状态
//! 获取调试模式状态
inline int getDebug(){ return m_debug;}
//! PlateLocate所用常量
//! PlateLocate所用常量
static const int DEFAULT_GAUSSIANBLUR_SIZE = 5;
static const int SOBEL_SCALE = 1;
static const int SOBEL_DELTA = 0;
@ -73,39 +73,39 @@ public:
static const int DEFAULT_MORPH_SIZE_WIDTH = 17;
static const int DEFAULT_MORPH_SIZE_HEIGHT = 3;
//! showResultMat所用常量
//! showResultMat所用常量
static const int WIDTH = 136;
static const int HEIGHT = 36;
static const int TYPE = CV_8UC3;
//! verifySize所用常量
//! verifySize所用常量
static const int DEFAULT_VERIFY_MIN = 3;
static const int DEFAULT_VERIFY_MAX = 20;
//! 角度判断所用常量
//! 角度判断所用常量
static const int DEFAULT_ANGLE = 30;
//! 是否开启调试模式常量默认0代表关闭
//! 是否开启调试模式常量默认0代表关闭
static const int DEFAULT_DEBUG = 0;
protected:
//! 高斯模糊所用变量
//! 高斯模糊所用变量
int m_GaussianBlurSize;
//! 连接操作所用变量
//! 连接操作所用变量
int m_MorphSizeWidth;
int m_MorphSizeHeight;
//! verifySize所用变量
//! verifySize所用变量
float m_error;
float m_aspect;
int m_verifyMin;
int m_verifyMax;
//! 角度判断所用变量
//! 角度判断所用变量
int m_angle;
//! 是否开启调试模式0关闭非0开启
//! 是否开启调试模式0关闭非0开启
int m_debug;
};

@ -27,39 +27,39 @@ class CPlateRecognize : public CPlateDetect, public CCharsRecognise
public:
CPlateRecognize();
//! 车牌检测与字符识别
//! 车牌检测与字符识别
int plateRecognize(Mat, vector<string>&);
//! 生活模式与工业模式切换
//! 生活模式与工业模式切换
inline void setLifemode(bool param)
{
CPlateDetect::setPDLifemode(param);
}
//! 是否开启调试模式
//! 是否开启调试模式
inline void setDebug(int param)
{
CPlateDetect::setPDDebug(param);
CCharsRecognise::setCRDebug(param);
}
////! 车牌定位与判断
////! 车牌定位与判断
//int plateDetect(Mat, vector<Mat>&);
////! 字符分割与识别
////! 字符分割与识别
//int charsRecognise(Mat, String&);
////! 装载SVM
////! 装载SVM
//void LoadSVM(string s);
////! 装载ANN模型
////! 装载ANN模型
//void LoadANN(string s);
private:
////!车牌检测
////!车牌检测
//CPlateDetect* m_plateDetect;
////! 字符识别
////! 字符识别
//CCharsRecognise* m_charsRecognise;
};

@ -7,19 +7,10 @@
#include "opencv2/nonfree/features2d.hpp"
#include "opencv/cvaux.h"
#if defined (WIN32) || defined (_WIN32)
#include <objbase.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#if defined (WIN32) || defined (_WIN32)
#include <io.h>
#elif defined (linux) || defined (__linux__)
#include <sys/io.h>
#endif
#include <iostream>
#include <assert.h>
#include <algorithm>
@ -30,4 +21,4 @@ using namespace std;
using namespace cv;
#endif
/* endif __PREP_H__ */
/* endif __PREP_H__ */

@ -2,22 +2,17 @@
#ifndef __UTIL_H__
#define __UTIL_H__
//C++的获取文件夹函数
//C++的获取文件夹函数
void getFiles(string path, vector<string>& files);
//Linux下的GetTickCount函数
#if defined (linux) || defined (__linux__)
double GetTickCount();
#endif
//C++的spilt函数
//C++的spilt函数
void SplitString(const string& s, vector<string>& v, const string& c);
//C++的从文件路径名称到文件名称(不包括后缀)的方法
//C++的从文件路径名称到文件名称(不包括后缀)的方法
void getFileName(const string& filepath, string& name);
//! levenshtein距离用于计算两个车牌的距离
//EasyPR中用levenshtein距离衡量车牌识别与真实车牌的误差
//! levenshtein距离用于计算两个车牌的距离
//EasyPR中用levenshtein距离衡量车牌识别与真实车牌的误差
template<class T>
unsigned int levenshtein_distance(const T &s1, const T & s2) {
const size_t len1 = s1.size(), len2 = s2.size();
@ -36,33 +31,33 @@ unsigned int levenshtein_distance(const T &s1, const T & s2) {
}
/// test.cpp中方法
/// test.cpp中方法
int testMain();
/// accuracy_test.cpp中方法
/// accuracy_test.cpp中方法
int acurayTest(const string&);
/// mc_data_prepare.cpp中方法
/// mc_data_prepare.cpp中方法
void getLearnData();
void Code2Province(const string& code, string& province);
void changeFileName();
void getPlateLicense(const string& filepath, string& plateLicense);
/// learn_prepare.cpp中方法
/// learn_prepare.cpp中方法
void label_data();
/// general_test_prepare.cpp中方法
/// general_test_prepare.cpp中方法
int general_test();
// deface.cpp中方法
// 反人脸识别函数
// 在发布数据到general_test数据集里请先用这里的方法对图像进行处理
// EasyPR开源项目非常注重保护图片中驾驶人的隐私
// deface.cpp中方法
// 反人脸识别函数
// 在发布数据到general_test数据集里请先用这里的方法对图像进行处理
// EasyPR开源项目非常注重保护图片中驾驶人的隐私
int deface();
/// generate_gdts.cpp中方法
/// generate_gdts.cpp中方法
int generate_gdts();
#endif
/* endif __UTIL_H__ */
/* endif __UTIL_H__ */

@ -18,18 +18,18 @@ extern const string GENERAL_TEST_PATH = "image/general_test";
extern const string NATIVE_TEST_PATH = "image/native_test";
////////////////////////////////////////////////////////////
// EasyPR 训练命令行
// EasyPR 训练命令行
const string option[] =
{
"1. 测试;" ,
"2. 批量测试;" ,
"3. SVM训练;" ,
"4. ANN训练(未开放);" ,
"5. GDTS生成;" ,
"6. 开发团队;" ,
"7. 感谢名单;" ,
"8. 退出;" ,
"1. 测试;" ,
"2. 批量测试;" ,
"3. SVM训练;" ,
"4. ANN训练(未开放);" ,
"5. GDTS生成;" ,
"6. 开发团队;" ,
"7. 感谢名单;" ,
"8. 退出;" ,
};
const int optionCount = 8;
@ -49,7 +49,7 @@ int main()
cout << "////////////////////////////////////"<< endl;
cout << selectOption.str();
cout << "////////////////////////////////////"<< endl;
cout << "请选择一项操作:";
cout << "请选择一项操作:";
int select = -1;
bool isRepeat = true;
@ -75,28 +75,28 @@ int main()
generate_gdts();
break;
case 6:
// 开发团队;
// 开发团队;
cout << endl;
cout << "我们EasyPR团队目前有一个5人左右的小组在进行EasyPR后续版本的开发工作。" << endl;
cout << "如果你对本项目感兴趣,并且愿意为开源贡献一份力量,我们很欢迎你的加入。" << endl;
cout << "目前招聘的主要人才是:车牌定位,图像识别,深度学习,网站建设相关方面的牛人。" << endl;
cout << "如果你觉得自己符合条件,请发邮件到地址(easypr_dev@163.com),期待你的加入!" << endl;
cout << "我们EasyPR团队目前有一个5人左右的小组在进行EasyPR后续版本的开发工作。" << endl;
cout << "如果你对本项目感兴趣,并且愿意为开源贡献一份力量,我们很欢迎你的加入。" << endl;
cout << "目前招聘的主要人才是:车牌定位,图像识别,深度学习,网站建设相关方面的牛人。" << endl;
cout << "如果你觉得自己符合条件,请发邮件到地址(easypr_dev@163.com),期待你的加入!" << endl;
cout << endl;
break;
case 7:
// 感谢名单
// 感谢名单
cout << endl;
cout << "本项目在建设过程中,受到了很多人的帮助,其中以下是对本项目做出突出贡献的" << endl;
cout << "(贡献包括有益建议,代码调优,数据提供等等,排名按时间顺序)" << endl;
cout << "taotao1233, 唐大侠jsxyhelu如果有一天学习奋斗袁承志圣城小石匠" << endl;
cout << "还有很多的同学对本项目也给予了鼓励与支持,在此也一并表示真诚的谢意!" << endl;
cout << "本项目在建设过程中,受到了很多人的帮助,其中以下是对本项目做出突出贡献的" << endl;
cout << "(贡献包括有益建议,代码调优,数据提供等等,排名按时间顺序)" << endl;
cout << "taotao1233, 唐大侠jsxyhelu如果有一天学习奋斗袁承志圣城小石匠" << endl;
cout << "还有很多的同学对本项目也给予了鼓励与支持,在此也一并表示真诚的谢意!" << endl;
cout << endl;
break;
case 8:
isExit = true;
break;
default:
cout << "输入错误,请重新输入:";
cout << "输入错误,请重新输入:";
isRepeat = true;
break;
}
@ -104,18 +104,18 @@ int main()
}
return 0;
}
// /EasyPR 训练命令行 结束
// /EasyPR 训练命令行 结束
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// acurayTestMain 命令行
// acurayTestMain 命令行
const string acuray_option[] =
{
"1. general_test;" ,
"2. native_test;" ,
"3. 返回;" ,
"3. 返回;" ,
};
const int acuray_optionCount = 3;
@ -135,7 +135,7 @@ int acurayTestMain()
cout << "////////////////////////////////////"<< endl;
cout << selectOption.str();
cout << "////////////////////////////////////"<< endl;
cout << "请选择一项操作:";
cout << "请选择一项操作:";
int select = -1;
bool isRepeat = true;
@ -155,7 +155,7 @@ int acurayTestMain()
isExit = true;
break;
default:
cout << "输入错误,请重新输入:";
cout << "输入错误,请重新输入:";
isRepeat = true;
break;
}
@ -164,22 +164,22 @@ int acurayTestMain()
return 0;
}
// acurayTestMain 命令行
// acurayTestMain 命令行
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// SVM 训练命令行
// SVM 训练命令行
const string svm_option[] =
{
"1. 生成learndata(调整代码到你的环境后再用);" ,
"2. 标签learndata;" ,
"3. 车牌检测(not divide and train);" ,
"4. 车牌检测(not train);" ,
"5. 车牌检测(not divide);" ,
"6. 车牌检测;" ,
"7. 返回;" ,
"1. 生成learndata(调整代码到你的环境后再用);" ,
"2. 标签learndata;" ,
"3. 车牌检测(not divide and train);" ,
"4. 车牌检测(not train);" ,
"5. 车牌检测(not divide);" ,
"6. 车牌检测;" ,
"7. 返回;" ,
};
const int svm_optionCount = 7;
@ -199,7 +199,7 @@ int svmMain()
cout << "////////////////////////////////////"<< endl;
cout << selectOption.str();
cout << "////////////////////////////////////"<< endl;
cout << "请选择一项操作:";
cout << "请选择一项操作:";
int select = -1;
bool isRepeat = true;
@ -231,7 +231,7 @@ int svmMain()
isExit = true;
break;
default:
cout << "输入错误,请重新输入:";
cout << "输入错误,请重新输入:";
isRepeat = true;
break;
}
@ -240,5 +240,5 @@ int svmMain()
return 0;
}
// SVM 训练命令行
// SVM 训练命令行
////////////////////////////////////////////////////////////

@ -1,5 +1,5 @@
// 通用正确率测试文件
// AcurayTest对应到main控制命令中的选项2
// 通用正确率测试文件
// AcurayTest对应到main控制命令中的选项2
#include "../include/plate_recognize.h"
#include "../include/util.h"
@ -9,7 +9,7 @@ using namespace easypr;
int acurayTest(const string& test_path)
{
////获取该路径下的所有文件
////获取该路径下的所有文件
vector<string> files;
getFiles(test_path, files);
@ -32,20 +32,20 @@ int acurayTest(const string& test_path)
cout << "Begin to test the easypr accuracy!" << endl;
// 总的测试图片数量
// 总的测试图片数量
int count_all = 0;
// 错误的图片数量
// 错误的图片数量
int count_err = 0;
// 未识别的图片数量
// 未识别的图片数量
int count_norecogin = 0;
// 总的字符差距
// 总的字符差距
float diff_all = 0;
// 平均字符差距
// 平均字符差距
float diff_avg = 0;
// 完全匹配的识别次数
// 完全匹配的识别次数
float match_count = 0;
// 完全匹配的识别次数所占识别图片中的比例
// 完全匹配的识别次数所占识别图片中的比例
float match_rate = 0;
for (int i = 0; i < size; i++)
@ -53,13 +53,13 @@ int acurayTest(const string& test_path)
string filepath = files[i].c_str();
cout << "------------------" << endl;
// 获取真实的车牌
// 获取真实的车牌
string plateLicense = "";
getFileName(filepath, plateLicense);
cout << "原牌:" << plateLicense << endl;
cout << "原牌:" << plateLicense << endl;
// EasyPR开始判断车牌
// EasyPR开始判断车牌
Mat src = imread(filepath);
vector<string> plateVec;
int result = pr.plateRecognize(src, plateVec);
@ -69,20 +69,20 @@ int acurayTest(const string& test_path)
if (num == 0)
{
cout << ""<< "无车牌" <<endl;
if (plateLicense != "无车牌")
cout << ""<< "无车牌" <<endl;
if (plateLicense != "无车牌")
count_norecogin++;
}
else if ( num > 1)
{
// 多车牌使用diff最小的那个记录
// 多车牌使用diff最小的那个记录
int mindiff = 10000;
for (int j = 0; j < num; j++)
{
cout << plateVec[j] << " (" << j+1 << ")"<<endl;
string colorplate = plateVec[j];
// 计算"蓝牌:苏E7KU22"中冒号后面的车牌大小"
// 计算"蓝牌:苏E7KU22"中冒号后面的车牌大小"
vector<string> spilt_plate;
SplitString(colorplate, spilt_plate, ":");
@ -95,23 +95,23 @@ int acurayTest(const string& test_path)
}
}
cout << "差距:" << mindiff << "个字符" << endl;
cout << "差距:" << mindiff << "个字符" << endl;
if(mindiff == 0)
{
// 完全匹配
// 完全匹配
match_count++;
}
diff_all = diff_all + mindiff;
}
else
{
// 单车牌只计算一次diff
// 单车牌只计算一次diff
for (int j = 0; j < num; j++)
{
cout << plateVec[j] <<endl;
string colorplate = plateVec[j];
// 计算"蓝牌:苏E7KU22"中冒号后面的车牌大小"
// 计算"蓝牌:苏E7KU22"中冒号后面的车牌大小"
vector<string> spilt_plate;
SplitString(colorplate, spilt_plate, ":");
@ -119,11 +119,11 @@ int acurayTest(const string& test_path)
if (size == 2)
{
int diff = levenshtein_distance(plateLicense, spilt_plate[size-1]);
cout << "差距:" << diff << "个字符" << endl;
cout << "差距:" << diff << "个字符" << endl;
if(diff == 0)
{
// 完全匹配
// 完全匹配
match_count++;
}
diff_all = diff_all + diff;
@ -134,7 +134,7 @@ int acurayTest(const string& test_path)
}
else
{
cout << "错误码:" << result << endl;
cout << "错误码:" << result << endl;
count_err++;
}
count_all++;
@ -144,20 +144,20 @@ int acurayTest(const string& test_path)
cout << "Easypr accuracy test end!" << endl;
cout << "------------------" << endl;
cout << endl;
cout << "正确率统计:" << endl;
cout << "总图片数:" << count_all << "张, ";
cout << "未识别图片:" << count_norecogin << "张, ";
cout << "正确率统计:" << endl;
cout << "总图片数:" << count_all << "张, ";
cout << "未识别图片:" << count_norecogin << "张, ";
float count_recogin = count_all - (count_err + count_norecogin);
float count_rate = count_recogin / count_all * 100;
cout << "识别率:" << count_rate << "% " << endl;
cout << "识别率:" << count_rate << "% " << endl;
diff_avg = diff_all / count_recogin;
match_rate = match_count/ count_recogin * 100;
cout << "平均字距:" << diff_avg << "个, ";
cout << "完全匹配数:" << match_count << "张, ";
cout << "完全匹配率:" << match_rate << "% " << endl;
cout << "平均字距:" << diff_avg << "个, ";
cout << "完全匹配数:" << match_count << "张, ";
cout << "完全匹配率:" << match_rate << "% " << endl;
cout << endl;
cout << "------------------" << endl;

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

Loading…
Cancel
Save