Merge branch 'Micooz-master-gbk'

Conflicts:
	run_accuracy.txt
	src/core/chars_segment.cpp
1.3
liuruoze 10 years ago
commit 50de5ed2d6

9
.gitignore vendored

@ -187,3 +187,12 @@ UpgradeLog*.htm
# Microsoft Fakes # Microsoft Fakes
FakesAssemblies/ FakesAssemblies/
# idea IDE
.idea/
# XCode IDE
EasyPR.xcodeproj/
# Debug tmp files
image/tmp/

@ -93,6 +93,7 @@
<ClCompile Include="src\core\chars_segment.cpp" /> <ClCompile Include="src\core\chars_segment.cpp" />
<ClCompile Include="src\core\features.cpp" /> <ClCompile Include="src\core\features.cpp" />
<ClCompile Include="src\core\plate.cpp" /> <ClCompile Include="src\core\plate.cpp" />
<ClCompile Include="src\core\core_func.cpp" />
<ClCompile Include="src\test\accuracy_test.cpp" /> <ClCompile Include="src\test\accuracy_test.cpp" />
<ClCompile Include="src\train\ann_train.cpp" /> <ClCompile Include="src\train\ann_train.cpp" />
<ClCompile Include="src\train\svm_train.cpp" /> <ClCompile Include="src\train\svm_train.cpp" />
@ -121,6 +122,7 @@
<ClInclude Include="src\include\plate_judge.h" /> <ClInclude Include="src\include\plate_judge.h" />
<ClInclude Include="src\include\plate_locate.h" /> <ClInclude Include="src\include\plate_locate.h" />
<ClInclude Include="src\include\plate_recognize.h" /> <ClInclude Include="src\include\plate_recognize.h" />
<ClInclude Include="src\include\core_func.h" />
<ClInclude Include="src\include\prep.h" /> <ClInclude Include="src\include\prep.h" />
<ClInclude Include="src\include\util.h" /> <ClInclude Include="src\include\util.h" />
</ItemGroup> </ItemGroup>

