diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ac98151 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 2.6) + +project (EasyPR) + +list(APPEND CMAKE_CXX_FLAGS "-std=c++0x") + +find_package(OpenCV REQUIRED) + +aux_source_directory(./src SOURCE_FILES) + +set(SOURCE_FILES + src/main.cpp + src/core/chars_identify.cpp + src/core/chars_recognise.cpp + src/core/chars_segment.cpp + src/core/features.cpp + src/core/plate_detect.cpp + src/core/plate_judge.cpp + src/core/plate_locate.cpp + src/core/plate_recognize.cpp + src/test/accuracy_test.cpp + src/test/test.cpp + src/train/ann_train.cpp + src/train/svm_train.cpp + src/util/deface.cpp + src/util/general_test_prepare.cpp + src/util/generate_gdts.cpp + src/util/learn_prepare.cpp + src/util/mc_data_prepare.cpp + src/util/util.cpp +) + +add_executable(EasyPR ${SOURCE_FILES}) +target_link_libraries(EasyPR ${OpenCV_LIBS}) \ No newline at end of file diff --git a/src/core/chars_identify.cpp b/src/core/chars_identify.cpp index 1886d50..b2ffff5 100644 --- a/src/core/chars_identify.cpp +++ b/src/core/chars_identify.cpp @@ -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("zh_cuan","川")); - m_map.insert(pair("zh_e","鄂")); - m_map.insert(pair("zh_gan","赣")); - m_map.insert(pair("zh_hei","黑")); - m_map.insert(pair("zh_hu","沪")); - m_map.insert(pair("zh_ji","冀")); - m_map.insert(pair("zh_jl","吉")); - m_map.insert(pair("zh_jin","津")); - m_map.insert(pair("zh_jing","京")); - m_map.insert(pair("zh_shan","陕")); - m_map.insert(pair("zh_liao","辽")); - m_map.insert(pair("zh_lu","鲁")); - m_map.insert(pair("zh_min","闽")); - m_map.insert(pair("zh_ning","宁")); - m_map.insert(pair("zh_su","苏")); - m_map.insert(pair("zh_sx","晋")); - m_map.insert(pair("zh_wan","皖")); - m_map.insert(pair("zh_yu","豫")); - m_map.insert(pair("zh_yue","粤")); - m_map.insert(pair("zh_zhe","浙")); + m_map.insert(pair("zh_cuan","宸")); + m_map.insert(pair("zh_e","閯")); + m_map.insert(pair("zh_gan","璧")); + m_map.insert(pair("zh_hei","榛")); + m_map.insert(pair("zh_hu","娌")); + m_map.insert(pair("zh_ji","鍐")); + m_map.insert(pair("zh_jl","鍚")); + m_map.insert(pair("zh_jin","娲")); + m_map.insert(pair("zh_jing","浜")); + m_map.insert(pair("zh_shan","闄")); + m_map.insert(pair("zh_liao","杈")); + m_map.insert(pair("zh_lu","椴")); + m_map.insert(pair("zh_min","闂")); + m_map.insert(pair("zh_ning","瀹")); + m_map.insert(pair("zh_su","鑻")); + m_map.insert(pair("zh_sx","鏅")); + m_map.insert(pair("zh_wan","鐨")); + m_map.insert(pair("zh_yu","璞")); + m_map.insert(pair("zh_yue","绮")); + m_map.insert(pair("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(j)=countNonZero(data); //统计这一行或一列中,非零元素的个数,并保存到mhist中 + mhist.at(j)=countNonZero(data); //缁熻杩欎竴琛屾垨涓鍒椾腑锛岄潪闆跺厓绱犵殑涓暟锛屽苟淇濆瓨鍒癿hist涓 } //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);//鐢╩hist鐩存柟鍥句腑鐨勬渶澶у硷紝褰掍竴鍖栫洿鏂瑰浘 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 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; diff --git a/src/core/chars_segment.cpp b/src/core/chars_segment.cpp index c982be8..2206df4 100644 --- a/src/core/chars_segment.cpp +++ b/src/core/chars_segment.cpp @@ -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(0,2)=m/2 - w/2; @@ -66,7 +66,7 @@ Mat CCharsSegment::preprocessChar(Mat in){ return out; } -//! 直方图均衡,为判断车牌颜色做准备 +//! 鐩存柟鍥惧潎琛★紝涓哄垽鏂溅鐗岄鑹插仛鍑嗗 Mat CCharsSegment::histeq(Mat in) { Mat out(in.size(), in.type()); @@ -88,8 +88,8 @@ Mat CCharsSegment::histeq(Mat in) } //getPlateType -//判断车牌的类型,1为蓝牌,2为黄牌,0为未知,默认蓝牌 -//通过像素中蓝色所占比例的多少来判断,大于0.3为蓝牌,否则为黄牌 +//鍒ゆ柇杞︾墝鐨勭被鍨嬶紝1涓鸿摑鐗岋紝2涓洪粍鐗岋紝0涓烘湭鐭ワ紝榛樿钃濈墝 +//閫氳繃鍍忕礌涓摑鑹叉墍鍗犳瘮渚嬬殑澶氬皯鏉ュ垽鏂紝澶т簬0.3涓鸿摑鐗岋紝鍚﹀垯涓洪粍鐗 int CCharsSegment::getPlateType(Mat input) { Mat img; @@ -129,9 +129,9 @@ int CCharsSegment::getPlateType(Mat input) } //clearLiuDing -//去除车牌上方的钮钉 -//计算每行元素的阶跃数,如果小于X认为是柳丁,将此行全部填0(涂黑) -//X的推荐值为,可根据实际调整 +//鍘婚櫎杞︾墝涓婃柟鐨勯挳閽 +//璁$畻姣忚鍏冪礌鐨勯樁璺冩暟锛屽鏋滃皬浜嶺璁や负鏄煶涓侊紝灏嗘琛屽叏閮ㄥ~0锛堟秱榛戯級 +//X鐨勬帹鑽愬间负锛屽彲鏍规嵁瀹為檯璋冩暣 Mat CCharsSegment::clearLiuDing(Mat img) { const int x = m_LiuDingSize; @@ -159,13 +159,13 @@ Mat CCharsSegment::clearLiuDing(Mat img) return img; } -//! 字符分割与排序 +//! 瀛楃鍒嗗壊涓庢帓搴 int CCharsSegment::charsSegment(Mat input, vector& resultVec) { if( !input.data ) { return -3; } - //判断车牌颜色以此确认threshold方法 + //鍒ゆ柇杞︾墝棰滆壊浠ユ纭threshold鏂规硶 int plateType = getPlateType(input); cvtColor(input, input, CV_RGB2GRAY); @@ -183,7 +183,7 @@ int CCharsSegment::charsSegment(Mat input, vector& resultVec) imwrite(ss.str(), img_threshold); } - //去除车牌上方的柳钉以及下方的横线等干扰 + //鍘婚櫎杞︾墝涓婃柟鐨勬煶閽変互鍙婁笅鏂圭殑妯嚎绛夊共鎵 clearLiuDing(img_threshold); @@ -209,7 +209,7 @@ int CCharsSegment::charsSegment(Mat input, vector& resultVec) vector vecRect; //Remove patch that are no inside limits of aspect ratio and area. - //将不符合特定尺寸的图块排除出去 + //灏嗕笉绗﹀悎鐗瑰畾灏哄鐨勫浘鍧楁帓闄ゅ嚭鍘 while (itc != contours.end()) { Rect mr = boundingRect(Mat(*itc)); @@ -225,11 +225,11 @@ int CCharsSegment::charsSegment(Mat input, vector& resultVec) return -3; vector sortedRect; - //对符合尺寸的图块按照从左到右进行排序 + //瀵圭鍚堝昂瀵哥殑鍥惧潡鎸夌収浠庡乏鍒板彸杩涜鎺掑簭 SortRect(vecRect, sortedRect); int specIndex = 0; - //获得指示城市的特定Rect,如苏A的"A" + //鑾峰緱鎸囩ず鍩庡競鐨勭壒瀹歊ect,濡傝嫃A鐨"A" specIndex = GetSpecificRect(sortedRect); if(m_debug) @@ -243,9 +243,9 @@ int CCharsSegment::charsSegment(Mat input, vector& resultVec) } } - //根据特定Rect向左反推出中文字符 - //这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect,因此仅能 - //退过特定算法来指定 + //鏍规嵁鐗瑰畾Rect鍚戝乏鍙嶆帹鍑轰腑鏂囧瓧绗 + //杩欐牱鍋氱殑涓昏鍘熷洜鏄牴鎹甪indContours鏂规硶寰堥毦鎹曟崏鍒颁腑鏂囧瓧绗︾殑鍑嗙‘Rect锛屽洜姝や粎鑳 + //閫杩囩壒瀹氱畻娉曟潵鎸囧畾 Rect chineseRect; if (specIndex < sortedRect.size()) chineseRect = GetChineseRect(sortedRect[specIndex]); @@ -261,9 +261,9 @@ int CCharsSegment::charsSegment(Mat input, vector& resultVec) } - //新建一个全新的排序Rect - //将中文字符Rect第一个加进来,因为它肯定是最左边的 - //其余的Rect只按照顺序去6个,车牌只可能是7个字符!这样可以避免阴影导致的“1”字符 + //鏂板缓涓涓叏鏂扮殑鎺掑簭Rect + //灏嗕腑鏂囧瓧绗ect绗竴涓姞杩涙潵锛屽洜涓哄畠鑲畾鏄渶宸﹁竟鐨 + //鍏朵綑鐨凴ect鍙寜鐓ч『搴忓幓6涓紝杞︾墝鍙彲鑳芥槸7涓瓧绗︼紒杩欐牱鍙互閬垮厤闃村奖瀵艰嚧鐨勨1鈥濆瓧绗 vector newSortedRect; newSortedRect.push_back(chineseRect); RebuildRect(sortedRect, newSortedRect, specIndex); @@ -292,7 +292,7 @@ int CCharsSegment::charsSegment(Mat input, vector& resultVec) return 0; } -//! 将Rect按位置从左到右进行排序 +//! 灏哛ect鎸変綅缃粠宸﹀埌鍙宠繘琛屾帓搴 int CCharsSegment::SortRect(const vector& vecRect, vector& out) { vector orderIndex; @@ -336,7 +336,7 @@ int CCharsSegment::SortRect(const vector& vecRect, vector& out) return 0; } -//! 根据特殊车牌来构造猜测中文字符的位置和大小 +//! 鏍规嵁鐗规畩杞︾墝鏉ユ瀯閫犵寽娴嬩腑鏂囧瓧绗︾殑浣嶇疆鍜屽ぇ灏 Rect CCharsSegment::GetChineseRect(const Rect rectSpe) { int height = rectSpe.height; @@ -352,7 +352,7 @@ Rect CCharsSegment::GetChineseRect(const Rect rectSpe) return a; } -//! 找出指示城市的字符的Rect,例如苏A7003X,就是"A"的位置 +//! 鎵惧嚭鎸囩ず鍩庡競鐨勫瓧绗︾殑Rect锛屼緥濡傝嫃A7003X锛屽氨鏄"A"鐨勪綅缃 int CCharsSegment::GetSpecificRect(const vector& vecRect) { vector xpositions; @@ -379,7 +379,7 @@ int CCharsSegment::GetSpecificRect(const vector& vecRect) Rect mr = vecRect[i]; int midx = mr.x + mr.width/2; - //如果一个字符有一定的大小,并且在整个车牌的1/7到2/7之间,则是我们要找的特殊车牌 + //濡傛灉涓涓瓧绗︽湁涓瀹氱殑澶у皬锛屽苟涓斿湪鏁翠釜杞︾墝鐨1/7鍒2/7涔嬮棿锛屽垯鏄垜浠鎵剧殑鐗规畩杞︾墝 if ((mr.width > maxWidth * 0.8 || mr.height > maxHeight * 0.8) && (midx < int(m_theMatWidth / 7) * 2 && midx > int(m_theMatWidth / 7) * 1)) { @@ -390,17 +390,17 @@ int CCharsSegment::GetSpecificRect(const vector& vecRect) return specIndex; } -//! 这个函数做两个事情 -// 1.把特殊字符Rect左边的全部Rect去掉,后面再重建中文字符的位置。 -// 2.从特殊字符Rect开始,依次选择6个Rect,多余的舍去。 +//! 杩欎釜鍑芥暟鍋氫袱涓簨鎯 +// 1.鎶婄壒娈婂瓧绗ect宸﹁竟鐨勫叏閮≧ect鍘绘帀锛屽悗闈㈠啀閲嶅缓涓枃瀛楃鐨勪綅缃 +// 2.浠庣壒娈婂瓧绗ect寮濮嬶紝渚濇閫夋嫨6涓猂ect锛屽浣欑殑鑸嶅幓銆 int CCharsSegment::RebuildRect(const vector& vecRect, vector& outRect, int specIndex) { - //最大只能有7个Rect,减去中文的就只有6个Rect + //鏈澶у彧鑳芥湁7涓猂ect,鍑忓幓涓枃鐨勫氨鍙湁6涓猂ect int count = 6; for (int i = 0; i < vecRect.size(); i++) { - //将特殊字符左边的Rect去掉,这个可能会去掉中文Rect,不过没关系,我们后面会重建。 + //灏嗙壒娈婂瓧绗﹀乏杈圭殑Rect鍘绘帀锛岃繖涓彲鑳戒細鍘绘帀涓枃Rect锛屼笉杩囨病鍏崇郴锛屾垜浠悗闈細閲嶅缓銆 if (i < specIndex) continue; diff --git a/src/core/features.cpp b/src/core/features.cpp index 26ec713..e5a790f 100644 --- a/src/core/features.cpp +++ b/src/core/features.cpp @@ -1,6 +1,6 @@ -// 这个文件定义了EasyPR里所有特征生成的函数 -// 所属命名空间为easypr -// 这个部分中的特征由easypr的开发者修改 +// 杩欎釜鏂囦欢瀹氫箟浜咵asyPR閲屾墍鏈夌壒寰佺敓鎴愮殑鍑芥暟 +// 鎵灞炲懡鍚嶇┖闂翠负easypr +// 杩欎釜閮ㄥ垎涓殑鐗瑰緛鐢眅asypr鐨勫紑鍙戣呬慨鏀 #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(j)=countNonZero(data); //统计这一行或一列中,非零元素的个数,并保存到mhist中 + mhist.at(j)=countNonZero(data); //缁熻杩欎竴琛屾垨涓鍒椾腑锛岄潪闆跺厓绱犵殑涓暟锛屽苟淇濆瓨鍒癿hist涓 } //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);//鐢╩hist鐩存柟鍥句腑鐨勬渶澶у硷紝褰掍竴鍖栫洿鏂瑰浘 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& resultVec) { - //可能是车牌的图块集合 + //鍙兘鏄溅鐗岀殑鍥惧潡闆嗗悎 vector matVec; int resultLo = m_plateLocate->plateLocate(src, matVec); diff --git a/src/core/plate_judge.cpp b/src/core/plate_judge.cpp index 4b4dfec..f6ae18a 100644 --- a/src/core/plate_judge.cpp +++ b/src/core/plate_judge.cpp @@ -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判断 +//! 瀵瑰崟骞呭浘鍍忚繘琛孲VM鍒ゆ柇 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判断 +//! 瀵瑰骞呭浘鍍忚繘琛孲VM鍒ゆ柇 int CPlateJudge::plateJudge(const vector& inVec, vector& resultVec) { diff --git a/src/core/plate_locate.cpp b/src/core/plate_locate.cpp index 5405c7d..7d6e9b7 100644 --- a/src/core/plate_locate.cpp +++ b/src/core/plate_locate.cpp @@ -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获得的最小外接矩形,用纵横比进行判断 +//! 瀵筸inAreaRect鑾峰緱鐨勬渶灏忓鎺ョ煩褰紝鐢ㄧ旱妯瘮杩涜鍒ゆ柇 bool CPlateLocate::verifySizes(RotatedRect mr) { float error = m_error; //Spain car plate size: 52x11 aspect 4,7272 - //China car plate size: 440mm*140mm,aspect 3.142857 + //China car plate size: 440mm*140mm锛宎spect 3.142857 float aspect = m_aspect; //Set a min and max area. All other patchs are discarded //int min= 1*aspect*1; // minimum area @@ -85,7 +85,7 @@ bool CPlateLocate::verifySizes(RotatedRect mr) } } -//! 显示最终生成的车牌图像,便于判断是否成功进行了旋转。 +//! 鏄剧ず鏈缁堢敓鎴愮殑杞︾墝鍥惧儚锛屼究浜庡垽鏂槸鍚︽垚鍔熻繘琛屼簡鏃嬭浆銆 Mat CPlateLocate::showResultMat(Mat src, Size rect_size, Point2f center, int index) { Mat img_crop; @@ -113,10 +113,10 @@ Mat CPlateLocate::showResultMat(Mat src, Size rect_size, Point2f center, int ind return resultResized; } -//! 定位车牌图像 -//! src 原始图像 -//! resultVec 一个Mat的向量,存储所有抓取到的图像 -//! 成功返回0,否则返回-1 +//! 瀹氫綅杞︾墝鍥惧儚 +//! src 鍘熷鍥惧儚 +//! resultVec 涓涓狹at鐨勫悜閲忥紝瀛樺偍鎵鏈夋姄鍙栧埌鐨勫浘鍍 +//! 鎴愬姛杩斿洖0锛屽惁鍒欒繑鍥-1 int CPlateLocate::plateLocate(Mat src, vector& resultVec) { Mat src_blur, src_gray; @@ -129,7 +129,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec) if( !src.data ) { return -1; } - //高斯模糊。Size中的数字影响车牌定位的效果。 + //楂樻柉妯$硦銆係ize涓殑鏁板瓧褰卞搷杞︾墝瀹氫綅鐨勬晥鏋溿 GaussianBlur( src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize), 0, 0, BORDER_DEFAULT ); @@ -199,11 +199,11 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec) imwrite(ss.str(), img_threshold); } - //Find 轮廓 of possibles plates + //Find 杞粨 of possibles plates vector< vector< Point> > contours; findContours(img_threshold, contours, // a vector of contours - CV_RETR_EXTERNAL, // 提取外部轮廓 + CV_RETR_EXTERNAL, // 鎻愬彇澶栭儴杞粨 CV_CHAIN_APPROX_NONE); // all pixels of each contours Mat result; @@ -252,10 +252,10 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec) { // rotated rectangle drawing // Get rotation matrix - // 旋转这部分代码确实可以将某些倾斜的车牌调整正, - // 但是它也会误将更多正的车牌搞成倾斜!所以综合考虑,还是不使用这段代码。 - // 2014-08-14,由于新到的一批图片中发现有很多车牌是倾斜的,因此决定再次尝试 - // 这段代码。 + // 鏃嬭浆杩欓儴鍒嗕唬鐮佺‘瀹炲彲浠ュ皢鏌愪簺鍊炬枩鐨勮溅鐗岃皟鏁存锛 + // 浣嗘槸瀹冧篃浼氳灏嗘洿澶氭鐨勮溅鐗屾悶鎴愬炬枩锛佹墍浠ョ患鍚堣冭檻锛岃繕鏄笉浣跨敤杩欐浠g爜銆 + // 2014-08-14,鐢变簬鏂板埌鐨勪竴鎵瑰浘鐗囦腑鍙戠幇鏈夊緢澶氳溅鐗屾槸鍊炬枩鐨勶紝鍥犳鍐冲畾鍐嶆灏濊瘯 + // 杩欐浠g爜銆 if(m_debug) { Point2f rect_points[4]; @@ -272,7 +272,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec) angle = 90 + angle; swap(rect_size.width, rect_size.height); } - //如果抓取的方块旋转超过m_angle角度,则不是车牌,放弃处理 + //濡傛灉鎶撳彇鐨勬柟鍧楁棆杞秴杩噈_angle瑙掑害锛屽垯涓嶆槸杞︾墝锛屾斁寮冨鐞 if (angle - m_angle < 0 && angle + m_angle > 0) { //Create and rotate image diff --git a/src/core/plate_recognize.cpp b/src/core/plate_recognize.cpp index 0a614bf..ab41411 100644 --- a/src/core/plate_recognize.cpp +++ b/src/core/plate_recognize.cpp @@ -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& licenseVec) { - //车牌方块集合 + //杞︾墝鏂瑰潡闆嗗悎 vector plateVec; int resultPD = plateDetect(src, plateVec); @@ -51,10 +51,10 @@ int CPlateRecognize::plateRecognize(Mat src, vector& licenseVec) { Mat plate = plateVec[j]; - //获取车牌颜色 + //鑾峰彇杞︾墝棰滆壊 string plateType = getPlateType(plate); - //获取车牌号 + //鑾峰彇杞︾墝鍙 string plateIdentify = ""; int resultCR = charsRecognise(plate, plateIdentify); if (resultCR == 0) diff --git a/src/include/chars_identify.h b/src/include/chars_identify.h index 3657418..d08015c 100644 --- a/src/include/chars_identify.h +++ b/src/include/chars_identify.h @@ -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 m_map; }; diff --git a/src/include/chars_recognise.h b/src/include/chars_recognise.h index 80d2240..ea17452 100644 --- a/src/include/chars_recognise.h +++ b/src/include/chars_recognise.h @@ -27,32 +27,32 @@ class CCharsRecognise public: CCharsRecognise(); - //! 字符分割与识别 + //! 瀛楃鍒嗗壊涓庤瘑鍒 int charsRecognise(Mat, String&); - //! 装载ANN模型 + //! 瑁呰浇ANN妯″瀷 void LoadANN(string s); - //! 是否开启调试模式 + //! 鏄惁寮鍚皟璇曟ā寮 inline void setCRDebug(int param){ m_charsSegment->setDebug(param);} - //! 获取调试模式状态 + //! 鑾峰彇璋冭瘯妯″紡鐘舵 inline int getCRDebug(){ return m_charsSegment->getDebug();} - //! 获得车牌颜色 + //! 鑾峰緱杞︾墝棰滆壊 inline string getPlateType(Mat input) const { - string color = "未知"; + string color = "鏈煡"; int result = m_charsSegment->getPlateType(input); if (1 == result) - color = "蓝牌"; + color = "钃濈墝"; if (2 == result) - color = "黄牌"; + color = "榛勭墝"; return color; } - //! 设置变量 + //! 璁剧疆鍙橀噺 inline void setLiuDingSize(int param){ m_charsSegment->setLiuDingSize(param);} inline void setColorThreshold(int param){ m_charsSegment->setColorThreshold(param);} inline void setBluePercent(float param){ m_charsSegment->setBluePercent(param);} @@ -61,10 +61,10 @@ public: inline float getWhitePercent() const { return m_charsSegment->getWhitePercent();} private: - //!字符分割 + //锛佸瓧绗﹀垎鍓 CCharsSegment* m_charsSegment; - //! 字符识别 + //! 瀛楃璇嗗埆 CCharsIdentify* m_charsIdentify; }; diff --git a/src/include/chars_segment.h b/src/include/chars_segment.h index ed1c40f..be4bef0 100644 --- a/src/include/chars_segment.h +++ b/src/include/chars_segment.h @@ -24,45 +24,45 @@ class CCharsSegment public: CCharsSegment(); - //! 字符分割 + //! 瀛楃鍒嗗壊 int charsSegment(Mat, vector& ); - //! 字符尺寸验证 + //! 瀛楃灏哄楠岃瘉 bool verifySizes(Mat r); - //! 字符预处理 + //! 瀛楃棰勫鐞 Mat preprocessChar(Mat in); - //! 生成直方图 + //! 鐢熸垚鐩存柟鍥 Mat ProjectedHistogram(Mat img, int t); - //! 生成字符的特定特征 + //! 鐢熸垚瀛楃鐨勭壒瀹氱壒寰 Mat features(Mat in, int sizeData); - //! 直方图均衡,为判断车牌颜色做准备 + //! 鐩存柟鍥惧潎琛★紝涓哄垽鏂溅鐗岄鑹插仛鍑嗗 Mat histeq(Mat in); - //! 获得车牌颜色 + //! 鑾峰緱杞︾墝棰滆壊 int getPlateType(Mat input); - //! 去除影响字符识别的柳钉 + //! 鍘婚櫎褰卞搷瀛楃璇嗗埆鐨勬煶閽 Mat clearLiuDing(Mat img); - //! 根据特殊车牌来构造猜测中文字符的位置和大小 + //! 鏍规嵁鐗规畩杞︾墝鏉ユ瀯閫犵寽娴嬩腑鏂囧瓧绗︾殑浣嶇疆鍜屽ぇ灏 Rect GetChineseRect(const Rect rectSpe); - //! 找出指示城市的字符的Rect,例如苏A7003X,就是A的位置 + //! 鎵惧嚭鎸囩ず鍩庡競鐨勫瓧绗︾殑Rect锛屼緥濡傝嫃A7003X锛屽氨鏄疉鐨勪綅缃 int GetSpecificRect(const vector& vecRect); - //! 这个函数做两个事情 - // 1.把特殊字符Rect左边的全部Rect去掉,后面再重建中文字符的位置。 - // 2.从特殊字符Rect开始,依次选择6个Rect,多余的舍去。 + //! 杩欎釜鍑芥暟鍋氫袱涓簨鎯 + // 1.鎶婄壒娈婂瓧绗ect宸﹁竟鐨勫叏閮≧ect鍘绘帀锛屽悗闈㈠啀閲嶅缓涓枃瀛楃鐨勪綅缃 + // 2.浠庣壒娈婂瓧绗ect寮濮嬶紝渚濇閫夋嫨6涓猂ect锛屽浣欑殑鑸嶅幓銆 int RebuildRect(const vector& vecRect, vector& outRect, int specIndex); - //! 将Rect按位置从左到右进行排序 + //! 灏哛ect鎸変綅缃粠宸﹀埌鍙宠繘琛屾帓搴 int SortRect(const vector& vecRect, vector& out); - //! 设置变量 + //! 璁剧疆鍙橀噺 inline void setLiuDingSize(int param){ m_LiuDingSize = param;} inline void setColorThreshold(int param){ m_ColorThreshold = param;} @@ -71,38 +71,38 @@ public: inline void setWhitePercent(float param){ m_WhitePercent = param;} inline float getWhitePercent() const { return m_WhitePercent;} - //! 是否开启调试模式常量,默认0代表关闭 + //! 鏄惁寮鍚皟璇曟ā寮忓父閲忥紝榛樿0浠h〃鍏抽棴 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; }; diff --git a/src/include/features.h b/src/include/features.h index 976173a..4346f8e 100644 --- a/src/include/features.h +++ b/src/include/features.h @@ -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鐨刧etFeatures鍥炶皟鍑芥暟 +// 锛佺敤浜庝粠杞︾墝鐨刬mage鐢熸垚svm鐨勮缁冪壒寰乫eatures typedef void(*svmCallback)(const Mat& image, Mat& features); -// ! EasyPR的getFeatures回调函数 -// !本函数是生成直方图均衡特征的回调函数 +// ! EasyPR鐨刧etFeatures鍥炶皟鍑芥暟 +// 锛佹湰鍑芥暟鏄敓鎴愮洿鏂瑰浘鍧囪 鐗瑰緛鐨勫洖璋冨嚱鏁 void getHisteqFeatures(const Mat& image, Mat& features); -// ! EasyPR的getFeatures回调函数 -// !本函数是获取垂直和水平的直方图图值 +// ! EasyPR鐨刧etFeatures鍥炶皟鍑芥暟 +// 锛佹湰鍑芥暟鏄幏鍙栧瀭鐩村拰姘村钩鐨勭洿鏂瑰浘鍥惧 void getHistogramFeatures(const Mat& image, Mat& features); -// !本函数是获取SIFT特征子 +// 锛佹湰鍑芥暟鏄幏鍙朣IFT鐗瑰緛瀛 void getSIFTFeatures(const Mat& image, Mat& features); -// !本函数是获取HOG特征子 +// 锛佹湰鍑芥暟鏄幏鍙朒OG鐗瑰緛瀛 void getHOGFeatures(const Mat& image, Mat& features); diff --git a/src/include/plate_detect.h b/src/include/plate_detect.h index abe497f..12e68b8 100644 --- a/src/include/plate_detect.h +++ b/src/include/plate_detect.h @@ -27,22 +27,22 @@ class CPlateDetect public: CPlateDetect(); - //! 车牌检测:车牌定位与判断 + //! 杞︾墝妫娴嬶細杞︾墝瀹氫綅涓庡垽鏂 int plateDetect(Mat, vector&); - //! 装载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; }; diff --git a/src/include/plate_judge.h b/src/include/plate_judge.h index 388a98a..4c50093 100644 --- a/src/include/plate_judge.h +++ b/src/include/plate_judge.h @@ -25,34 +25,34 @@ class CPlateJudge public: CPlateJudge(); - //! 车牌判断 + //! 杞︾墝鍒ゆ柇 int plateJudge(const vector&, vector&); - //! 车牌判断(一副图像) + //! 杞︾墝鍒ゆ柇锛堜竴鍓浘鍍忥級 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鐨刧etFeatures鍥炶皟鍑芥暟 + // 锛佺敤浜庝粠杞︾墝鐨刬mage鐢熸垚svm鐨勮缁冪壒寰乫eatures svmCallback m_getFeatures; - //! 模型存储路径 + //! 妯″瀷瀛樺偍璺緞 string m_path; }; diff --git a/src/include/plate_locate.h b/src/include/plate_locate.h index 61d94bc..48240ab 100644 --- a/src/include/plate_locate.h +++ b/src/include/plate_locate.h @@ -25,19 +25,19 @@ class CPlateLocate public: CPlateLocate(); - //! 车牌定位 + //! 杞︾墝瀹氫綅 int plateLocate(Mat, vector& ); - //! 车牌的尺寸验证 + //! 杞︾墝鐨勫昂瀵搁獙璇 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浠h〃鍏抽棴 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; }; diff --git a/src/include/plate_recognize.h b/src/include/plate_recognize.h index a07a162..c799e46 100644 --- a/src/include/plate_recognize.h +++ b/src/include/plate_recognize.h @@ -27,39 +27,39 @@ class CPlateRecognize : public CPlateDetect, public CCharsRecognise public: CPlateRecognize(); - //! 车牌检测与字符识别 + //! 杞︾墝妫娴嬩笌瀛楃璇嗗埆 int plateRecognize(Mat, vector&); - //! 生活模式与工业模式切换 + //! 鐢熸椿妯″紡涓庡伐涓氭ā寮忓垏鎹 inline void setLifemode(bool param) { CPlateDetect::setPDLifemode(param); } - //! 是否开启调试模式 + //! 鏄惁寮鍚皟璇曟ā寮 inline void setDebug(int param) { CPlateDetect::setPDDebug(param); CCharsRecognise::setCRDebug(param); } - ////! 车牌定位与判断 + ////! 杞︾墝瀹氫綅涓庡垽鏂 //int plateDetect(Mat, vector&); - ////! 字符分割与识别 + ////! 瀛楃鍒嗗壊涓庤瘑鍒 //int charsRecognise(Mat, String&); - ////! 装载SVM + ////! 瑁呰浇SVM //void LoadSVM(string s); - ////! 装载ANN模型 + ////! 瑁呰浇ANN妯″瀷 //void LoadANN(string s); private: - ////!车牌检测 + ////锛佽溅鐗屾娴 //CPlateDetect* m_plateDetect; - ////! 字符识别 + ////! 瀛楃璇嗗埆 //CCharsRecognise* m_charsRecognise; }; diff --git a/src/include/prep.h b/src/include/prep.h index 97ee7fb..2df96b4 100644 --- a/src/include/prep.h +++ b/src/include/prep.h @@ -7,10 +7,19 @@ #include "opencv2/nonfree/features2d.hpp" #include "opencv/cvaux.h" +#if defined (WIN32) || defined (_WIN32) #include +#endif + #include #include + +#if defined (WIN32) || defined (_WIN32) #include +#elif defined (linux) || defined (__linux__) +#include +#endif + #include #include #include @@ -21,4 +30,4 @@ using namespace std; using namespace cv; #endif -/* endif __PREP_H__ */ \ No newline at end of file +/* endif __PREP_H__ */ diff --git a/src/include/util.h b/src/include/util.h index ea22940..6661edb 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -2,17 +2,22 @@ #ifndef __UTIL_H__ #define __UTIL_H__ -//C++的获取文件夹函数 +//C++鐨勮幏鍙栨枃浠跺す鍑芥暟 void getFiles(string path, vector& files); -//C++的spilt函数 +//Linux涓嬬殑GetTickCount鍑芥暟 +#if defined (linux) || defined (__linux__) +double GetTickCount(); +#endif + +//C++鐨剆pilt鍑芥暟 void SplitString(const string& s, vector& v, const string& c); -//C++的从文件路径名称到文件名称(不包括后缀)的方法 +//C++鐨勪粠鏂囦欢璺緞鍚嶇О鍒版枃浠跺悕绉帮紙涓嶅寘鎷悗缂锛夌殑鏂规硶 void getFileName(const string& filepath, string& name); -//! levenshtein距离,用于计算两个车牌的距离 -//!EasyPR中用levenshtein距离衡量车牌识别与真实车牌的误差 +//! levenshtein璺濈锛岀敤浜庤绠椾袱涓溅鐗岀殑璺濈 +//锛丒asyPR涓敤levenshtein璺濈琛¢噺杞︾墝璇嗗埆涓庣湡瀹炶溅鐗岀殑璇樊 template unsigned int levenshtein_distance(const T &s1, const T & s2) { const size_t len1 = s1.size(), len2 = s2.size(); @@ -31,33 +36,33 @@ unsigned int levenshtein_distance(const T &s1, const T & s2) { } -/// test.cpp中方法 +/// test.cpp涓柟娉 int testMain(); -/// accuracy_test.cpp中方法 +/// accuracy_test.cpp涓柟娉 int acurayTest(const string&); -/// mc_data_prepare.cpp中方法 +/// mc_data_prepare.cpp涓柟娉 void getLearnData(); void Code2Province(const string& code, string& province); void changeFileName(); void getPlateLicense(const string& filepath, string& plateLicense); -/// learn_prepare.cpp中方法 +/// learn_prepare.cpp涓柟娉 void label_data(); -/// general_test_prepare.cpp中方法 +/// general_test_prepare.cpp涓柟娉 int general_test(); -// deface.cpp中方法 -// 反人脸识别函数 -// 在发布数据到general_test数据集里,请先用这里的方法对图像进行处理 -// EasyPR开源项目非常注重保护图片中驾驶人的隐私 +// deface.cpp涓柟娉 +// 鍙嶄汉鑴歌瘑鍒嚱鏁 +// 鍦ㄥ彂甯冩暟鎹埌general_test鏁版嵁闆嗛噷锛岃鍏堢敤杩欓噷鐨勬柟娉曞鍥惧儚杩涜澶勭悊 +// EasyPR寮婧愰」鐩潪甯告敞閲嶄繚鎶ゅ浘鐗囦腑椹鹃┒浜虹殑闅愮 int deface(); -/// generate_gdts.cpp中方法 +/// generate_gdts.cpp涓柟娉 int generate_gdts(); #endif -/* endif __UTIL_H__ */ \ No newline at end of file +/* endif __UTIL_H__ */ diff --git a/src/main.cpp b/src/main.cpp index 2a59f07..a53286a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,18 +18,18 @@ extern const string GENERAL_TEST_PATH = "image/general_test"; extern const string NATIVE_TEST_PATH = "image/native_test"; //////////////////////////////////////////////////////////// -// EasyPR 训练命令行 +// EasyPR 璁粌鍛戒护琛 const string option[] = { - "1. 测试;" , - "2. 批量测试;" , - "3. SVM训练;" , - "4. ANN训练(未开放);" , - "5. GDTS生成;" , - "6. 开发团队;" , - "7. 感谢名单;" , - "8. 退出;" , + "1. 娴嬭瘯;" , + "2. 鎵归噺娴嬭瘯;" , + "3. SVM璁粌;" , + "4. ANN璁粌(鏈紑鏀);" , + "5. GDTS鐢熸垚;" , + "6. 寮鍙戝洟闃;" , + "7. 鎰熻阿鍚嶅崟;" , + "8. 閫鍑;" , }; const int optionCount = 8; @@ -49,7 +49,7 @@ int main() cout << "////////////////////////////////////"<< endl; cout << selectOption.str(); cout << "////////////////////////////////////"<< endl; - cout << "请选择一项操作:"; + cout << "璇烽夋嫨涓椤规搷浣:"; int select = -1; bool isRepeat = true; @@ -75,28 +75,28 @@ int main() generate_gdts(); break; case 6: - // 开发团队; + // 寮鍙戝洟闃; cout << endl; - cout << "我们EasyPR团队目前有一个5人左右的小组在进行EasyPR后续版本的开发工作。" << endl; - cout << "如果你对本项目感兴趣,并且愿意为开源贡献一份力量,我们很欢迎你的加入。" << endl; - cout << "目前招聘的主要人才是:车牌定位,图像识别,深度学习,网站建设相关方面的牛人。" << endl; - cout << "如果你觉得自己符合条件,请发邮件到地址(easypr_dev@163.com),期待你的加入!" << endl; + cout << "鎴戜滑EasyPR鍥㈤槦鐩墠鏈変竴涓5浜哄乏鍙崇殑灏忕粍鍦ㄨ繘琛孍asyPR鍚庣画鐗堟湰鐨勫紑鍙戝伐浣溿" << endl; + cout << "濡傛灉浣犲鏈」鐩劅鍏磋叮锛屽苟涓旀効鎰忎负寮婧愯础鐚竴浠藉姏閲忥紝鎴戜滑寰堟杩庝綘鐨勫姞鍏ャ" << endl; + cout << "鐩墠鎷涜仒鐨勪富瑕佷汉鎵嶆槸锛氳溅鐗屽畾浣嶏紝鍥惧儚璇嗗埆锛屾繁搴﹀涔狅紝缃戠珯寤鸿鐩稿叧鏂归潰鐨勭墰浜恒" << endl; + cout << "濡傛灉浣犺寰楄嚜宸辩鍚堟潯浠讹紝璇峰彂閭欢鍒板湴鍧(easypr_dev@163.com)锛屾湡寰呬綘鐨勫姞鍏ワ紒" << endl; cout << endl; break; case 7: - // 感谢名单 + // 鎰熻阿鍚嶅崟 cout << endl; - cout << "本项目在建设过程中,受到了很多人的帮助,其中以下是对本项目做出突出贡献的" << endl; - cout << "(贡献包括有益建议,代码调优,数据提供等等,排名按时间顺序):" << endl; - cout << "taotao1233, 唐大侠,jsxyhelu,如果有一天,学习奋斗,袁承志,圣城小石匠," << endl; - cout << "还有很多的同学对本项目也给予了鼓励与支持,在此也一并表示真诚的谢意!" << endl; + cout << "鏈」鐩湪寤鸿杩囩▼涓紝鍙楀埌浜嗗緢澶氫汉鐨勫府鍔╋紝鍏朵腑浠ヤ笅鏄鏈」鐩仛鍑虹獊鍑鸿础鐚殑" << endl; + cout << "(璐$尞鍖呮嫭鏈夌泭寤鸿锛屼唬鐮佽皟浼橈紝鏁版嵁鎻愪緵绛夌瓑,鎺掑悕鎸夋椂闂撮『搴)锛" << endl; + cout << "taotao1233, 鍞愬ぇ渚狅紝jsxyhelu锛屽鏋滄湁涓澶╋紝瀛︿範濂嬫枟锛岃鎵垮織锛屽湥鍩庡皬鐭冲尃锛" << endl; + cout << "杩樻湁寰堝鐨勫悓瀛﹀鏈」鐩篃缁欎簣浜嗛紦鍔变笌鏀寔锛屽湪姝や篃涓骞惰〃绀虹湡璇氱殑璋㈡剰锛" << endl; cout << endl; break; case 8: isExit = true; break; default: - cout << "输入错误,请重新输入:"; + cout << "杈撳叆閿欒锛岃閲嶆柊杈撳叆:"; isRepeat = true; break; } @@ -104,18 +104,18 @@ int main() } return 0; } -// /EasyPR 训练命令行 结束 +// /EasyPR 璁粌鍛戒护琛 缁撴潫 //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// -// acurayTestMain 命令行 +// acurayTestMain 鍛戒护琛 const string acuray_option[] = { "1. general_test;" , "2. native_test;" , - "3. 返回;" , + "3. 杩斿洖;" , }; const int acuray_optionCount = 3; @@ -135,7 +135,7 @@ int acurayTestMain() cout << "////////////////////////////////////"<< endl; cout << selectOption.str(); cout << "////////////////////////////////////"<< endl; - cout << "请选择一项操作:"; + cout << "璇烽夋嫨涓椤规搷浣:"; int select = -1; bool isRepeat = true; @@ -155,7 +155,7 @@ int acurayTestMain() isExit = true; break; default: - cout << "输入错误,请重新输入:"; + cout << "杈撳叆閿欒锛岃閲嶆柊杈撳叆:"; isRepeat = true; break; } @@ -164,22 +164,22 @@ int acurayTestMain() return 0; } -// acurayTestMain 命令行 +// acurayTestMain 鍛戒护琛 //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// -// SVM 训练命令行 +// SVM 璁粌鍛戒护琛 const string svm_option[] = { - "1. 生成learndata(调整代码到你的环境后再用);" , - "2. 标签learndata;" , - "3. 车牌检测(not divide and train);" , - "4. 车牌检测(not train);" , - "5. 车牌检测(not divide);" , - "6. 车牌检测;" , - "7. 返回;" , + "1. 鐢熸垚learndata(璋冩暣浠g爜鍒颁綘鐨勭幆澧冨悗鍐嶇敤);" , + "2. 鏍囩learndata;" , + "3. 杞︾墝妫娴(not divide and train);" , + "4. 杞︾墝妫娴(not train);" , + "5. 杞︾墝妫娴(not divide);" , + "6. 杞︾墝妫娴;" , + "7. 杩斿洖;" , }; const int svm_optionCount = 7; @@ -199,7 +199,7 @@ int svmMain() cout << "////////////////////////////////////"<< endl; cout << selectOption.str(); cout << "////////////////////////////////////"<< endl; - cout << "请选择一项操作:"; + cout << "璇烽夋嫨涓椤规搷浣:"; int select = -1; bool isRepeat = true; @@ -231,7 +231,7 @@ int svmMain() isExit = true; break; default: - cout << "输入错误,请重新输入:"; + cout << "杈撳叆閿欒锛岃閲嶆柊杈撳叆:"; isRepeat = true; break; } @@ -240,5 +240,5 @@ int svmMain() return 0; } -// SVM 训练命令行 +// SVM 璁粌鍛戒护琛 //////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/src/test/accuracy_test.cpp b/src/test/accuracy_test.cpp index 01b1aa2..a0df620 100644 --- a/src/test/accuracy_test.cpp +++ b/src/test/accuracy_test.cpp @@ -1,5 +1,5 @@ -// 通用正确率测试文件 -// AcurayTest对应到main控制命令中的选项2 +// 閫氱敤姝g‘鐜囨祴璇曟枃浠 +// AcurayTest瀵瑰簲鍒癿ain鎺у埗鍛戒护涓殑閫夐」2 #include "../include/plate_recognize.h" #include "../include/util.h" @@ -9,7 +9,7 @@ using namespace easypr; int acurayTest(const string& test_path) { - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 vector files; getFiles(test_path, files); @@ -32,20 +32,20 @@ int acurayTest(const string& test_path) cout << "Begin to test the easypr accuracy!" << endl; - // 总的测试图片数量 + // 鎬荤殑娴嬭瘯鍥剧墖鏁伴噺 int count_all = 0; - // 错误的图片数量 + // 閿欒鐨勫浘鐗囨暟閲 int count_err = 0; - // 未识别的图片数量 + // 鏈瘑鍒殑鍥剧墖鏁伴噺 int count_norecogin = 0; - // 总的字符差距 + // 鎬荤殑瀛楃宸窛 float diff_all = 0; - // 平均字符差距 + // 骞冲潎瀛楃宸窛 float diff_avg = 0; - // 完全匹配的识别次数 + // 瀹屽叏鍖归厤鐨勮瘑鍒鏁 float match_count = 0; - // 完全匹配的识别次数所占识别图片中的比例 + // 瀹屽叏鍖归厤鐨勮瘑鍒鏁版墍鍗犺瘑鍒浘鐗囦腑鐨勬瘮渚 float match_rate = 0; for (int i = 0; i < size; i++) @@ -53,13 +53,13 @@ int acurayTest(const string& test_path) string filepath = files[i].c_str(); cout << "------------------" << endl; - // 获取真实的车牌 + // 鑾峰彇鐪熷疄鐨勮溅鐗 string plateLicense = ""; getFileName(filepath, plateLicense); - cout << "原牌:" << plateLicense << endl; + cout << "鍘熺墝:" << plateLicense << endl; - // EasyPR开始判断车牌 + // EasyPR寮濮嬪垽鏂溅鐗 Mat src = imread(filepath); vector plateVec; int result = pr.plateRecognize(src, plateVec); @@ -69,20 +69,20 @@ int acurayTest(const string& test_path) if (num == 0) { - cout << ""<< "无车牌" < 1) { - // 多车牌使用diff最小的那个记录 + // 澶氳溅鐗屼娇鐢╠iff鏈灏忕殑閭d釜璁板綍 int mindiff = 10000; for (int j = 0; j < num; j++) { cout << plateVec[j] << " (" << j+1 << ")"< spilt_plate; SplitString(colorplate, spilt_plate, ":"); @@ -95,23 +95,23 @@ int acurayTest(const string& test_path) } } - cout << "差距:" << mindiff << "个字符" << endl; + cout << "宸窛:" << mindiff << "涓瓧绗" << endl; if(mindiff == 0) { - // 完全匹配 + // 瀹屽叏鍖归厤 match_count++; } diff_all = diff_all + mindiff; } else { - // 单车牌只计算一次diff + // 鍗曡溅鐗屽彧璁$畻涓娆iff for (int j = 0; j < num; j++) { cout << plateVec[j] < spilt_plate; SplitString(colorplate, spilt_plate, ":"); @@ -119,11 +119,11 @@ int acurayTest(const string& test_path) if (size == 2) { int diff = levenshtein_distance(plateLicense, spilt_plate[size-1]); - cout << "差距:" << diff << "个字符" << endl; + cout << "宸窛:" << diff << "涓瓧绗" << endl; if(diff == 0) { - // 完全匹配 + // 瀹屽叏鍖归厤 match_count++; } diff_all = diff_all + diff; @@ -134,7 +134,7 @@ int acurayTest(const string& test_path) } else { - cout << "错误码:" << result << endl; + cout << "閿欒鐮:" << result << endl; count_err++; } count_all++; @@ -144,20 +144,20 @@ int acurayTest(const string& test_path) cout << "Easypr accuracy test end!" << endl; cout << "------------------" << endl; cout << endl; - cout << "正确率统计:" << endl; - cout << "总图片数:" << count_all << "张, "; - cout << "未识别图片:" << count_norecogin << "张, "; + cout << "姝g‘鐜囩粺璁:" << endl; + cout << "鎬诲浘鐗囨暟:" << count_all << "寮, "; + cout << "鏈瘑鍒浘鐗:" << count_norecogin << "寮, "; float count_recogin = count_all - (count_err + count_norecogin); float count_rate = count_recogin / count_all * 100; - cout << "识别率:" << count_rate << "% " << endl; + cout << "璇嗗埆鐜:" << count_rate << "% " << endl; diff_avg = diff_all / count_recogin; match_rate = match_count/ count_recogin * 100; - cout << "平均字距:" << diff_avg << "个, "; - cout << "完全匹配数:" << match_count << "张, "; - cout << "完全匹配率:" << match_rate << "% " << endl; + cout << "骞冲潎瀛楄窛:" << diff_avg << "涓, "; + cout << "瀹屽叏鍖归厤鏁:" << match_count << "寮, "; + cout << "瀹屽叏鍖归厤鐜:" << match_rate << "% " << endl; cout << endl; cout << "------------------" << endl; diff --git a/src/test/test.cpp b/src/test/test.cpp index 45997c2..69b5c11 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -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; } @@ -143,10 +143,10 @@ int test_plate_judge() Mat src = imread("image/plate_judge.jpg"); - //可能是车牌的图块集合 + //鍙兘鏄溅鐗岀殑鍥惧潡闆嗗悎 vector matVec; - //经过SVM判断后得到的图块集合 + //缁忚繃SVM鍒ゆ柇鍚庡緱鍒扮殑鍥惧潡闆嗗悎 vector resultVec; CPlateLocate lo; @@ -236,7 +236,7 @@ int test_chars_identify() Mat resultMat = resultVec[j]; bool isChinses = false; - //默认首个字符块是中文字符 + //榛樿棣栦釜瀛楃鍧楁槸涓枃瀛楃 if (j == 0) isChinses = true; @@ -245,7 +245,7 @@ int test_chars_identify() } } - const string plateLicense = "苏E771H6"; + const string plateLicense = "鑻廍771H6"; cout << "plateLicense: " << plateLicense << endl; cout << "plateIdentify: " << plateIdentify << endl; diff --git a/src/train/ann_train.cpp b/src/train/ann_train.cpp index eb254f3..39d33e7 100644 --- a/src/train/ann_train.cpp +++ b/src/train/ann_train.cpp @@ -1,15 +1,24 @@ -// ann_train.cpp : ann模型的训练文件,主要用在OCR中 +// ann_train.cpp : ann妯″瀷鐨勮缁冩枃浠讹紝涓昏鐢ㄥ湪OCR涓 #include #include #include "opencv2/ml/ml.hpp" #include "opencv2/highgui/highgui.hpp" +#if defined (WIN32) || defined (_WIN32) #include +#endif + #include #include #include + +#if defined (WIN32) || defined (_WIN32) #include +#elif defined (linux) || defined (__linux__) +#include +#endif + #include #include @@ -24,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和0,10个数字与24个英文字符之和 */ +const int numCharacter = 34; /* 娌℃湁I鍜0,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 */ @@ -59,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 files; - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 getFiles(filePath, files ); int size = files.size(); if (0 == size) cout << "No File Found in learn HasPlate!" << endl; - ////随机选取70%作为训练数据,30%作为测试数据 + ////闅忔満閫夊彇70%浣滀负璁粌鏁版嵁锛30%浣滀负娴嬭瘯鏁版嵁 srand(unsigned(time(NULL))); random_shuffle(files.begin(), files.end()); @@ -61,13 +61,13 @@ void learn2NoPlate(float bound = 0.7) char * filePath = "train/data/plate_detect_svm/learn/NoPlate"; vector files; - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 getFiles(filePath, files ); int size = files.size(); if (0 == size) cout << "No File Found in learn NoPlate!" << endl; - ////随机选取70%作为训练数据,30%作为测试数据 + ////闅忔満閫夊彇70%浣滀负璁粌鏁版嵁锛30%浣滀负娴嬭瘯鏁版嵁 srand(unsigned(time(NULL))); random_shuffle(files.begin(), files.end()); @@ -107,7 +107,7 @@ void getHasPlateTrain(Mat& trainingImages, vector& trainingLabels, char * filePath = "train/data/plate_detect_svm/train/HasPlate"; vector files; - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 getFiles(filePath, files ); int size = files.size(); @@ -120,7 +120,7 @@ void getHasPlateTrain(Mat& trainingImages, vector& trainingLabels, //cout << files[i].c_str() << endl; Mat img = imread(files[i].c_str()); - //调用回调函数决定特征 + //璋冪敤鍥炶皟鍑芥暟鍐冲畾鐗瑰緛 Mat features; getFeatures(img, features); features = features.reshape(1, 1); @@ -138,7 +138,7 @@ void getNoPlateTrain(Mat& trainingImages, vector& trainingLabels, char * filePath = "train/data/plate_detect_svm/train/NoPlate"; vector files; - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 getFiles(filePath, files ); int size = files.size(); @@ -151,7 +151,7 @@ void getNoPlateTrain(Mat& trainingImages, vector& trainingLabels, //cout << files[i].c_str() << endl; Mat img = imread(files[i].c_str()); - //调用回调函数决定特征 + //璋冪敤鍥炶皟鍑芥暟鍐冲畾鐗瑰緛 Mat features; getFeatures(img, features); features = features.reshape(1, 1); @@ -167,7 +167,7 @@ void getHasPlateTest(vector& testingImages, vector& testingLabels) char * filePath = "train/data/plate_detect_svm/test/HasPlate"; vector files; - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 getFiles(filePath, files ); int size = files.size(); @@ -191,7 +191,7 @@ void getNoPlateTest(vector& testingImages, vector& testingLabels) char * filePath = "train/data/plate_detect_svm/test/NoPlate"; vector files; - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 getFiles(filePath, files ); int size = files.size(); @@ -210,7 +210,7 @@ void getNoPlateTest(vector& testingImages, vector& testingLabels) } -//! 测试SVM的准确率,回归率以及FScore +//! 娴嬭瘯SVM鐨勫噯纭巼锛屽洖褰掔巼浠ュ強FScore void getAccuracy(Mat& testingclasses_preditc, Mat& testingclasses_real) { int channels = testingclasses_preditc.channels(); @@ -312,13 +312,13 @@ int svmTrain(bool dividePrepared = true, bool trainPrepared = true, if (dividePrepared == false) { - //分割learn里的数据到train和test里 + //鍒嗗壊learn閲岀殑鏁版嵁鍒皌rain鍜宼est閲 cout << "Divide learn to train and test" << endl; learn2HasPlate(); learn2NoPlate(); } - //将训练数据加载入内存 + //灏嗚缁冩暟鎹姞杞藉叆鍐呭瓨 if (trainPrepared == false) { cout << "Begin to get train data to memory" << endl; @@ -335,7 +335,7 @@ int svmTrain(bool dividePrepared = true, bool trainPrepared = true, vector testingImages; vector testingLabels_real; - //将测试数据加载入内存 + //灏嗘祴璇曟暟鎹姞杞藉叆鍐呭瓨 cout << "Begin to get test data to memory" << endl; getHasPlateTest(testingImages, testingLabels_real); getNoPlateTest(testingImages, testingLabels_real); @@ -345,8 +345,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; @@ -393,7 +393,7 @@ int svmTrain(bool dividePrepared = true, bool trainPrepared = true, //cout << files[i].c_str() << endl; Mat p = testingImages[i]; - //调用回调函数决定特征 + //璋冪敤鍥炶皟鍑芥暟鍐冲畾鐗瑰緛 Mat features; getFeatures(p, features); diff --git a/src/util/deface.cpp b/src/util/deface.cpp index 3a1d970..0007484 100644 --- a/src/util/deface.cpp +++ b/src/util/deface.cpp @@ -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 #include -// 反人脸识别文件 -// 在发布数据到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; diff --git a/src/util/general_test_prepare.cpp b/src/util/general_test_prepare.cpp index acaae03..1c84427 100644 --- a/src/util/general_test_prepare.cpp +++ b/src/util/general_test_prepare.cpp @@ -1,6 +1,6 @@ -// 辅助生成general_test中的图片 -// 通用做法是使用easypr依次读取图片,并用其中的一个车牌识别文字给图片重命名 -// easypr识别的文字不一定准确,因此需要人再次确认与手工调整下 +// 杈呭姪鐢熸垚general_test涓殑鍥剧墖 +// 閫氱敤鍋氭硶鏄娇鐢╡asypr渚濇璇诲彇鍥剧墖锛屽苟鐢ㄥ叾涓殑涓涓溅鐗岃瘑鍒枃瀛楃粰鍥剧墖閲嶅懡鍚 +// easypr璇嗗埆鐨勬枃瀛椾笉涓瀹氬噯纭紝鍥犳闇瑕佷汉鍐嶆纭涓庢墜宸ヨ皟鏁翠笅 #include "../include/plate_recognize.h" #include "../include/util.h" @@ -10,12 +10,12 @@ using namespace easypr; extern const string GENERAL_TEST_PATH; -// TODO 将下面的路径改成你的 +// TODO 灏嗕笅闈㈢殑璺緞鏀规垚浣犵殑 const string your_data_path = "F:/data/easypr-data/tmp-2"; int general_test() { - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 vector files; getFiles(your_data_path, files); @@ -43,7 +43,7 @@ int general_test() string filepath = files[i].c_str(); cout << "------------------" << endl; - // EasyPR开始判断车牌 + // EasyPR寮濮嬪垽鏂溅鐗 Mat src = imread(filepath); vector plateVec; @@ -54,14 +54,14 @@ int general_test() if (num == 0) { - cout << ""<< "无车牌" < spilt_plate; SplitString(colorplate, spilt_plate, ":"); @@ -76,7 +76,7 @@ int general_test() } else { - cout << "错误码:" << result << endl; + cout << "閿欒鐮:" << result << endl; } } diff --git a/src/util/generate_gdts.cpp b/src/util/generate_gdts.cpp index d3e2dab..50480df 100644 --- a/src/util/generate_gdts.cpp +++ b/src/util/generate_gdts.cpp @@ -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瀵笹DTS鏁版嵁闆嗙殑浣跨敤涓嶄互閲忎负涓昏鎸囨爣 +// 鍙杩欎簺鍥剧墖瓒冲鍙嶆槧浣犳暟鎹泦鐨勪富瑕佺壒寰佸嵆鍙 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_default.xml"; - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 vector 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 spilt_path; SplitString(filepath, spilt_path, "\\"); int spiltsize = spilt_path.size(); @@ -110,7 +110,7 @@ int generate_gdts() -// EasyPR的图像预处理函数,进行模糊化与裁剪化处理 +// EasyPR鐨勫浘鍍忛澶勭悊鍑芥暟锛岃繘琛屾ā绯婂寲涓庤鍓寲澶勭悊 Mat imageProcess(Mat img) { int width = img.size().width; diff --git a/src/util/learn_prepare.cpp b/src/util/learn_prepare.cpp index 4a50033..9feff99 100644 --- a/src/util/learn_prepare.cpp +++ b/src/util/learn_prepare.cpp @@ -1,29 +1,29 @@ // learn data_prepare : -// 生成learn data的cpp,learn data指的是train data,verify data, test data的总和,这个名字是我起的。 -// learn data应该是贴好标签的数据,因此即便通过EasyPR自动化处理以后,也要人为的修正一下. +// 鐢熸垚learn data鐨刢pp锛宭earn data鎸囩殑鏄痶rain data锛寁erify data锛 test data鐨勬诲拰锛岃繖涓悕瀛楁槸鎴戣捣鐨勩 +// learn data搴旇鏄创濂芥爣绛剧殑鏁版嵁锛屽洜姝ゅ嵆渚块氳繃EasyPR鑷姩鍖栧鐞嗕互鍚庯紝涔熻浜轰负鐨勪慨姝d竴涓. -// 你应该按照如下的步骤和顺序组织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分块,训练,测试 +// 浣犲簲璇ユ寜鐓у涓嬬殑姝ラ鍜岄『搴忕粍缁噇earn data锛 +// 1.鐢‥asyPR瀵筺ot label data杩涜澶勭悊锛岄氳繃EasyPR杈呭姪鏉ュ杞︾墝鍥剧墖杩涜鏍囩锛堟斁鍒颁笉鍚屾枃浠跺す涓嬶級锛 +// 2.鏍囩鍒嗕袱绉嶏紝涓绉嶆槸鏈夎溅鐗岀殑锛屼竴绉嶆槸鏃犺溅鐗岀殑锛 +// 2.EasyPR鐢熸垚鏍囩浠ュ悗锛屼綘杩樺緱闇瑕佽倝鐪肩‘璁や笅锛屽皢琚笉姝g‘鏍囩鐨勬暟鎹浆绉诲埌瀹冧滑璇ュ幓鐨勬枃浠跺す涓嬶紱 +// 3.閫氳繃涓婇潰鐨勬楠わ紝姝g‘鐨勮溅鐗屽浘鐗囧拰闈炶溅鐗屽浘鐗囧凡缁忚鍒嗗埆鏀惧埌涓や釜鏂囦欢涓嬶紝鍋囪鏄痟asplate鍜宯oplate锛 +// 4.灏嗚繖涓や釜鏂囦欢澶规斁鍒癊asyPR鐩綍train/data/plate_detect_svm/learn涓嬮潰 +// 5.杩愯EasyPR锛岄夋嫨鈥滆缁冣濈洰褰曚笅鐨勨滆溅鐗屾娴嬶紙not divide锛夆濓紝杩欎釜绋嬪簭浼氳嚜鍔ㄦ妸learn data鍒嗗潡锛岃缁冿紝娴嬭瘯 #include "../include/plate_recognize.h" #include "../include/util.h" using namespace easypr; -//! 将以下路径改成你的位置 +//! 灏嗕互涓嬭矾寰勬敼鎴愪綘鐨勪綅缃 char * notlabelPath = "F:/data/easypr-data/notlabel"; char * hasPaltePath = "F:/data/easypr-data/learn/hasPlate/"; char * noPlatePath = "F:/data/easypr-data/learn/noPlate/"; -//! 读取not label data,生成learn data +//! 璇诲彇not label data锛岀敓鎴恖earn data void label_data() { - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 vector files; getFiles(notlabelPath, files); diff --git a/src/util/mc_data_prepare.cpp b/src/util/mc_data_prepare.cpp index 6b97b41..745550a 100644 --- a/src/util/mc_data_prepare.cpp +++ b/src/util/mc_data_prepare.cpp @@ -1,11 +1,17 @@ // mc_data_prepare.cpp : -// 数据预处理的程序,主要做以下两件事 -// 1.读取原生数据 rawdata,这可能有数百万张 -// 2.随机/选择性地选取部分数据成为learndata,这个根据参数设置,一般设置为1000,10000,或者1百万 +// 鏁版嵁棰勫鐞嗙殑绋嬪簭锛屼富瑕佸仛浠ヤ笅涓や欢浜 +// 1.璇诲彇鍘熺敓鏁版嵁 rawdata锛岃繖鍙兘鏈夋暟鐧句竾寮 +// 2.闅忔満/閫夋嫨鎬у湴閫夊彇閮ㄥ垎鏁版嵁鎴愪负learndata锛岃繖涓牴鎹弬鏁拌缃紝涓鑸缃负1000锛10000锛屾垨鑰1鐧句竾 #include #include + +#if defined (WIN32) || defined (_WIN32) #include +#elif defined (linux) || defined (__linux__) +#include +#endif + #include #include #include @@ -19,65 +25,65 @@ const int LEARANDATA_COUNT = 1000; void getFiles( string path, vector& files ); void SplitString(const string& s, vector& v, const string& c); -//! 省份对应map +//! 鐪佷唤瀵瑰簲map map mc_map; void Code2Province(const string& code, string& province) { if (mc_map.empty()) { - mc_map.insert(pair("E00","未识别")); - mc_map.insert(pair("A01","京")); - mc_map.insert(pair("A02","津")); - mc_map.insert(pair("A03","沪")); - mc_map.insert(pair("A04","渝")); - mc_map.insert(pair("B01","桂")); - mc_map.insert(pair("B02","蒙")); - mc_map.insert(pair("B03","宁")); - mc_map.insert(pair("B04","新")); - mc_map.insert(pair("B05","藏")); - mc_map.insert(pair("S01","皖")); - mc_map.insert(pair("S02","闽")); - mc_map.insert(pair("S03","粤")); - mc_map.insert(pair("S04","甘")); - mc_map.insert(pair("S05","贵")); - mc_map.insert(pair("S06","鄂")); - mc_map.insert(pair("S07","冀")); - mc_map.insert(pair("S08","黑")); - mc_map.insert(pair("S09","湘")); - mc_map.insert(pair("S10","豫")); - mc_map.insert(pair("S11","琼")); - mc_map.insert(pair("S12","吉")); - mc_map.insert(pair("S13","苏")); - mc_map.insert(pair("S14","赣")); - mc_map.insert(pair("S15","辽")); - mc_map.insert(pair("S16","青")); - mc_map.insert(pair("S17","川")); - mc_map.insert(pair("S18","鲁")); - mc_map.insert(pair("S19","陕")); - mc_map.insert(pair("S20","晋")); - mc_map.insert(pair("S21","云")); - mc_map.insert(pair("S22","浙")); - mc_map.insert(pair("J01","军")); - mc_map.insert(pair("J02","海")); - mc_map.insert(pair("J03","空")); - mc_map.insert(pair("J04","北")); - mc_map.insert(pair("J05","成")); - mc_map.insert(pair("J06","广")); - mc_map.insert(pair("J07","济")); - mc_map.insert(pair("J08","兰")); - mc_map.insert(pair("J09","南")); - mc_map.insert(pair("J10","沈")); + mc_map.insert(pair("E00","鏈瘑鍒")); + mc_map.insert(pair("A01","浜")); + mc_map.insert(pair("A02","娲")); + mc_map.insert(pair("A03","娌")); + mc_map.insert(pair("A04","娓")); + mc_map.insert(pair("B01","妗")); + mc_map.insert(pair("B02","钂")); + mc_map.insert(pair("B03","瀹")); + mc_map.insert(pair("B04","鏂")); + mc_map.insert(pair("B05","钘")); + mc_map.insert(pair("S01","鐨")); + mc_map.insert(pair("S02","闂")); + mc_map.insert(pair("S03","绮")); + mc_map.insert(pair("S04","鐢")); + mc_map.insert(pair("S05","璐")); + mc_map.insert(pair("S06","閯")); + mc_map.insert(pair("S07","鍐")); + mc_map.insert(pair("S08","榛")); + mc_map.insert(pair("S09","婀")); + mc_map.insert(pair("S10","璞")); + mc_map.insert(pair("S11","鐞")); + mc_map.insert(pair("S12","鍚")); + mc_map.insert(pair("S13","鑻")); + mc_map.insert(pair("S14","璧")); + mc_map.insert(pair("S15","杈")); + mc_map.insert(pair("S16","闈")); + mc_map.insert(pair("S17","宸")); + mc_map.insert(pair("S18","椴")); + mc_map.insert(pair("S19","闄")); + mc_map.insert(pair("S20","鏅")); + mc_map.insert(pair("S21","浜")); + mc_map.insert(pair("S22","娴")); + mc_map.insert(pair("J01","鍐")); + mc_map.insert(pair("J02","娴")); + mc_map.insert(pair("J03","绌")); + mc_map.insert(pair("J04","鍖")); + mc_map.insert(pair("J05","鎴")); + mc_map.insert(pair("J06","骞")); + mc_map.insert(pair("J07","娴")); + mc_map.insert(pair("J08","鍏")); + mc_map.insert(pair("J09","鍗")); + mc_map.insert(pair("J10","娌")); } if (mc_map.count(code)) province = mc_map[code]; else - province = "无"; + province = "鏃"; } -//MC:切去上部与底部干扰的细节 +//MC锛氬垏鍘讳笂閮ㄤ笌搴曢儴骞叉壈鐨勭粏鑺 Mat cutBottom(Mat img) { int width = img.size().width; @@ -87,7 +93,7 @@ Mat cutBottom(Mat img) return dst; } -//MC:filepath示例:F:\data\easypr-data\learndata\20150110132005-210028-S18-H3952K.jpg +//MC锛歠ilepath绀轰緥锛欶:\data\easypr-data\learndata\20150110132005-210028-S18-H3952K.jpg bool isNotNight(const string& filepath) { vector spilt_path; @@ -110,8 +116,8 @@ bool isNotNight(const string& filepath) datestr = spilt_name[0]; if (datestr != "") { - //"20150110132005", 时间在第6,7个位置 - //将早上10点到下午2点的图片截取出来 + //"20150110132005", 鏃堕棿鍦ㄧ6锛7涓綅缃 + //灏嗘棭涓10鐐瑰埌涓嬪崍2鐐圭殑鍥剧墖鎴彇鍑烘潵 string hourstr = datestr.substr(8, 2); if ( hourstr <= "14" && hourstr >= "10") return true; @@ -123,7 +129,7 @@ bool isNotNight(const string& filepath) return false; } -//! MC:将rawdata的文件换个路径到learndata里 +//! MC锛氬皢rawdata鐨勬枃浠舵崲涓矾寰勫埌learndata閲 bool getNewPath(const string& filepath, string& newfilepath) { string writePath = "F:/data/easypr-data/learndata/"; @@ -142,7 +148,7 @@ bool getNewPath(const string& filepath, string& newfilepath) } -//! MC:通过filepath获取车牌号码 +//! MC锛氶氳繃filepath鑾峰彇杞︾墝鍙风爜 void getPlateLicense(const string& filepath, string& plateLicense) { vector spilt_path; @@ -164,10 +170,10 @@ void getPlateLicense(const string& filepath, string& plateLicense) string provinceStr = ""; if (name_size != 0) { - // plateStr是最后一个字符串,包括后面的".jpg" + // plateStr鏄渶鍚庝竴涓瓧绗︿覆锛屽寘鎷悗闈㈢殑".jpg" plateStr = spilt_name[name_size-1]; - // 将".jpg"去掉 + // 灏".jpg"鍘绘帀 vector spilt_plate; SplitString(plateStr, spilt_plate, "."); int plate_size = spilt_plate.size(); @@ -177,7 +183,7 @@ void getPlateLicense(const string& filepath, string& plateLicense) rawplate = spilt_plate[0]; } - // provinceStr是倒数第二个字符串,主要是"S13"代表"苏" + // provinceStr鏄掓暟绗簩涓瓧绗︿覆锛屼富瑕佹槸"S13"浠h〃"鑻" provinceCode = spilt_name[name_size-2]; Code2Province(provinceCode, provinceStr); plateLicense = provinceStr + rawplate; @@ -187,12 +193,12 @@ void getPlateLicense(const string& filepath, string& plateLicense) } -//! MC:将rawdata截取部分数据到learndata中 +//! MC锛氬皢rawdata鎴彇閮ㄥ垎鏁版嵁鍒發earndata涓 void getLearnData() { char * filePath = "F:/data/easypr-data/rawdata"; - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 vector files; getFiles(filePath, files ); @@ -200,11 +206,11 @@ void getLearnData() if (0 == size) cout << "No File Found in rawdata!" << endl; - ////随机排列rawdata + ////闅忔満鎺掑垪rawdata srand(unsigned(time(NULL))); random_shuffle(files.begin(), files.end()); - ////选取前LEARANDATA_COUNT个rawdata数据作为learndata + ////閫夊彇鍓峀EARANDATA_COUNT涓猺awdata鏁版嵁浣滀负learndata int boundry = LEARANDATA_COUNT; int count = 0; cout << "Save learndata!" << endl; @@ -213,15 +219,15 @@ void getLearnData() cout << files[i].c_str() << endl; string filepath = files[i].c_str(); - //只处理白天的数据 + //鍙鐞嗙櫧澶╃殑鏁版嵁 if (isNotNight(filepath)!=true) continue; - //读取数据,并对图片进行预处理 + //璇诲彇鏁版嵁锛屽苟瀵瑰浘鐗囪繘琛岄澶勭悊 Mat img = imread(filepath); img = cutBottom(img); - //存储路径替换为新的 + //瀛樺偍璺緞鏇挎崲涓烘柊鐨 string newfilepath = ""; getNewPath(filepath, newfilepath); @@ -238,13 +244,13 @@ void getLearnData() } } -//! 将文件名称替换,重点是MC的code替换为province +//! 灏嗘枃浠跺悕绉版浛鎹紝閲嶇偣鏄疢C鐨刢ode鏇挎崲涓簆rovince void changeFileName() { //char * filePath = "F:/data/easypr-data/learndata"; char * filePath = "F:/data/PlateLocate/pic1"; - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 vector files; getFiles(filePath, files ); @@ -257,7 +263,7 @@ void changeFileName() cout << files[i].c_str() << endl; string filepath = files[i].c_str(); - //读取数据,并对图片进行预处理 + //璇诲彇鏁版嵁锛屽苟瀵瑰浘鐗囪繘琛岄澶勭悊 Mat img = imread(filepath); img = cutBottom(img); @@ -273,4 +279,4 @@ void changeFileName() } } -} \ No newline at end of file +} diff --git a/src/util/util.cpp b/src/util/util.cpp index b010d4a..4653e8c 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -1,41 +1,100 @@ +#if defined (WIN32) || defined (_WIN32) #include +#endif + #include #include + +#if defined (WIN32) || defined (_WIN32) #include +#elif defined (linux) || defined (__linux__) +#include +#include +#include + +#include +#include +#include +#endif + #include #include #include using namespace std; +#if defined (WIN32) || defined (_WIN32) + void getFiles(string path, vector& files) { - //文件句柄 - long hFile = 0; - //文件信息 - struct _finddata_t fileinfo; - string p; - if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1) - { - do - { - //如果是目录,迭代之 - //如果不是,加入列表 - if((fileinfo.attrib & _A_SUBDIR)) - { - if(strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"..") != 0) - getFiles( p.assign(path).append("\\").append(fileinfo.name), files ); - } - else - { - files.push_back(p.assign(path).append("\\").append(fileinfo.name) ); - } - }while(_findnext(hFile, &fileinfo) == 0); - _findclose(hFile); - } + //鏂囦欢鍙ユ焺 + long hFile = 0; + //鏂囦欢淇℃伅 + struct _finddata_t fileinfo; + string p; + if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1) + { + do + { + //濡傛灉鏄洰褰,杩唬涔 + //濡傛灉涓嶆槸,鍔犲叆鍒楄〃 + if((fileinfo.attrib & _A_SUBDIR)) + { + if(strcmp(fileinfo.name,".") != 0 && strcmp(fileinfo.name,"..") != 0) + getFiles( p.assign(path).append("\\").append(fileinfo.name), files ); + } + else + { + files.push_back(p.assign(path).append("\\").append(fileinfo.name) ); + } + }while(_findnext(hFile, &fileinfo) == 0); + _findclose(hFile); + } +} + +#elif defined (linux) || defined (__linux__) + +void getFiles(string path, vector& files) { + DIR *dirp = opendir(path.c_str()); + if (dirp) { + struct stat st; + struct dirent *dir; + char fullpath[512]; + while ((dir = readdir(dirp)) != NULL) { + if (!strcmp(dir->d_name, ".") || + !strcmp(dir->d_name, "..")) { + continue; + } + + sprintf(fullpath, "%s/%s", path.c_str(), dir->d_name); + + if (lstat(fullpath, &st) < 0) { + //perror("lstat"); + continue; + } + + if (S_ISDIR(st.st_mode)) { + getFiles(fullpath, files); + } else { + files.push_back(fullpath); + } + } + } + closedir(dirp); +} + +double GetTickCount() { + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + return (ts.tv_sec * 1e3 + ts.tv_nsec / 1e6); } -//C++的spilt函数 +#endif + + +//C++鐨剆pilt鍑芥暟 void SplitString(const string& s, vector& v, const string& c) { std::string::size_type pos1, pos2; @@ -53,7 +112,7 @@ void SplitString(const string& s, vector& v, const string& c) } -//! 通过文件夹名称获取文件名,不包括后缀 +//! 閫氳繃鏂囦欢澶瑰悕绉拌幏鍙栨枃浠跺悕锛屼笉鍖呮嫭鍚庣紑 void getFileName(const string& filepath, string& name) { vector spilt_path;