Convert all source file encoding to gb2312.

1.3
Micooz 12 years ago
parent 4cea45c004
commit a0dd498ce2

@ -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为蓝牌,否则为黄牌
PlateColor CCharsSegment::getPlateType(Mat input)
{
Mat img;
@ -129,9 +129,9 @@ PlateColor CCharsSegment::getPlateType(Mat input)
}
//clearLiuDing
//去除车牌上方的钮钉
//计算每行元素的阶跃数如果小于X认为是柳丁将此行全部填0涂黑
//X的推荐值为可根据实际调整
//去除车牌上方的钮钉
//计算每行元素的阶跃数如果小于X认为是柳丁将此行全部填0涂黑
//X的推荐值为可根据实际调整
void CCharsSegment::clearLiuDing(Mat &img)
{
int *jump = new int[img.rows];
@ -144,7 +144,7 @@ void CCharsSegment::clearLiuDing(Mat &img)
jump[i]++;
}
if (jump[i] <= m_LiuDingSize) {
// 将此行涂黑
// 将此行涂黑
for (int k = 0; k < img.rows; ++k) {
img.at<char>(i, k) = 0;
}
@ -155,13 +155,13 @@ void CCharsSegment::clearLiuDing(Mat &img)
jump = nullptr;
}
//! 字符分割与排序
//! 字符分割与排序
int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
{
if( !input.data )
{ return -3; }
//判断车牌颜色以此确认threshold方法
//判断车牌颜色以此确认threshold方法
PlateColor plateType = getPlateType(input);
cvtColor(input, input, CV_RGB2GRAY);
@ -179,7 +179,7 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
imwrite(ss.str(), img_threshold);
}
//去除车牌上方的柳钉以及下方的横线等干扰
//去除车牌上方的柳钉以及下方的横线等干扰
clearLiuDing(img_threshold);
@ -205,7 +205,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));
@ -221,13 +221,13 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
return -3;
vector<Rect> sortedRect(vecRect);
//对符合尺寸的图块按照从左到右进行排序
//对符合尺寸的图块按照从左到右进行排序
std::sort(sortedRect.begin(), sortedRect.end(), [] (const Rect &r1, const Rect &r2) {
return r1.x < r2.x;
});
int specIndex = 0;
//获得指示城市的特定Rect,如苏A的"A"
//获得指示城市的特定Rect,如苏A的"A"
specIndex = GetSpecificRect(sortedRect);
if(m_debug)
@ -241,9 +241,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]);
@ -259,9 +259,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);
@ -290,7 +290,7 @@ int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
return 0;
}
//! 根据特殊车牌来构造猜测中文字符的位置和大小
//! 根据特殊车牌来构造猜测中文字符的位置和大小
Rect CCharsSegment::GetChineseRect(const Rect rectSpe)
{
int height = rectSpe.height;
@ -306,7 +306,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;
@ -333,7 +333,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))
{
@ -344,12 +344,12 @@ 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 (size_t i = specIndex; i < vecRect.size() && count; ++i, --count) {

@ -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;
@ -114,10 +114,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;
@ -130,7 +130,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 );
@ -200,11 +200,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;
@ -253,10 +253,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];
@ -273,7 +273,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 (PlateColor::Blue == result)
color = "蓝牌";
color = "蓝牌";
if (PlateColor::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);}
@ -61,10 +61,10 @@ public:
inline float getWhitePercent() const { return m_charsSegment->getWhitePercent();}
private:
//!字符分割
//!字符分割
CCharsSegment* m_charsSegment;
//! 字符识别
//! 字符识别
CCharsIdentify* m_charsIdentify;
};

@ -30,42 +30,42 @@ 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);
//! 获得车牌颜色
//! 获得车牌颜色
PlateColor getPlateType(Mat input);
//! 去除影响字符识别的柳钉
//! 去除影响字符识别的柳钉
void 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);
//! 设置变量
//! 设置变量
inline void setLiuDingSize(int param){ m_LiuDingSize = param;}
inline void setColorThreshold(int param){ m_ColorThreshold = param;}
@ -74,38 +74,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;
};