@ -93,6 +93,9 @@
<ClCompile Include="src\core\plate.cpp"> <ClCompile Include="src\core\plate.cpp">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\core\core_func.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\include\chars_identify.h"> <ClInclude Include="src\include\chars_identify.h">
@ -131,5 +134,8 @@
<ClInclude Include="src\include\plate.h"> <ClInclude Include="src\include\plate.h">
<Filter>头文件</Filter> <Filter>头文件</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\include\core_func.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -5,46 +5,44 @@ EasyPR是一个中文的开源车牌识别系统其目标是成为一个简
相比于其他的车牌识别系统EasyPR有如下特点 相比于其他的车牌识别系统EasyPR有如下特点
* 它基于openCV这个开源库。这意味着你可以获取全部源代码并且移植到java等平台。 * 它基于openCV这个开源库。这意味着你可以获取全部源代码并且移植到opencv支持的所有平台。
* 它能够识别中文。例如车牌为苏EUK722的图片它可以准确地输出std:string类型的"苏EUK722"的结果。 * 它能够识别中文。例如车牌为苏EUK722的图片它可以准确地输出std:string类型的"苏EUK722"的结果。
* 它的识别率较高。图片清晰情况下车牌检测与字符识别可以达到90%以上的精度。 * 它的识别率较高。图片清晰情况下车牌检测与字符识别可以达到80%以上的精度。
### 版本
EasyPR最开始是发布在[GitHub](https://github.com/liuruoze/EasyPR)上的,然后在国内的[oschina](http://git.oschina.net/easypr/EasyPR)上也部署了一份镜像。
相关的issue欢迎在GitHub上统一提交。目前除了windows版本以外还有以下其他平台的版本
|版本 | 开发者 | 地址
|------|-------|-------
| android | goldriver | [linuxxx/EasyPR_Android](https://github.com/linuxxx/EasyPR_Android)
| linux | Micooz | [Micooz/EasyPR/tree/linux-dev](https://github.com/Micooz/EasyPR/tree/linux-dev)
| ios | zhoushiwei | [zhoushiwei/EasyPR-iOS](https://github.com/zhoushiwei/EasyPR-iOS)
| mac | zhoushiwei | [zhoushiwei/EasyPR](https://github.com/zhoushiwei/EasyPR)
| c# | 暂无 |
| java | 暂无 |
感谢以上所有开发者的努力!
### 更新 ### 更新
本版本是EasyPR 1.2版本相比前版本的主要改进是提升了车牌定位模块的准确性从上个版本70%左右的准确率提升到目前的94%。见下图: 本版本是EasyPR 1.2版本相比前版本的主要改进是提升了车牌定位模块的准确性从上个版本70%左右的准确率提升到目前的94%。见下图:
![1.2版综合效果](doc/res/testresult.png) ![1.2版综合效果](doc/res/testresult.png)
主要内容如下: 主要内容如下:
* 1.车牌定位使用了“颜色信息”+“二次Sobel”的综合搜索方法。在下面的window中红框代表Sobel定位结果黄框代表颜色定位结果。 * 车牌定位使用了“颜色信息”+“二次Sobel”的综合搜索方法。在下面的window中红框代表Sobel定位结果黄框代表颜色定位结果。
* 2.“批量测试”功能增加了一个结果查看window这个窗口可以用SetDebug()方法开闭(true开false关)。 * “批量测试”增加了一个结果查看window这个窗口可以用SetDebug()方法开闭(true开false关)。
![查看结果](doc/res/window.png) ![查看结果](doc/res/window.png)
* 3.解决了“大角度定位”问题,见下图。原图中的车牌可以被定位并转换到正确的视角。 * 基本攻克了“大角度定位”问题,下图的车牌被定位并转到了正确的视角。
![大角度定位](doc/res/bigangle.png) ![大角度定位](doc/res/bigangle.png)
* 4.GDTS里新增了若干张新测试图包括数张大角度图。 * GDTS里新增了若干张新测试图包括数张大角度图。
* “批量测试”结果现在同时会保存在“run_accuracy”文件中可以查询历史运行信息。
* 与Linux版本做了整合可以实现跨平台编译。
### 平台
目前除了windows平台以外还有以下其他平台的EasyPR版本。一些平台的版本可能会暂时落后于主平台。
|版本 | 开发者 | 版本 | 地址
|------|-------|-------|-------
| android | goldriver | 1.1 | [linuxxx/EasyPR_Android](https://github.com/linuxxx/EasyPR_Android)
| linux | Micooz | 1.2 | 已跟EasyPR整合
| ios | zhoushiwei | 1.1 | [zhoushiwei/EasyPR-iOS](https://github.com/zhoushiwei/EasyPR-iOS)
| mac | zhoushiwei | 1.1 | [zhoushiwei/EasyPR](https://github.com/zhoushiwei/EasyPR)
### 兼容性 ### 兼容性
@ -117,7 +115,7 @@ EasyPR不需要安装开发者直接在其上做改动。如果想使用DLL
| plate_recognize | 车牌识别,是车牌检测与字符识别的共有子类 | plate_recognize | 车牌识别,是车牌检测与字符识别的共有子类
| features | 特征提取回调函数 | features | 特征提取回调函数
| plate | 车牌抽象 | plate | 车牌抽象
| prep.h | 预包含头文件 | core_func.h | 共有的一些函数
以下表格是src目录下一些辅助文件的解释与关系: 以下表格是src目录下一些辅助文件的解释与关系:
@ -130,10 +128,17 @@ EasyPR不需要安装开发者直接在其上做改动。如果想使用DLL
| svm_train.cpp | svm训练函数 | svm_train.cpp | svm训练函数
| generate_gdts.cpp | GDTS生成函数 | generate_gdts.cpp | GDTS生成函数
### 问题 ### Contributer
* liuruoze作者与核心代码编写
* Micoozlinux平台编译性能优化util类
* jsxyheludeface版本一
* zhoushiweideface版本二
如果有任何问题或者建议请在issues里直接提交或者发emaileasypr_dev@163.com。 * ahccom新的plateLocate函数
建议与问题一经采纳即会将您的贡献大名列入EasyPR的感谢名单 Credits )中。
### 鸣谢 ### 鸣谢

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

File diff suppressed because it is too large Load Diff

@ -1,24 +1,24 @@
#include "../include/chars_recognise.h" #include "../include/chars_recognise.h"
/*! \namespace easypr /*! \namespace easypr
Namespace where all the C++ EasyPR functionality resides Namespace where all the C++ EasyPR functionality resides
*/ */
namespace easypr{ namespace easypr{
CCharsRecognise::CCharsRecognise() CCharsRecognise::CCharsRecognise()
{ {
//cout << "CCharsRecognise" << endl; //cout << "CCharsRecognise" << endl;
m_charsSegment = new CCharsSegment(); m_charsSegment = new CCharsSegment();
m_charsIdentify = new CCharsIdentify(); m_charsIdentify = new CCharsIdentify();
} }
void CCharsRecognise::LoadANN(string s) void CCharsRecognise::LoadANN(string s)
{ {
m_charsIdentify->LoadModel(s.c_str()); m_charsIdentify->LoadModel(s.c_str());
} }
int CCharsRecognise::charsRecognise(Mat plate, string& plateLicense) int CCharsRecognise::charsRecognise(Mat plate, string& plateLicense)
{ {
//车牌字符方块集合 //车牌字符方块集合
vector<Mat> matVec; vector<Mat> matVec;
@ -45,6 +45,6 @@ int CCharsRecognise::charsRecognise(Mat plate, string& plateLicense)
plateLicense = plateIdentify; plateLicense = plateIdentify;
return 0; return 0;
} }
} /*! \namespace easypr*/ } /*! \namespace easypr*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -4,64 +4,22 @@
#include "../include/prep.h" #include "../include/prep.h"
#include "../include/features.h" #include "../include/features.h"
#include "../include/core_func.h"
/*! \namespace easypr /*! \namespace easypr
Namespace where all the C++ EasyPR functionality resides Namespace where all the C++ EasyPR functionality resides
*/ */
namespace easypr { namespace easypr {
//! 直方图均衡 //! 获取垂直和水平的直方图图值
Mat histeq(Mat in) Mat getTheFeatures(Mat in)
{
Mat out(in.size(), in.type());
if(in.channels()==3)
{ {
Mat hsv;
vector<Mat> hsvSplit;
cvtColor(in, hsv, CV_BGR2HSV);
split(hsv, hsvSplit);
equalizeHist(hsvSplit[2], hsvSplit[2]);
merge(hsvSplit, hsv);
cvtColor(hsv, out, CV_HSV2BGR);
}
else if(in.channels()==1)
{
equalizeHist(in, out);
}
return out;
}
// !获取垂直和水平方向直方图
Mat ProjectedHistogram(Mat img, int t)
{
int sz=(t)?img.rows:img.cols;
Mat mhist=Mat::zeros(1,sz,CV_32F);
for(int j=0; j<sz; j++){
Mat data=(t)?img.row(j):img.col(j);
mhist.at<float>(j)=countNonZero(data); //统计这一行或一列中非零元素的个数并保存到mhist中
}
//Normalize histogram
double min, max;
minMaxLoc(mhist, &min, &max);
if(max>0)
mhist.convertTo(mhist,-1 , 1.0f/max, 0);//用mhist直方图中的最大值归一化直方图
return mhist;
}
//! 获得车牌的特征数
Mat getTheFeatures(Mat in)
{
const int VERTICAL = 0; const int VERTICAL = 0;
const int HORIZONTAL = 1; const int HORIZONTAL = 1;
//Histogram features //Histogram features
Mat vhist=ProjectedHistogram(in, VERTICAL); Mat vhist = ProjectedHistogram(in, VERTICAL);
Mat hhist=ProjectedHistogram(in, HORIZONTAL); Mat hhist = ProjectedHistogram(in, HORIZONTAL);
//Last 10 is the number of moments components //Last 10 is the number of moments components
int numCols = vhist.cols + hhist.cols; int numCols = vhist.cols + hhist.cols;
@ -69,55 +27,64 @@ Mat getTheFeatures(Mat in)
Mat out = Mat::zeros(1, numCols, CV_32F); Mat out = Mat::zeros(1, numCols, CV_32F);
//Asign values to feature,样本特征为水平、垂直直方图 //Asign values to feature,样本特征为水平、垂直直方图
int j=0; int j = 0;
for(int i=0; i<vhist.cols; i++) for (int i = 0; i<vhist.cols; i++)
{ {
out.at<float>(j)=vhist.at<float>(i); out.at<float>(j) = vhist.at<float>(i);
j++; j++;
} }
for(int i=0; i<hhist.cols; i++) for (int i = 0; i<hhist.cols; i++)
{ {
out.at<float>(j)=hhist.at<float>(i); out.at<float>(j) = hhist.at<float>(i);
j++; j++;
} }
return out; return out;
} }
// ! EasyPR的getFeatures回调函数 //! EasyPR的getFeatures回调函数
// 本函数是生成直方图均衡特征的回调函数 //! 本函数是生成直方图均衡特征的回调函数
void getHisteqFeatures(const Mat& image, Mat& features) void getHisteqFeatures(const Mat& image, Mat& features)
{ {
features = histeq(image); features = histeq(image);
} }
// ! EasyPR的getFeatures回调函数 //! EasyPR的getFeatures回调函数
// 本函数是获取垂直和水平的直方图图值 //! 本函数是获取垂直和水平的直方图图值
void getHistogramFeatures(const Mat& image, Mat& features) void getHistogramFeatures(const Mat& image, Mat& features)
{ {
Mat grayImage; Mat grayImage;
cvtColor(image, grayImage, CV_RGB2GRAY); cvtColor(image, grayImage, CV_RGB2GRAY);
//grayImage = histeq(grayImage); //grayImage = histeq(grayImage);
Mat img_threshold; Mat img_threshold;
threshold(grayImage, img_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY); threshold(grayImage, img_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);
features = getTheFeatures(img_threshold); features = getTheFeatures(img_threshold);
} }
// ! EasyPR的getFeatures回调函数 //! EasyPR的getFeatures回调函数
// 本函数是获取SITF特征子 //! 本函数是获取SITF特征子
// ! void getSIFTFeatures(const Mat& image, Mat& features)
void getSIFTFeatures(const Mat& image, Mat& features) {
{
//待完善 //待完善
} }
// ! EasyPR的getFeatures回调函数 //! EasyPR的getFeatures回调函数
// 本函数是获取HOG特征子 //! 本函数是获取HOG特征子
void getHOGFeatures(const Mat& image, Mat& features) void getHOGFeatures(const Mat& image, Mat& features)
{ {
//待完善 //待完善
} }
//! EasyPR的getFeatures回调函数
//! 本函数是获取HSV空间量化的直方图特征子
void getHSVHistFeatures(const Mat& image, Mat& features)
{
//TODO
}
} /* \namespace easypr */ } /* \namespace easypr */

@ -10,6 +10,9 @@ CPlateDetect::CPlateDetect()
//cout << "CPlateDetect" << endl; //cout << "CPlateDetect" << endl;
m_plateLocate = new CPlateLocate(); m_plateLocate = new CPlateLocate();
m_plateJudge = new CPlateJudge(); m_plateJudge = new CPlateJudge();
// 默认EasyPR在一幅图中定位最多3个车
m_maxPlates = 3;
} }
void CPlateDetect::LoadSVM(string s) void CPlateDetect::LoadSVM(string s)
@ -65,7 +68,7 @@ int CPlateDetect::plateDetectDeep(Mat src, vector<Mat>& resultVec, bool showDete
vector<CPlate> all_result_Plates; vector<CPlate> all_result_Plates;
//如果颜色查找找到n个以上包含n个的车牌就不再进行Sobel查找了。 //如果颜色查找找到n个以上包含n个的车牌就不再进行Sobel查找了。
const int color_find_max = 4; const int color_find_max = m_maxPlates;
Mat result; Mat result;
src.copyTo(result); src.copyTo(result);

File diff suppressed because it is too large Load Diff

@ -57,7 +57,7 @@ int CPlateRecognize::plateRecognize(Mat src, vector<string>& licenseVec)
Mat plate = plateVec[j]; Mat plate = plateVec[j];
//»ñÈ¡³µÅÆÑÕÉ« //»ñÈ¡³µÅÆÑÕÉ«
string plateType = getPlateType(plate); string plateType = getPlateColor(plate);
//»ñÈ¡³µÅƺŠ//»ñÈ¡³µÅƺÅ
string plateIdentify = ""; string plateIdentify = "";

@ -1,11 +1,3 @@
//////////////////////////////////////////////////////////////////////////
// Name: CParser Header
// Date: 2015-02-05
// Author: Micooz
// Copyright: Micooz
// Desciption:
// Defines OptionError, CParseItem, CParser
//////////////////////////////////////////////////////////////////////////
#ifndef __CPARSER_H__ #ifndef __CPARSER_H__
#define __CPARSER_H__ #define __CPARSER_H__
@ -15,6 +7,9 @@
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
// CParser can be used for parsing command line. It stores options and values to a map.
// It's easy to check whether an option exist, get value with a specified type.
namespace easypr { namespace easypr {
// class OptionError // class OptionError

@ -18,13 +18,13 @@
#include "chars_identify.h" #include "chars_identify.h"
/*! \namespace easypr /*! \namespace easypr
Namespace where all the C++ EasyPR functionality resides Namespace where all the C++ EasyPR functionality resides
*/ */
namespace easypr { namespace easypr {
class CCharsRecognise class CCharsRecognise
{ {
public: public:
CCharsRecognise(); CCharsRecognise();
//! 字符分割与识别 //! 字符分割与识别
@ -34,39 +34,39 @@ public:
void LoadANN(string s); void LoadANN(string s);
//! 是否开启调试模式 //! 是否开启调试模式
inline void setCRDebug(int param){ m_charsSegment->setDebug(param);} inline void setCRDebug(int param){ m_charsSegment->setDebug(param); }
//! 获取调试模式状态 //! 获取调试模式状态
inline int getCRDebug(){ return m_charsSegment->getDebug();} inline int getCRDebug(){ return m_charsSegment->getDebug(); }
//! 获得车牌颜色 //! 获得车牌颜色
inline string getPlateType(Mat input) const inline string getPlateColor(Mat input) const
{ {
string color = "未知"; string color = "未知";
int result = m_charsSegment->getPlateType(input); Color result = getPlateType(input, true);
if (1 == result) if (BLUE == result)
color = "蓝牌"; color = "蓝牌";
if (2 == result) if (YELLOW == result)
color = "黄牌"; color = "黄牌";
return color; return color;
} }
//! 设置变量 //! 设置变量
inline void setLiuDingSize(int param){ m_charsSegment->setLiuDingSize(param);} inline void setLiuDingSize(int param){ m_charsSegment->setLiuDingSize(param); }
inline void setColorThreshold(int param){ m_charsSegment->setColorThreshold(param);} inline void setColorThreshold(int param){ m_charsSegment->setColorThreshold(param); }
inline void setBluePercent(float param){ m_charsSegment->setBluePercent(param);} inline void setBluePercent(float param){ m_charsSegment->setBluePercent(param); }
inline float getBluePercent() const { return m_charsSegment->getBluePercent();} inline float getBluePercent() const { return m_charsSegment->getBluePercent(); }
inline void setWhitePercent(float param){ m_charsSegment->setWhitePercent(param);} inline void setWhitePercent(float param){ m_charsSegment->setWhitePercent(param); }
inline float getWhitePercent() const { return m_charsSegment->getWhitePercent();} inline float getWhitePercent() const { return m_charsSegment->getWhitePercent(); }
private: private:
//!字符分割 //!字符分割
CCharsSegment* m_charsSegment; CCharsSegment* m_charsSegment;
//! 字符识别 //! 字符识别
CCharsIdentify* m_charsIdentify; CCharsIdentify* m_charsIdentify;
}; };
} /* \namespace easypr */ } /* \namespace easypr */

@ -13,44 +13,27 @@
#define __CHARS_SEGMENT_H__ #define __CHARS_SEGMENT_H__
#include "prep.h" #include "prep.h"
#include "core_func.h"
/*! \namespace easypr /*! \namespace easypr
Namespace where all the C++ EasyPR functionality resides Namespace where all the C++ EasyPR functionality resides
*/ */
namespace easypr { namespace easypr {
class CCharsSegment class CCharsSegment
{ {
public: public:
enum Color { BLUE, YELLOW };
CCharsSegment(); CCharsSegment();
bool plateColorJudge(Mat src, Color r);
//! 字符分割 //! 字符分割
int charsSegment(Mat, vector<Mat>& ); int charsSegment(Mat, vector<Mat>&);
//! 字符尺寸验证 //! 字符尺寸验证
bool verifySizes(Mat r); bool verifyCharSizes(Mat r);
//! 字符预处理 //! 字符预处理
Mat preprocessChar(Mat in); 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 GetChineseRect(const Rect rectSpe);
@ -66,13 +49,13 @@ public:
int SortRect(const vector<Rect>& vecRect, vector<Rect>& out); int SortRect(const vector<Rect>& vecRect, vector<Rect>& out);
//! 设置变量 //! 设置变量
inline void setLiuDingSize(int param){ m_LiuDingSize = param;} inline void setLiuDingSize(int param){ m_LiuDingSize = param; }
inline void setColorThreshold(int param){ m_ColorThreshold = param;} inline void setColorThreshold(int param){ m_ColorThreshold = param; }
inline void setBluePercent(float param){ m_BluePercent = param;} inline void setBluePercent(float param){ m_BluePercent = param; }
inline float getBluePercent() const { return m_BluePercent;} inline float getBluePercent() const { return m_BluePercent; }
inline void setWhitePercent(float param){ m_WhitePercent = param;} inline void setWhitePercent(float param){ m_WhitePercent = param; }
inline float getWhitePercent() const { return m_WhitePercent;} inline float getWhitePercent() const { return m_WhitePercent; }
//! 是否开启调试模式常量默认0代表关闭 //! 是否开启调试模式常量默认0代表关闭
static const int DEFAULT_DEBUG = 0; static const int DEFAULT_DEBUG = 0;
@ -88,12 +71,12 @@ public:
static const int DEFAULT_COLORTHRESHOLD = 150; static const int DEFAULT_COLORTHRESHOLD = 150;
//! 是否开启调试模式 //! 是否开启调试模式
inline void setDebug(int param){ m_debug = param;} inline void setDebug(int param){ m_debug = param; }
//! 获取调试模式状态 //! 获取调试模式状态
inline int getDebug(){ return m_debug;} inline int getDebug(){ return m_debug; }
private: private:
//!柳钉判断参数 //!柳钉判断参数
int m_LiuDingSize; int m_LiuDingSize;
@ -107,7 +90,7 @@ private:
//! 是否开启调试模式0关闭非0开启 //! 是否开启调试模式0关闭非0开启
int m_debug; int m_debug;
}; };
} /* \namespace easypr */ } /* \namespace easypr */

@ -0,0 +1,39 @@
#ifndef __CORE_FUNC_H__
#define __CORE_FUNC_H__
/*! \namespace easypr
Namespace where all the C++ EasyPR functionality resides
*/
namespace easypr {
enum Color{ BLUE, YELLOW };
//! 根据一幅图像与颜色模板获取对应的二值图
//! 输入RGB图像, 颜色模板(蓝色、黄色)
//! 输出灰度图只有0和255两个值255代表匹配0代表不匹配
Mat colorMatch(const Mat& src, Mat& match, const Color r, const bool adaptive_minsv);
//! 判断一个车牌的颜色
//! 输入车牌mat与颜色模板
//! 返回true或fasle
bool plateColorJudge(const Mat& src, const Color r, const bool adaptive_minsv);
//clearLiuDing
//去除车牌上方的钮钉
//计算每行元素的阶跃数如果小于X认为是柳丁将此行全部填0涂黑
//X的推荐值为可根据实际调整
Mat clearLiuDing(Mat img);
//! 获得车牌颜色
Color getPlateType(const Mat& src, const bool adaptive_minsv);
//! 直方图均衡
Mat histeq(Mat in);
// !获取垂直和水平方向直方图
Mat ProjectedHistogram(Mat img, int t);
} /*! \namespace easypr*/
#endif
/* endif __CORE_FUNC_H__ */

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

@ -69,8 +69,14 @@ public:
inline void setJudgeAngle(int param){m_plateLocate->setJudgeAngle(param);} inline void setJudgeAngle(int param){m_plateLocate->setJudgeAngle(param);}
inline void setMaxPlates(float param){ m_maxPlates = param; }
inline float getMaxPlates() const { return m_maxPlates; }
private: private:
//!车牌定位 //! 设置一幅图中最多有多少车牌
int m_maxPlates;
//! 车牌定位
CPlateLocate* m_plateLocate; CPlateLocate* m_plateLocate;
//! łľĹĆĹĐśĎ //! łľĹĆĹĐśĎ

@ -14,8 +14,9 @@
#define __PLATE_JUDGE_H__ #define __PLATE_JUDGE_H__
#include "prep.h" #include "prep.h"
#include "features.h"
#include "plate.h" #include "plate.h"
#include "features.h"
#include "core_func.h"
/*! \namespace easypr /*! \namespace easypr
Namespace where all the C++ EasyPR functionality resides Namespace where all the C++ EasyPR functionality resides

@ -16,6 +16,7 @@
#include "prep.h" #include "prep.h"
#include "plate.h" #include "plate.h"
#include "core_func.h"
/*! \namespace easypr /*! \namespace easypr
Namespace where all the C++ EasyPR functionality resides Namespace where all the C++ EasyPR functionality resides
@ -28,7 +29,6 @@ public:
CPlateLocate(); CPlateLocate();
enum LocateType { SOBEL, COLOR }; enum LocateType { SOBEL, COLOR };
enum Color { BLUE, YELLOW };
//! Sobel第一次搜索 //! Sobel第一次搜索
//! 不限制大小和形状获取的BoundRect进入下一步 //! 不限制大小和形状获取的BoundRect进入下一步
@ -65,24 +65,13 @@ public:
int plateSobelLocate(Mat src, vector<CPlate>& candPlates, int index = 0); int plateSobelLocate(Mat src, vector<CPlate>& candPlates, int index = 0);
//! Color搜索 //! Color搜索
int colorMatch(const Mat& src, const Color r, Mat& out, vector<RotatedRect>& outRects, int index = 0); int colorSearch(const Mat& src, const Color r, Mat& out, vector<RotatedRect>& outRects, int index = 0);
//! 未使用函数与代码 //! 未使用函数与代码
//! 开始------------ //! 开始------------
int sobelFind(const Mat& src, vector<RotatedRect>& rects);
int sobelFindAgn(const Mat& src, vector<RotatedRect>& outRects, vector<Mat>& resultVec);
bool charJudge(Mat roi);
bool sobelJudge(Mat roi); bool sobelJudge(Mat roi);
int colorJudge(const Mat& src, const Color r, vector<RotatedRect>& rects);
int deskewOld(Mat src, vector<RotatedRect>& inRects, vector<RotatedRect>& outRects, vector<Mat>& outMats, LocateType locateType); int deskewOld(Mat src, vector<RotatedRect>& inRects, vector<RotatedRect>& outRects, vector<Mat>& outMats, LocateType locateType);
bool verifyCharSizes(Mat r); bool verifyCharSizes(Mat r);
int getPlateType(Mat src);
bool plateColorJudge(Mat src, const Color r);
Mat clearLiuDing(Mat img);
//! 结束------------ //! 结束------------
//! 未使用函数与代码 //! 未使用函数与代码

@ -7,10 +7,19 @@
#include "opencv2/nonfree/features2d.hpp" #include "opencv2/nonfree/features2d.hpp"
#include "opencv/cvaux.h" #include "opencv/cvaux.h"
#if defined (WIN32) || defined (_WIN32)
#include <objbase.h> #include <objbase.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#if defined (WIN32) || defined (_WIN32)
#include <io.h> #include <io.h>
#elif defined (linux) || defined (__linux__)
#include <sys/io.h>
#endif
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <assert.h> #include <assert.h>

@ -2,28 +2,55 @@
#ifndef __UTIL_H__ #ifndef __UTIL_H__
#define __UTIL_H__ #define __UTIL_H__
//C++的获取文件夹函数 #ifdef min
void getFiles(string path, vector<string>& files); #undef min
#endif
namespace easypr {
class Utils {
public:
static long getTimestamp();
/*
* Get file name from a given path
* bool postfix: including the postfix
*/
static std::string getFileName(const std::string &path, const bool postfix = false);
/*
* Split the given string into segements by a delimiter
*/
static std::vector<std::string> splitString(const std::string &str, const char delimiter);
/*
* returns the smaller of the two numbers
*/
template<typename T>
static T min(const T &v1, const T &v2) {
return (v1 < v2) ? v1 : v2;
}
//C++的spilt函数 };
void SplitString(const string& s, vector<string>& v, const string& c);
//C++的从文件路径名称到文件名称(不包括后缀)的方法 }
void getFileName(const string& filepath, string& name);
//C++µÄ»ñÈ¡Îļþ¼Ðº¯Êý
void getFiles(std::string path, std::vector<std::string>& files);
//! levenshtein距离用于计算两个车牌的距离 //! levenshtein距离用于计算两个车牌的距离
//EasyPR中用levenshtein距离衡量车牌识别与真实车牌的误差 //EasyPR中用levenshtein距离衡量车牌识别与真实车牌的误差
template<class T> template<class T>
unsigned int levenshtein_distance(const T &s1, const T & s2) { unsigned int levenshtein_distance(const T &s1, const T & s2) {
const size_t len1 = s1.size(), len2 = s2.size(); const size_t len1 = s1.size(), len2 = s2.size();
vector<unsigned int> col(len2+1), prevCol(len2+1); std::vector<unsigned int> col(len2+1), prevCol(len2+1);
for (unsigned int i = 0; i < prevCol.size(); i++) for (unsigned int i = 0; i < prevCol.size(); i++)
prevCol[i] = i; prevCol[i] = i;
for (unsigned int i = 0; i < len1; i++) { for (unsigned int i = 0; i < len1; i++) {
col[0] = i+1; col[0] = i+1;
for (unsigned int j = 0; j < len2; j++) for (unsigned int j = 0; j < len2; j++)
col[j+1] = min( min(prevCol[1 + j] + 1, col[j] + 1), \ col[j+1] = easypr::Utils::min(easypr::Utils::min(prevCol[1 + j] + 1, col[j] + 1), \
prevCol[j] + (s1[i]==s2[j] ? 0 : 1) ); prevCol[j] + (s1[i]==s2[j] ? 0 : 1) );
col.swap(prevCol); col.swap(prevCol);
} }
@ -35,13 +62,13 @@ unsigned int levenshtein_distance(const T &s1, const T & s2) {
int testMain(); int testMain();
/// accuracy_test.cpp中方法 /// accuracy_test.cpp中方法
int acurayTest(const string&); int acurayTest(const std::string&);
/// mc_data_prepare.cpp中方法 /// mc_data_prepare.cpp中方法
void getLearnData(); void getLearnData();
void Code2Province(const string& code, string& province); void Code2Province(const std::string& code, std::string& province);
void changeFileName(); void changeFileName();
void getPlateLicense(const string& filepath, string& plateLicense); void getPlateLicense(const std::string& filepath, std::string& plateLicense);
/// learn_prepare.cpp中方法 /// learn_prepare.cpp中方法
void label_data(); void label_data();

@ -23,7 +23,7 @@ extern const string NATIVE_TEST_PATH = "image/native_test";
// EasyPR 训练命令行 // EasyPR 训练命令行
const string option[] = const string option[] =
{ {
"1. 测试;" , "1. 测试;" ,
"2. 批量测试;" , "2. 批量测试;" ,
"3. SVM训练;" , "3. SVM训练;" ,
@ -32,7 +32,7 @@ const string option[] =
"6. 开发团队;" , "6. 开发团队;" ,
"7. 感谢名单;" , "7. 感谢名单;" ,
"8. 退出;" , "8. 退出;" ,
}; };
const int optionCount = 8; const int optionCount = 8;
@ -97,7 +97,7 @@ int main(int argc, char *argv[])
cout << endl; cout << endl;
cout << "本项目在建设过程中,受到了很多人的帮助,其中以下是对本项目做出突出贡献的" << endl; cout << "本项目在建设过程中,受到了很多人的帮助,其中以下是对本项目做出突出贡献的" << endl;
cout << "(贡献包括有益建议,代码调优,数据提供等等,排名按时间顺序)" << endl; cout << "(贡献包括有益建议,代码调优,数据提供等等,排名按时间顺序)" << endl;
cout << "taotao1233唐大侠jsxyhelu如果有一天(zhoushiwei)学习奋斗袁承志圣城小石匠goldriverMicooz梦里时光Rain Wang" << endl; cout << "taotao1233唐大侠jsxyhelu如果有一天(zhoushiwei)学习奋斗袁承志圣城小石匠goldriverMicooz梦里时光Rain Wangahccom" << endl;
cout << "还有很多的同学对本项目也给予了鼓励与支持,在此也一并表示真诚的谢意!" << endl; cout << "还有很多的同学对本项目也给予了鼓励与支持,在此也一并表示真诚的谢意!" << endl;
cout << endl; cout << endl;
break; break;
@ -121,11 +121,11 @@ int main(int argc, char *argv[])
// acurayTestMain 命令行 // acurayTestMain 命令行
const string acuray_option[] = const string acuray_option[] =
{ {
"1. general_test;" , "1. general_test;" ,
"2. native_test;" , "2. native_test;" ,
"3. 返回;" , "3. 返回;" ,
}; };
const int acuray_optionCount = 3; const int acuray_optionCount = 3;
@ -181,7 +181,7 @@ int acurayTestMain()
// SVM 训练命令行 // SVM 训练命令行
const string svm_option[] = const string svm_option[] =
{ {
"1. 生成learndata(调整代码到你的环境后再用);" , "1. 生成learndata(调整代码到你的环境后再用);" ,
"2. 标签learndata;" , "2. 标签learndata;" ,
"3. 车牌检测(not divide and train);" , "3. 车牌检测(not divide and train);" ,
@ -189,7 +189,7 @@ const string svm_option[] =
"5. 车牌检测(not divide);" , "5. 车牌检测(not divide);" ,
"6. 车牌检测;" , "6. 车牌检测;" ,
"7. 返回;" , "7. 返回;" ,
}; };
const int svm_optionCount = 7; const int svm_optionCount = 7;

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

Loading…
Cancel
Save