Convert src/* to UTF-8.

1.3
Micooz 11 years ago
parent f594e4ba96
commit d067f34e5b

@ -8,27 +8,27 @@ namespace easypr{
#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个英文字符之和 */
//以下都是我训练时用到的中文字符数据,并不全面,有些省份没有训练数据所以没有字符
//有些后面加数字2的表示在训练时常看到字符的一种变形也作为训练数据存储
//以下都是我训练时用到的中文字符数据,并不全面,有些省份没有训练数据所以没有字符
//有些后面加数字2的表示在训练时常看到字符的一种变形也作为训练数据存储
const string strChinese[] = {
"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" /* 浙 */};
"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" /* 浙 */};
const int numChinese = 31;
const int numAll = 65; /* 34+20=54 */
@ -42,37 +42,37 @@ 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_gan1",""));
m_map.insert(pair<string, string>("zh_gui",""));
m_map.insert(pair<string, string>("zh_gui1",""));
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_jin",""));
m_map.insert(pair<string, string>("zh_jing",""));
m_map.insert(pair<string, string>("zh_jl",""));
m_map.insert(pair<string, string>("zh_liao",""));
m_map.insert(pair<string, string>("zh_lu",""));
m_map.insert(pair<string, string>("zh_meng",""));
m_map.insert(pair<string, string>("zh_min",""));
m_map.insert(pair<string, string>("zh_ning",""));
m_map.insert(pair<string, string>("zh_qing",""));
m_map.insert(pair<string, string>("zh_qiong",""));
m_map.insert(pair<string, string>("zh_shan",""));
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_xiang",""));
m_map.insert(pair<string, string>("zh_xin",""));
m_map.insert(pair<string, string>("zh_yu",""));
m_map.insert(pair<string, string>("zh_yu1",""));
m_map.insert(pair<string, string>("zh_yue",""));
m_map.insert(pair<string, string>("zh_yun",""));
m_map.insert(pair<string, string>("zh_zang",""));
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_gan1",""));
m_map.insert(pair<string, string>("zh_gui",""));
m_map.insert(pair<string, string>("zh_gui1",""));
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_jin",""));
m_map.insert(pair<string, string>("zh_jing",""));
m_map.insert(pair<string, string>("zh_jl",""));
m_map.insert(pair<string, string>("zh_liao",""));
m_map.insert(pair<string, string>("zh_lu",""));
m_map.insert(pair<string, string>("zh_meng",""));
m_map.insert(pair<string, string>("zh_min",""));
m_map.insert(pair<string, string>("zh_ning",""));
m_map.insert(pair<string, string>("zh_qing",""));
m_map.insert(pair<string, string>("zh_qiong",""));
m_map.insert(pair<string, string>("zh_shan",""));
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_xiang",""));
m_map.insert(pair<string, string>("zh_xin",""));
m_map.insert(pair<string, string>("zh_yu",""));
m_map.insert(pair<string, string>("zh_yu1",""));
m_map.insert(pair<string, string>("zh_yue",""));
m_map.insert(pair<string, string>("zh_yun",""));
m_map.insert(pair<string, string>("zh_zang",""));
m_map.insert(pair<string, string>("zh_zhe",""));
}
}
@ -93,9 +93,9 @@ void CCharsIdentify::LoadModel(string s)
int CCharsIdentify::classify(Mat f, bool isChinses,bool isSpeci){
int result = -1;
Mat output(1, numAll, CV_32FC1);
ann.predict(f, output);//使用ann对字符做判断
ann.predict(f, output);//使用ann对字符做判断
if (!isChinses)//对中文字符的判断
if (!isChinses)//对中文字符的判断
{if(isSpeci)
{result = 0;
float maxVal = -2;
@ -118,7 +118,7 @@ int CCharsIdentify::classify(Mat f, bool isChinses,bool isSpeci){
{
float val = output.at<float>(j);
//cout << "j:" << j << "val:"<< val << endl;
if (val > maxVal)//求得中文字符权重最大的那个也就是通过ann认为最可能的字符
if (val > maxVal)//求得中文字符权重最大的那个也就是通过ann认为最可能的字符
{
maxVal = val;
result = j;
@ -126,7 +126,7 @@ int CCharsIdentify::classify(Mat f, bool isChinses,bool isSpeci){
}
}
}
else//对数字和英文字母的判断
else//对数字和英文字母的判断
{
result = numCharacter;
@ -150,7 +150,7 @@ int CCharsIdentify::classify(Mat f)
{
int result = -1;
Mat output(1, numAll, CV_32FC1);
ann.predict(f, output);//使用ann对字符做判断
ann.predict(f, output);//使用ann对字符做判断
@ -160,7 +160,7 @@ int CCharsIdentify::classify(Mat f)
float val = output.at<float>(j);
//cout << "j:" << j << "val:"<< val << endl;
if (val > maxVal)
//求得中文字符权重最大的那个也就是通过ann认为最可能的字符
//求得中文字符权重最大的那个也就是通过ann认为最可能的字符
{
maxVal = val;
result = j;
@ -190,7 +190,7 @@ string CCharsIdentify::charsIdentify(Mat input)
{
Mat f = features(input, m_predictSize);
string result = "";
int index = classify(f);//使用ann来判别那个字符
int index = classify(f);//使用ann来判别那个字符
if (index >= numCharacter)
{
@ -208,12 +208,12 @@ string CCharsIdentify::charsIdentify(Mat input)
}
//输入当个字符Mat,生成字符的string
//输入当个字符Mat,生成字符的string
string CCharsIdentify::charsIdentify(Mat input, bool isChinese,bool isSpeci)
{
Mat f = features(input, m_predictSize);
string result = "";
int index = classify(f, isChinese,isSpeci);//使用ann来判别那个字符
int index = classify(f, isChinese,isSpeci);//使用ann来判别那个字符
if (!isChinese)
{

@ -23,7 +23,7 @@ namespace easypr{
}
int CCharsRecognise::charsRecognise(Mat plate, string& plateLicense, int index)
{
//车牌字符方块集合
//车牌字符方块集合
vector<Mat> matVec;
string plateIdentify = "";
@ -37,7 +37,7 @@ namespace easypr{
Mat charMat = matVec[j];
bool isChinses = false;
bool isSpeci=false;
//默认首个字符块是中文字符
//默认首个字符块是中文字符
if (j == 0)
isChinses = true;
if(j==1)

@ -14,7 +14,7 @@ namespace easypr{
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 @@ namespace easypr{
m_debug = DEFAULT_DEBUG;
}
//! 字符尺寸验证
//! 字符尺寸验证
bool CCharsSegment::verifyCharSizes(Mat r){
//Char sizes 45x90
float aspect = 45.0f / 90.0f;
@ -46,12 +46,12 @@ namespace easypr{
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;
@ -74,7 +74,7 @@ namespace easypr{
int staticIndex = 0;
int iTag = 0;
//! 字符分割与排序
//! 字符分割与排序
int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
{
if (!input.data)
@ -84,7 +84,7 @@ namespace easypr{
int h = input.rows;
Mat tmpMat = input(Rect(w*0.1,h*0.1,w*0.8,h*0.8));
//判断车牌颜色以此确认threshold方法
//判断车牌颜色以此确认threshold方法
Color plateType = getPlateType(tmpMat, true);
Mat input_grey;
@ -134,7 +134,7 @@ namespace easypr{
imwrite(ss.str(), img_threshold);
}
//去除车牌上方的柳钉以及下方的横线等干扰
//去除车牌上方的柳钉以及下方的横线等干扰
if(!clearLiuDing(img_threshold))
{
return -3;
@ -162,7 +162,7 @@ namespace easypr{
vector<Rect> vecRect;
//Remove patch that are no inside limits of aspect ratio and area.
//将不符合特定尺寸的图块排除出去
//将不符合特定尺寸的图块排除出去
while (itc != contours.end())
{
Rect mr = boundingRect(Mat(*itc));
@ -177,7 +177,7 @@ namespace easypr{
return -3;
vector<Rect> sortedRect;
////对符合尺寸的图块按照从左到右进行排序
////对符合尺寸的图块按照从左到右进行排序
SortRect(vecRect, sortedRect);
/*vector<Rect> sortedRect(vecRect);
@ -189,7 +189,7 @@ namespace easypr{
);*/
int specIndex = 0;
//获得指示城市的特定Rect,如苏A的"A"
//获得指示城市的特定Rect,如苏A的"A"
specIndex = GetSpecificRect(sortedRect);
if (m_debug)
@ -203,9 +203,9 @@ namespace easypr{
}
}
//根据特定Rect向左反推出中文字符
//这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect因此仅能
//退过特定算法来指定
//根据特定Rect向左反推出中文字符
//这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect因此仅能
//退过特定算法来指定
Rect chineseRect;
if (specIndex < sortedRect.size())
chineseRect = GetChineseRect(sortedRect[specIndex]);
@ -221,9 +221,9 @@ namespace easypr{
}
//新建一个全新的排序Rect
//将中文字符Rect第一个加进来因为它肯定是最左边的
//其余的Rect只按照顺序去6个车牌只可能是7个字符这样可以避免阴影导致的“1”字符
//新建一个全新的排序Rect
//将中文字符Rect第一个加进来因为它肯定是最左边的
//其余的Rect只按照顺序去6个车牌只可能是7个字符这样可以避免阴影导致的“1”字符
vector<Rect> newSortedRect;
newSortedRect.push_back(chineseRect);
RebuildRect(sortedRect, newSortedRect, specIndex);
@ -254,7 +254,7 @@ namespace easypr{
return 0;
}
//! 将Rect按位置从左到右进行排序
//! 将Rect按位置从左到右进行排序
int CCharsSegment::SortRect(const vector<Rect>& vecRect, vector<Rect>& out)
{
vector<int> orderIndex;
@ -298,7 +298,7 @@ namespace easypr{
return 0;
}
//! 根据特殊车牌来构造猜测中文字符的位置和大小
//! 根据特殊车牌来构造猜测中文字符的位置和大小
Rect CCharsSegment::GetChineseRect(const Rect rectSpe)
{
int height = rectSpe.height;
@ -314,7 +314,7 @@ namespace easypr{
return a;
}
//! 找出指示城市的字符的Rect例如苏A7003X就是"A"的位置
//! 找出指示城市的字符的Rect例如苏A7003X就是"A"的位置
int CCharsSegment::GetSpecificRect(const vector<Rect>& vecRect)
{
vector<int> xpositions;
@ -341,8 +341,8 @@ namespace easypr{
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))
{
@ -353,17 +353,17 @@ namespace easypr{
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里所有plate判断的通用函数
// 所属命名空间为easypr
// 这个部分中的函数轻易不要改动
// 这个文件定义了EasyPR里所有plate判断的通用函数
// 所属命名空间为easypr
// 这个部分中的函数轻易不要改动
#include "../include/prep.h"
#include "../include/core_func.h"
@ -10,30 +10,30 @@ Namespace where all the C++ EasyPR functionality resides
*/
namespace easypr {
//! 根据一幅图像与颜色模板获取对应的二值图
//! 输入RGB图像, 颜色模板(蓝色、黄色)
//! 输出灰度图只有0和255两个值255代表匹配0代表不匹配
//! 根据一幅图像与颜色模板获取对应的二值图
//! 输入RGB图像, 颜色模板(蓝色、黄色)
//! 输出灰度图只有0和255两个值255代表匹配0代表不匹配
Mat colorMatch(const Mat& src, Mat& match, const Color r, const bool adaptive_minsv)
{
// S和V的最小值由adaptive_minsv这个bool值判断
// 如果为true则最小值取决于H值按比例衰减
// 如果为false则不再自适应使用固定的最小值minabs_sv
// 默认为false
// S和V的最小值由adaptive_minsv这个bool值判断
// 如果为true则最小值取决于H值按比例衰减
// 如果为false则不再自适应使用固定的最小值minabs_sv
// 默认为false
const float max_sv = 255;
const float minref_sv = 64;
const float minabs_sv = 95;
//blue的H范围
//blue的H范围
const int min_blue = 100; //100
const int max_blue = 140; //140
//yellow的H范围
//yellow的H范围
const int min_yellow = 15; //15
const int max_yellow = 40; //40
Mat src_hsv;
// 转到HSV空间进行处理颜色搜索主要使用的是H分量进行蓝色与黄色的匹配工作
// 转到HSV空间进行处理颜色搜索主要使用的是H分量进行蓝色与黄色的匹配工作
cvtColor(src, src_hsv, CV_BGR2HSV);
vector<Mat> hsvSplit;
@ -41,7 +41,7 @@ namespace easypr {
equalizeHist(hsvSplit[2], hsvSplit[2]);
merge(hsvSplit, src_hsv);
//匹配模板基色,切换以查找想要的基色
//匹配模板基色,切换以查找想要的基色
int min_h = 0;
int max_h = 0;
switch (r) {
@ -60,10 +60,10 @@ namespace easypr {
int channels = src_hsv.channels();
int nRows = src_hsv.rows;
//图像数据列需要考虑通道数的影响;
//图像数据列需要考虑通道数的影响;
int nCols = src_hsv.cols * channels;
if (src_hsv.isContinuous())//连续存储的数据,按一行处理
if (src_hsv.isContinuous())//连续存储的数据,按一行处理
{
nCols *= nRows;
nRows = 1;
@ -99,9 +99,9 @@ namespace easypr {
float Hdiff_p = float(Hdiff) / diff_h;
// S和V的最小值由adaptive_minsv这个bool值判断
// 如果为true则最小值取决于H值按比例衰减
// 如果为false则不再自适应使用固定的最小值minabs_sv
// S和V的最小值由adaptive_minsv这个bool值判断
// 如果为true则最小值取决于H值按比例衰减
// 如果为false则不再自适应使用固定的最小值minabs_sv
float min_sv = 0;
if (true == adaptive_minsv)
min_sv = minref_sv - minref_sv / 2 * (1 - Hdiff_p); // inref_sv - minref_sv / 2 * (1 - Hdiff_p)
@ -124,7 +124,7 @@ namespace easypr {
//cout << "avg_s:" << s_all / count << endl;
//cout << "avg_v:" << v_all / count << endl;
// 获取颜色匹配后的二值灰度图
// 获取颜色匹配后的二值灰度图
Mat src_grey;
vector<Mat> hsvSplit_done;
split(src_hsv, hsvSplit_done);
@ -137,9 +137,9 @@ namespace easypr {
bool bFindLeftRightBound1(Mat& bound_threshold,int& posLeft,int& posRight)
{
//从两边寻找边界
//从两边寻找边界
int span = bound_threshold.rows*0.2;
//左边界检测
//左边界检测
for (int i=0; i < bound_threshold.cols-span-1;i+=3)
{
int whiteCount = 0;
@ -162,7 +162,7 @@ namespace easypr {
}
span = bound_threshold.rows*0.2;
//右边界检测
//右边界检测
for (int i=bound_threshold.cols-1; i > span;i-=2)
{
int whiteCount = 0;
@ -204,9 +204,9 @@ namespace easypr {
bool bFindLeftRightBound(Mat& bound_threshold,int& posLeft,int& posRight)
{
//从两边寻找边界
//从两边寻找边界
int span = bound_threshold.rows*0.2;
//左边界检测
//左边界检测
for (int i=0; i < bound_threshold.cols-span-1;i+=2)
{
int whiteCount = 0;
@ -229,7 +229,7 @@ namespace easypr {
}
span = bound_threshold.rows*0.2;
//右边界检测
//右边界检测
for (int i=bound_threshold.cols-1; i > span;i-=2)
{
int whiteCount = 0;
@ -262,9 +262,9 @@ namespace easypr {
bool bFindLeftRightBound2(Mat& bound_threshold,int& posLeft,int& posRight)
{
//从两边寻找边界
//从两边寻找边界
int span = bound_threshold.rows*0.2;
//左边界检测
//左边界检测
for (int i=0; i < bound_threshold.cols-span-1;i+=3)
{
int whiteCount = 0;
@ -287,7 +287,7 @@ namespace easypr {
}
span = bound_threshold.rows*0.2;
//右边界检测
//右边界检测
for (int i=bound_threshold.cols-1; i > span;i-=3)
{
int whiteCount = 0;
@ -318,12 +318,12 @@ namespace easypr {
}
//! 判断一个车牌的颜色
//! 输入车牌mat与颜色模板
//! 返回true或fasle
//! 判断一个车牌的颜色
//! 输入车牌mat与颜色模板
//! 返回true或fasle
bool plateColorJudge(const Mat& src, const Color r, const bool adaptive_minsv)
{
// 判断阈值
// 判断阈值
const float thresh = 0.45;
Mat src_gray;
@ -339,7 +339,7 @@ namespace easypr {
}
//getPlateType
//判断车牌的类型
//判断车牌的类型
Color getPlateType(const Mat& src, const bool adaptive_minsv)
{
if (plateColorJudge(src, BLUE, adaptive_minsv) == true) {
@ -370,7 +370,7 @@ namespace easypr {
if (img.at<char>(i, j) != img.at<char>(i, j + 1))
jumpCount++;
if (img.at<char>(i,j) == 255)
if (img.at<char>(i, j) == 255)
{
whiteCount++;
}
@ -394,9 +394,9 @@ namespace easypr {
}
}
//去除车牌上方的钮钉
//计算每行元素的阶跃数如果小于X认为是柳丁将此行全部填0涂黑
//X的推荐值为可根据实际调整
//去除车牌上方的钮钉
//计算每行元素的阶跃数如果小于X认为是柳丁将此行全部填0涂黑
//X的推荐值为可根据实际调整
bool clearLiuDing(Mat& img)
{
@ -431,7 +431,7 @@ namespace easypr {
}
}
////这样的不是车牌
////这样的不是车牌
if (iCount*1.0/img.rows < 0.5)
{
return false;
@ -491,7 +491,7 @@ namespace easypr {
}
//ok,找到上下边界
//ok,找到上下边界
for (int i = mask.rows-1; i >= mask.rows/2; i--)
{
int jumpCount = 0;
@ -572,7 +572,7 @@ namespace easypr {
return thresholdV;
}
//! 直方图均衡
//! 直方图均衡
Mat histeq(Mat in)
{
Mat out(in.size(), in.type());
@ -609,7 +609,7 @@ namespace easypr {
int numCols=vhist.cols+hhist.cols+lowData.cols*lowData.cols;
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++)
{
@ -675,7 +675,7 @@ namespace easypr {
}
}
// !获取垂直和水平方向直方图
// !获取垂直和水平方向直方图
Mat ProjectedHistogram(Mat img, int t)
{
int sz = (t) ? img.rows : img.cols;
@ -684,7 +684,7 @@ namespace easypr {
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
@ -692,7 +692,7 @@ namespace easypr {
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;
}

@ -11,7 +11,7 @@ CPlateDetect::CPlateDetect()
m_plateLocate = new CPlateLocate();
m_plateJudge = new CPlateJudge();
// 默认EasyPR在一幅图中定位最多3个车
// 默认EasyPR在一幅图中定位最多3个车
m_maxPlates = 3;
}
@ -22,7 +22,7 @@ void CPlateDetect::LoadSVM(string s)
int CPlateDetect::plateDetect(Mat src, vector<Mat>& resultVec, int index)
{
//可能是车牌的图块集合
//可能是车牌的图块集合
vector<Mat> matVec;
int resultLo = m_plateLocate->plateLocate(src, matVec);
@ -67,7 +67,7 @@ int CPlateDetect::plateDetectDeep(Mat src, vector<CPlate>& resultVec, bool showD
vector<CPlate> all_result_Plates;
//如果颜色查找找到n个以上包含n个的车牌就不再进行Sobel查找了。
//如果颜色查找找到n个以上包含n个的车牌就不再进行Sobel查找了。
const int color_find_max = m_maxPlates;
m_plateLocate->plateColorLocate(src, color_Plates, index);
@ -104,7 +104,7 @@ int CPlateDetect::plateDetectDeep(Mat src, vector<CPlate>& resultVec, bool showD
for (int i = 0; i < all_result_Plates.size(); i++)
{
// 把截取的车牌图像依次放到左上角
// 把截取的车牌图像依次放到左上角
CPlate plate = all_result_Plates[i];
resultVec.push_back(plate);
}

File diff suppressed because it is too large Load Diff

@ -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,14 +38,14 @@ CPlateRecognize::CPlateRecognize()
int CPlateRecognize::plateRecognize(Mat src, vector<string>& licenseVec,int index)
{
// 车牌方块集合
// 车牌方块集合
vector<CPlate> plateVec;
// 如果设置了Debug模式就依次显示所有的图片
// 如果设置了Debug模式就依次显示所有的图片
bool showDetectArea = getPDDebug();
showDetectArea=0;
// 进行深度定位使用颜色信息与二次Sobel
// 进行深度定位使用颜色信息与二次Sobel
int resultPD = plateDetectDeep(src, plateVec, showDetectArea, 0);
Mat result;
@ -64,10 +64,10 @@ int CPlateRecognize::plateRecognize(Mat src, vector<string>& licenseVec,int inde
Mat plate = item.getPlateMat();
//获取车牌颜色
//获取车牌颜色
string plateType = getPlateColor(plate);
//获取车牌号
//获取车牌号
string plateIdentify = "";
int resultCR = charsRecognise(plate, plateIdentify);
if (resultCR == 0)
@ -88,7 +88,7 @@ int CPlateRecognize::plateRecognize(Mat src, vector<string>& licenseVec,int inde
// CvScalar size(cvScalar(8,0.5,0.1));
// text.setFont(NULL, &size, NULL, &p); // 透明处理
// text.setFont(NULL, &size, NULL, &p); // 透明处理
// text.putText(result, license.c_str(), Point(width,height*(index+1)));
@ -107,14 +107,14 @@ int CPlateRecognize::plateRecognize(Mat src, vector<string>& licenseVec,int inde
for (int j = 0; j < 4; j++)
{
line(result, rect_points[j], rect_points[(j + 1) % 4], Scalar(255, 255, 0), 2, 8);
//颜色定位车牌,黄色方框
//颜色定位车牌,黄色方框
}
}
else
{
for( int j = 0; j < 4; j++ )
{
line(result, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,255), 2, 8 );//sobel定位车牌红色方框
line(result, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,255), 2, 8 );//sobel定位车牌红色方框
}
}

@ -24,34 +24,34 @@ class CCharsIdentify
public:
CCharsIdentify();
//! 字符鉴别
//! 字符鉴别
string charsIdentify(Mat, bool, bool);
string charsIdentify(Mat input);
//! 字符分类
//! 字符分类
int classify(Mat, bool,bool);
int classify(Mat f);
//! 装载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,34 +27,34 @@ namespace easypr {
public:
CCharsRecognise();
//! 字符分割与识别
//! 字符分割与识别
int charsRecognise(Mat, String&, int = 0);
string charsRecognise(Mat plate);
//! 装载ANN模型
//! 装载ANN模型
void LoadANN(string s);
//! 是否开启调试模式
//! 是否开启调试模式
inline void setCRDebug(int param){ m_charsSegment->setDebug(param); }
//! 获取调试模式状态
//! 获取调试模式状态
inline int getCRDebug(){ return m_charsSegment->getDebug(); }
//! 获得车牌颜色
//! 获得车牌颜色
inline string getPlateColor(Mat input) const
{
string color = "未知";
string color = "未知";
Color result = getPlateType(input, true);
if (BLUE == result)
color = "蓝牌";
color = "蓝牌";
if (YELLOW == 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); }
@ -63,10 +63,10 @@ namespace easypr {
inline float getWhitePercent() const { return m_charsSegment->getWhitePercent(); }
private:
//!字符分割
//!字符分割
CCharsSegment* m_charsSegment;
//! 字符识别
//! 字符识别
CCharsIdentify* m_charsIdentify;
};

@ -25,30 +25,30 @@ namespace easypr {
public:
CCharsSegment();
//! 字符分割
//! 字符分割
int charsSegment(Mat, vector<Mat>&);
//! 字符尺寸验证
//! 字符尺寸验证
bool verifyCharSizes(Mat r);
//! 字符预处理
//! 字符预处理
Mat preprocessChar(Mat in);
//! 根据特殊车牌来构造猜测中文字符的位置和大小
//! 根据特殊车牌来构造猜测中文字符的位置和大小
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; }
@ -57,38 +57,38 @@ namespace easypr {
inline void setWhitePercent(float param){ m_WhitePercent = param; }
inline float getWhitePercent() const { return m_WhitePercent; }
//! 是否开启调试模式常量默认0代表关闭
//! 是否开启调试模式常量默认0代表关闭
static const int DEFAULT_DEBUG = 1;
//! 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;
};

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

@ -29,27 +29,27 @@ class CPlateDetect
public:
CPlateDetect();
//! 车牌检测:车牌定位与判断
//! 车牌检测:车牌定位与判断
int plateDetect(Mat, vector<Mat>&, int index = 0);
//! 深度车牌检测使用颜色与二次Sobel法综合
//! 深度车牌检测使用颜色与二次Sobel法综合
int plateDetectDeep(Mat src, vector<CPlate>& resultVec, bool showDetectArea = true, int index = 0);
int showResult(const Mat& result);
//! 装载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();}
@ -73,13 +73,13 @@ public:
inline float getMaxPlates() const { return m_maxPlates; }
private:
//! 设置一幅图中最多有多少车牌
//! 设置一幅图中最多有多少车牌
int m_maxPlates;
//! 车牌定位
//! 车牌定位
CPlateLocate* m_plateLocate;
//! 车牌判断
//! 车牌判断
CPlateJudge* m_plateJudge;
};

@ -30,66 +30,66 @@ public:
enum LocateType { SOBEL, COLOR };
//! Sobel第一次搜索
//! 不限制大小和形状获取的BoundRect进入下一步
//! Sobel第一次搜索
//! 不限制大小和形状获取的BoundRect进入下一步
int sobelFrtSearch(const Mat& src, vector<Rect_<float>>& outRects);
//! Sobel第二次搜索
//! 对大小和形状做限制,生成参考坐标
//! Sobel第二次搜索
//! 对大小和形状做限制,生成参考坐标
int sobelSecSearch( Mat& bound, Point2f refpoint, vector<RotatedRect>& outRects);
int sobelSecSearchPart( Mat& bound, Point2f refpoint, vector<RotatedRect>& outRects);
//! 抗扭斜处理
//! 抗扭斜处理
int deskew(const Mat& src, const Mat& src_b, vector<RotatedRect>& inRects, vector<CPlate>& outPlates);
//! 是否偏斜
//! 输入二值化图像,输出判断结果
//! 是否偏斜
//! 输入二值化图像,输出判断结果
bool isdeflection(const Mat& in, const double angle, double& slope);
//! Sobel运算
//! 输入彩色图像,输出二值化图像
//! Sobel运算
//! 输入彩色图像,输出二值化图像
int sobelOper(const Mat& in, Mat& out, int blurSize, int morphW, int morphH);
//! 计算一个安全的Rect
//! 计算一个安全的Rect
bool calcSafeRect(const RotatedRect& roi_rect, const Mat& src, Rect_<float>& safeBoundRect);
//! 旋转操作
//! 旋转操作
bool rotation(Mat& in, Mat& out, const Size rect_size, const Point2f center, const double angle);
//! 扭变操作
//! 扭变操作
void affine(const Mat& in, Mat& out, const double slope);
//! 颜色定位法
//! 颜色定位法
int plateColorLocate(Mat src, vector<CPlate>& candPlates, int index = 0);
//! Sobel定位法
//! Sobel定位法
int plateSobelLocate(Mat src, vector<CPlate>& candPlates, int index = 0);
int sobelOperT(const Mat& in, Mat& out, int blurSize, int morphW, int morphH);
//! Color搜索
//! Color搜索
int colorSearch(const Mat& src, const Color r, Mat& out, vector<RotatedRect>& outRects, int index = 0);
//! 未使用函数与代码
//! 开始------------
//! 未使用函数与代码
//! 开始------------
bool sobelJudge(Mat roi);
int deskewOld(Mat src, vector<RotatedRect>& inRects, vector<RotatedRect>& outRects, vector<Mat>& outMats, LocateType locateType);
bool verifyCharSizes(Mat r);
//! 结束------------
//! 未使用函数与代码
//! 结束------------
//! 未使用函数与代码
//! 车牌定位
//! 车牌定位
int plateLocate(Mat, vector<Mat>&, int = 0 );
//! 车牌的尺寸验证
//! 车牌的尺寸验证
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;}
@ -109,13 +109,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;
@ -125,39 +125,39 @@ public:
static const int DEFAULT_MORPH_SIZE_WIDTH = 17;//17
static const int DEFAULT_MORPH_SIZE_HEIGHT = 3;//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 = 1;//3
static const int DEFAULT_VERIFY_MAX = 24;//20
//! 角度判断所用常量
//! 角度判断所用常量
static const int DEFAULT_ANGLE = 60;//30
//! 是否开启调试模式常量默认0代表关闭
//! 是否开启调试模式常量默认0代表关闭
static const int DEFAULT_DEBUG = 1;
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;
LabInfo * m_labItem;

@ -27,39 +27,39 @@ class CPlateRecognize : public CPlateDetect, public CCharsRecognise
public:
CPlateRecognize();
//! 车牌检测与字符识别
//! 车牌检测与字符识别
int plateRecognize(Mat, vector<string>&, int index = 0);
//! 生活模式与工业模式切换
//! 生活模式与工业模式切换
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;
};

File diff suppressed because it is too large Load Diff

@ -1,4 +1,4 @@
// ann_train.cpp : ann模型的训练文件主要用在OCR中
// ann_train.cpp : ann模型的训练文件主要用在OCR中
#include <opencv/cv.h>
#include <opencv/cvaux.h>
@ -33,30 +33,30 @@ using namespace easypr;
CvANN_MLP ann;
//中国车牌
//中国车牌
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和O,10个数字与24个英文字符之和 */
const int numCharacter = 34; /* 没有I和O,10个数字与24个英文字符之和 */
const int numNeurons = 20;
const int predictSize = 10;
//以下都是我训练时用到的中文字符数据,并不全面,有些省份没有训练数据所以没有字符
//有些后面加数字2的表示在训练时常看到字符的一种变形也作为训练数据存储
//以下都是我训练时用到的中文字符数据,并不全面,有些省份没有训练数据所以没有字符
//有些后面加数字2的表示在训练时常看到字符的一种变形也作为训练数据存储
const string strChinese[] = {
"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" /* 浙 */};
"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" /* 浙 */};
const int numChinese = 31;
const int numAll = 65; /* 34+20=54 */
@ -145,7 +145,7 @@ int saveTrainData()
trainingDataf10.push_back(f10);
trainingDataf15.push_back(f15);
trainingDataf20.push_back(f20);
trainingLabels.push_back(i); //每一幅字符图片所对应的字符类别索引下标
trainingLabels.push_back(i); //每一幅字符图片所对应的字符类别索引下标
}
}
@ -245,7 +245,7 @@ int annMain()
saveTrainData();
//可根据需要训练不同的predictSize或者neurons的ANN模型
//可根据需要训练不同的predictSize或者neurons的ANN模型
//for (int i = 2; i <= 2; i ++)
//{
// int size = i * 5;
@ -256,8 +256,8 @@ int annMain()
// }
//}
//这里演示只训练model文件夹下的ann.xml此模型是一个predictSize=10,neurons=40的ANN模型。
//根据机器的不同训练时间不一样但一般需要10分钟左右所以慢慢等一会吧。
//这里演示只训练model文件夹下的ann.xml此模型是一个predictSize=10,neurons=40的ANN模型。
//根据机器的不同训练时间不一样但一般需要10分钟左右所以慢慢等一会吧。
saveModel(10, 40);
cout << "To be end." << endl;

@ -1,29 +1,29 @@
// learn data_prepare :
// 生成learn data的cpplearn data指的是train dataverify data test data的总和这个名字是我起的。
// learn data应该是贴好标签的数据因此即便通过EasyPR自动化处理以后也要人为的修正一下.
// 生成learn data的cpplearn data指的是train dataverify data test data的总和这个名字是我起的。
// learn data应该是贴好标签的数据因此即便通过EasyPR自动化处理以后也要人为的修正一下.
// 你应该按照如下的步骤和顺序组织learn data
// 1.用EasyPR对not label data进行处理通过EasyPR辅助来对车牌图片进行标签放到不同文件夹下
// 2.标签分两种,一种是有车牌的,一种是无车牌的;
// 2.EasyPR生成标签以后你还得需要肉眼确认下将被不正确标签的数据转移到它们该去的文件夹下
// 3.通过上面的步骤正确的车牌图片和非车牌图片已经被分别放到两个文件下假设是hasplate和noplate
// 4.将这两个文件夹放到EasyPR目录train/data/plate_detect_svm/learn下面
// 5.运行EasyPR选择“训练”目录下的“车牌检测not divide这个程序会自动把learn data分块训练测试
// 你应该按照如下的步骤和顺序组织learn data
// 1.用EasyPR对not label data进行处理通过EasyPR辅助来对车牌图片进行标签放到不同文件夹下
// 2.标签分两种,一种是有车牌的,一种是无车牌的;
// 2.EasyPR生成标签以后你还得需要肉眼确认下将被不正确标签的数据转移到它们该去的文件夹下
// 3.通过上面的步骤正确的车牌图片和非车牌图片已经被分别放到两个文件下假设是hasplate和noplate
// 4.将这两个文件夹放到EasyPR目录train/data/plate_detect_svm/learn下面
// 5.运行EasyPR选择“训练”目录下的“车牌检测not divide这个程序会自动把learn data分块训练测试
#include "../include/plate_recognize.h"
#include "../include/util.h"
using namespace easypr;
//! 将以下路径改成你的位置
//! 将以下路径改成你的位置
const char * notlabelPath = "F:/data/easypr-data/notlabel";
const char * hasPaltePath = "F:/data/easypr-data/learn/hasPlate/";
const char * noPlatePath = "F:/data/easypr-data/learn/noPlate/";
//! 读取not label data生成learn data
//! 读取not label data生成learn data
void label_data()
{
////获取该路径下的所有文件
////获取该路径下的所有文件
auto files = Utils::getFiles(notlabelPath);
CPlateLocate lo;

Loading…
Cancel
Save