@ -35,11 +35,11 @@ namespace easypr {
}
//C++的获取文件夹函数
//C++的获取文件夹函数
void getFiles(std::string path, std::vector<std::string>& files);
//! 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();
@ -58,32 +58,32 @@ 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 std::string&);
/// mc_data_prepare.cpp中方法
/// mc_data_prepare.cpp中方法
void getLearnData();
void Code2Province(const std::string& code, std::string& province);
void changeFileName();
void getPlateLicense(const std::string& filepath, std::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

File diff suppressed because it is too large Load Diff

@ -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,12 +53,12 @@ int acurayTest(const string& test_path)
string filepath = files[i].c_str();
cout << "------------------" << endl;
// 获取真实的车牌
// 获取真实的车牌
string plateLicense = Utils::getFileName(filepath);
cout << "原牌:" << plateLicense << endl;
cout << "原牌:" << plateLicense << endl;
// EasyPR开始判断车牌
// EasyPR开始判断车牌
Mat src = imread(filepath);
vector<string> plateVec;
int result = pr.plateRecognize(src, plateVec);
@ -68,20 +68,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 = Utils::splitString(colorplate, ':');
int size = spilt_plate.size();
@ -93,34 +93,34 @@ 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 = Utils::splitString(colorplate, ':');
int size = spilt_plate.size();
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;
@ -131,7 +131,7 @@ int acurayTest(const string& test_path)
}
else
{
cout << "错误码:" << result << endl;
cout << "错误码:" << result << endl;
count_err++;
}
count_all++;
@ -141,21 +141,21 @@ 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;
float count_norate = 1 - count_rate;
cout << "识出率:" << count_rate * 100 << "% " << endl;
cout << "识出率:" << count_rate * 100 << "% " << 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;

@ -20,21 +20,21 @@ int test_plate_recognize();
int testMain();
//把你要测试的图片地址写在下面
//把你要测试的图片地址写在下面
const string test_img = "";
const string testOption[] =
{
"1. test plate_locate(车牌定位);" /* 车牌定位 */,
"2. test plate_judge(车牌判断);" /* 车牌判断 */,
"3. test plate_detect(车牌检测);" /* 车牌检测(包含车牌定位与车牌判断) */,
"4. test chars_segment(字符分隔);" /* 字符分隔 */,
"5. test chars_identify(字符鉴别);" /* 字符鉴别 */,
"6. test chars_recognise(字符识别);" /* 字符识别(包含字符分隔与字符鉴别) */,
"7. test plate_recognize(车牌识别);" /* 车牌识别 */,
"8. test all(测试全部);" /* 以上全部 */,
"9. 返回;" /* 退出 */,
"1. test plate_locate(车牌定位);" /* 车牌定位 */,
"2. test plate_judge(车牌判断);" /* 车牌判断 */,
"3. test plate_detect(车牌检测);" /* 车牌检测(包含车牌定位与车牌判断) */,
"4. test chars_segment(字符分隔);" /* 字符分隔 */,
"5. test chars_identify(字符鉴别);" /* 字符鉴别 */,
"6. test chars_recognise(字符识别);" /* 字符识别(包含字符分隔与字符鉴别) */,
"7. test plate_recognize(车牌识别);" /* 车牌识别 */,
"8. test all(测试全部);" /* 以上全部 */,
"9. 返回;" /* 退出 */,
};
const int testOptionCount = 9;
@ -54,7 +54,7 @@ int testMain()
cout << "////////////////////////////////////"<< endl;
cout << selectOption.str();
cout << "////////////////////////////////////"<< endl;
cout << "请选择一项操作:";
cout << "请选择一项操作:";
int select = -1;
bool isRepeat = true;
@ -100,7 +100,7 @@ int testMain()
isExit = true;
break;
default:
cout << "输入错误,请重新输入:";
cout << "输入错误,请重新输入:";
isRepeat = true;
break;
}
@ -144,10 +144,10 @@ int test_plate_judge()
Mat src = imread("image/plate_judge.jpg");
//可能是车牌的图块集合
//可能是车牌的图块集合
vector<Mat> matVec;
//经过SVM判断后得到的图块集合
//经过SVM判断后得到的图块集合
vector<Mat> resultVec;
CPlateLocate lo;
@ -240,7 +240,7 @@ int test_chars_identify()
Mat resultMat = resultVec[j];
bool isChinses = false;
//默认首个字符块是中文字符
//默认首个字符块是中文字符
if (j == 0)
isChinses = true;
@ -249,7 +249,7 @@ int test_chars_identify()
}
}
const string plateLicense = "苏E771H6";
const string plateLicense = "苏E771H6";
cout << "plateLicense: " << plateLicense << endl;
cout << "plateIdentify: " << plateIdentify << endl;

@ -1,4 +1,4 @@
// ann_train.cpp : ann模型的训练文件主要用在OCR中
// ann_train.cpp : ann模型的训练文件主要用在OCR中
#include <opencv/cv.h>
#include <opencv/cvaux.h>
@ -33,21 +33,21 @@ 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个英文字符之和 */
//以下都是我训练时用到的中文字符数据,并不全面,有些省份没有训练数据所以没有字符
//有些后面加数字2的表示在训练时常看到字符的一种变形也作为训练数据存储
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" /* 浙 */};
//以下都是我训练时用到的中文字符数据,并不全面,有些省份没有训练数据所以没有字符
//有些后面加数字2的表示在训练时常看到字符的一种变形也作为训练数据存储
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 */
@ -68,7 +68,7 @@ Mat features(Mat in, int sizeData){
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++)
{
@ -157,7 +157,7 @@ int saveTrainData()
trainingDataf10.push_back(f10);
trainingDataf15.push_back(f15);
trainingDataf20.push_back(f20);
trainingLabels.push_back(i); //每一幅字符图片所对应的字符类别索引下标
trainingLabels.push_back(i); //每一幅字符图片所对应的字符类别索引下标
}
}
@ -257,7 +257,7 @@ int annMain()
saveTrainData();
//可根据需要训练不同的predictSize或者neurons的ANN模型
//可根据需要训练不同的predictSize或者neurons的ANN模型
//for (int i = 2; i <= 2; i ++)
//{
// int size = i * 5;
@ -268,8 +268,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,4 +1,4 @@
// svm_train.cpp : svm模型的训练文件主要用在plate_detect中
// svm_train.cpp : svm模型的训练文件主要用在plate_detect中
#include "../include/plate_recognize.h"
#include "../include/features.h"
@ -15,7 +15,7 @@ void learn2HasPlate(float bound = 0.7)
const char * filePath = "train/data/plate_detect_svm/learn/HasPlate";
vector<string> files;
////获取该路径下的所有文件
////获取该路径下的所有文件
getFiles(filePath, files );
int size = files.size();
@ -23,7 +23,7 @@ void learn2HasPlate(float bound = 0.7)
cout << "File not found in " << filePath << endl;
return;
}
////随机选取70%作为训练数据30%作为测试数据
////随机选取70%作为训练数据30%作为测试数据
srand(unsigned(time(NULL)));
random_shuffle(files.begin(), files.end());
@ -62,14 +62,14 @@ void learn2NoPlate(float bound = 0.7)
const char * filePath = "train/data/plate_detect_svm/learn/NoPlate";
vector<string> files;
////获取该路径下的所有文件
////获取该路径下的所有文件
getFiles(filePath, files );
int size = files.size();
if (0 == size) {
cout << "File not found in " << filePath << endl;
return;
}
////随机选取70%作为训练数据30%作为测试数据
////随机选取70%作为训练数据30%作为测试数据
srand(unsigned(time(NULL)));
random_shuffle(files.begin(), files.end());
@ -109,7 +109,7 @@ void getHasPlateTrain(Mat& trainingImages, vector<int>& trainingLabels,
const char * filePath = "train/data/plate_detect_svm/train/HasPlate";
vector<string> files;
////获取该路径下的所有文件
////获取该路径下的所有文件
getFiles(filePath, files );
int size = files.size();
@ -123,7 +123,7 @@ void getHasPlateTrain(Mat& trainingImages, vector<int>& trainingLabels,
//cout << files[i].c_str() << endl;
Mat img = imread(files[i].c_str());
//调用回调函数决定特征
//调用回调函数决定特征
Mat features;
getFeatures(img, features);
features = features.reshape(1, 1);
@ -141,7 +141,7 @@ void getNoPlateTrain(Mat& trainingImages, vector<int>& trainingLabels,
const char * filePath = "train/data/plate_detect_svm/train/NoPlate";
vector<string> files;
////获取该路径下的所有文件
////获取该路径下的所有文件
getFiles(filePath, files );
int size = files.size();
@ -155,7 +155,7 @@ void getNoPlateTrain(Mat& trainingImages, vector<int>& trainingLabels,
//cout << files[i].c_str() << endl;
Mat img = imread(files[i].c_str());
//调用回调函数决定特征
//调用回调函数决定特征
Mat features;
getFeatures(img, features);
features = features.reshape(1, 1);
@ -171,7 +171,7 @@ void getHasPlateTest(vector<Mat>& testingImages, vector<int>& testingLabels)
const char * filePath = "train/data/plate_detect_svm/test/HasPlate";
vector<string> files;
////获取该路径下的所有文件
////获取该路径下的所有文件
getFiles(filePath, files );
int size = files.size();
@ -196,7 +196,7 @@ void getNoPlateTest(vector<Mat>& testingImages, vector<int>& testingLabels)
const char * filePath = "train/data/plate_detect_svm/test/NoPlate";
vector<string> files;
////获取该路径下的所有文件
////获取该路径下的所有文件
getFiles(filePath, files );
int size = files.size();
@ -216,7 +216,7 @@ void getNoPlateTest(vector<Mat>& testingImages, vector<int>& testingLabels)
}
//! 测试SVM的准确率回归率以及FScore
//! 测试SVM的准确率回归率以及FScore
void getAccuracy(Mat& testingclasses_preditc, Mat& testingclasses_real)
{
int channels = testingclasses_preditc.channels();
@ -318,13 +318,13 @@ int svmTrain(bool dividePrepared = true, bool trainPrepared = true,
if (dividePrepared == false)
{
//分割learn里的数据到train和test里
//分割learn里的数据到train和test里
cout << "Divide learn to train and test" << endl;
learn2HasPlate();
learn2NoPlate();
}
//将训练数据加载入内存
//将训练数据加载入内存
if (trainPrepared == false)
{
cout << "Begin to get train data to memory" << endl;
@ -340,7 +340,7 @@ int svmTrain(bool dividePrepared = true, bool trainPrepared = true,
vector<Mat> testingImages;
vector<int> testingLabels_real;
//将测试数据加载入内存
//将测试数据加载入内存
cout << "Begin to get test data to memory" << endl;
getHasPlateTest(testingImages, testingLabels_real);
getNoPlateTest(testingImages, testingLabels_real);
@ -350,8 +350,8 @@ int svmTrain(bool dividePrepared = true, bool trainPrepared = true,
{
CvSVMParams SVM_params;
SVM_params.svm_type = CvSVM::C_SVC;
//SVM_params.kernel_type = CvSVM::LINEAR; //CvSVM::LINEAR; 线型,也就是无核
SVM_params.kernel_type = CvSVM::RBF; //CvSVM::RBF 径向基函数,也就是高斯核
//SVM_params.kernel_type = CvSVM::LINEAR; //CvSVM::LINEAR; 线型,也就是无核
SVM_params.kernel_type = CvSVM::RBF; //CvSVM::RBF 径向基函数,也就是高斯核
SVM_params.degree = 0.1;
SVM_params.gamma = 1;
SVM_params.coef0 = 0.1;
@ -407,7 +407,7 @@ int svmTrain(bool dividePrepared = true, bool trainPrepared = true,
//cout << files[i].c_str() << endl;
Mat p = testingImages[i];
//调用回调函数决定特征
//调用回调函数决定特征
Mat features;
getFeatures(p, features);

@ -1,9 +1,9 @@
//
// main.cpp
// 人脸马赛克
// 人脸马赛克
//
// Created by zhou shiwei on 15/1/20.
// Copyright (c) 2015年 zhou shiwei. All rights reserved.
// Copyright (c) 2015年 zhou shiwei. All rights reserved.
//
// Modified by liu ruoze on 15/1/23
@ -15,9 +15,9 @@
#include <iostream>
#include <string>
// 反人脸识别文件
// 在发布数据到general_test数据集里请先用这里的方法对图像进行处理
// EasyPR开源项目非常注重保护图片中驾驶人的隐私
// 反人脸识别文件
// 在发布数据到general_test数据集里请先用这里的方法对图像进行处理
// EasyPR开源项目非常注重保护图片中驾驶人的隐私
#include "../include/plate_recognize.h"
#include "../include/util.h"
@ -29,9 +29,9 @@ using namespace cv;
Mat detectAndMaskFace(Mat& img, CascadeClassifier& cascade,
double scale );
// 反人脸识别函数
// 在发布数据到general_test数据集里请先用这里的方法对图像进行处理
// EasyPR开源项目非常注重保护图片中驾驶人的隐私
// 反人脸识别函数
// 在发布数据到general_test数据集里请先用这里的方法对图像进行处理
// EasyPR开源项目非常注重保护图片中驾驶人的隐私
int deface()
{
CascadeClassifier cascade;

@ -1,6 +1,6 @@
// 辅助生成general_test中的图片
// 通用做法是使用easypr依次读取图片并用其中的一个车牌识别文字给图片重命名
// easypr识别的文字不一定准确因此需要人再次确认与手工调整下
// 辅助生成general_test中的图片
// 通用做法是使用easypr依次读取图片并用其中的一个车牌识别文字给图片重命名
// easypr识别的文字不一定准确因此需要人再次确认与手工调整下
#include "../include/plate_recognize.h"
#include "../include/util.h"
@ -10,15 +10,15 @@ using namespace easypr;
extern const string GENERAL_TEST_PATH;
// TODO 将下面的路径改成你的
// TODO 将下面的路径改成你的
const string src_path = "F:/data/easypr-data/tmp-5";
// TODO 将下面的路径改成你的
// TODO 将下面的路径改成你的
const string dst_path = "F:/data/easypr-data/tmp-6";
int general_test()
{
////获取该路径下的所有文件
////获取该路径下的所有文件
vector<string> files;
getFiles(src_path, files);
@ -46,7 +46,7 @@ int general_test()
string filepath = files[i].c_str();
cout << "------------------" << endl;
// EasyPR开始判断车牌
// EasyPR开始判断车牌
Mat src = imread(filepath);
vector<string> plateVec;
@ -57,14 +57,14 @@ int general_test()
if (num == 0)
{
cout << ""<< "无车牌" <<endl;
cout << ""<< "无车牌" <<endl;
}
else
{
cout << plateVec[0] <<endl;
string colorplate = plateVec[0];
// 输出"蓝牌:苏E7KU22"中冒号后面的车牌
// 输出"蓝牌:苏E7KU22"中冒号后面的车牌
vector<string> spilt_plate = Utils::splitString(colorplate, ':');
int size = spilt_plate.size();
@ -78,7 +78,7 @@ int general_test()
}
else
{
cout << "错误码:" << result << endl;
cout << "错误码:" << result << endl;
}
}

@ -1,7 +1,7 @@
// 生成GDTS的文件
// 在捐赠数据到GDTS数据集里请先用这里的方法对图像进行预处理
// EasyPR开源项目非常注重保护原始图片的版权
// 所有的捐赠数据通过GDSL协议进行约定保证使用人仅用于非商业性目的
// 生成GDTS的文件
// 在捐赠数据到GDTS数据集里请先用这里的方法对图像进行预处理
// EasyPR开源项目非常注重保护原始图片的版权
// 所有的捐赠数据通过GDSL协议进行约定保证使用人仅用于非商业性目的
#include "../include/plate_recognize.h"
#include "../include/util.h"
@ -9,15 +9,15 @@
using namespace easypr;
// TODO 将下面的路径改成你的原始图片路径
// 图片不要多10-30张就足够了EasyPR对GDTS数据集的使用不以量为主要指标
// 只要这些图片足够反映你数据集的主要特征即可
// TODO 将下面的路径改成你的原始图片路径
// 图片不要多10-30张就足够了EasyPR对GDTS数据集的使用不以量为主要指标
// 只要这些图片足够反映你数据集的主要特征即可
const string src_path = "F:/data/easypr-data/tmp-1";
// TODO 将下面的路径改成你希望生成捐赠给GDTS数据存放的新路径
// TODO 将下面的路径改成你希望生成捐赠给GDTS数据存放的新路径
const string dst_path = "F:/data/easypr-data/tmp-2";
// EasyPR的图像预处理函数进行模糊化与裁剪化处理
// EasyPR的图像预处理函数进行模糊化与裁剪化处理
Mat imageProcess(Mat src);
Mat detectAndMaskFace(Mat& img, CascadeClassifier& cascade,
@ -25,12 +25,12 @@ Mat detectAndMaskFace(Mat& img, CascadeClassifier& cascade,
int generate_gdts()
{
// 获取人脸识别文件
// 获取人脸识别文件
CascadeClassifier cascade;
//string cascadeName="/Users/zhoushiwei/Dropbox/Avatar/SDMLIB/haarcascade_frontalface_alt2.xml";
string cascadeName="model/haarcascade_frontalface_alt_tree.xml";
////获取该路径下的所有文件
////获取该路径下的所有文件
vector<string> files;
getFiles(src_path, files);
int size = files.size();
@ -49,16 +49,16 @@ int generate_gdts()
cout << "------------------" << endl;
cout << filepath << endl;
// EasyPR读取原图片
// EasyPR读取原图片
Mat src = imread(filepath);
// EasyPR开始对图片进行模糊化与裁剪化处理
// EasyPR开始对图片进行模糊化与裁剪化处理
Mat img = imageProcess(src);
// EasyPR开始对图片进行人脸识别处理
// EasyPR开始对图片进行人脸识别处理
Mat dst = detectAndMaskFace(img, cascade, 1.5);
// 将图片导出到新路径
// 将图片导出到新路径
vector<string> spilt_path = Utils::splitString(filepath, '\\');
int spiltsize = spilt_path.size();
@ -110,7 +110,7 @@ int generate_gdts()
// EasyPR的图像预处理函数进行模糊化与裁剪化处理
// EasyPR的图像预处理函数进行模糊化与裁剪化处理
Mat imageProcess(Mat img)
{
int width = img.size().width;

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

Loading…
Cancel
Save