From d067f34e5b9eb91d30c4ac23ca182efb6ebe84bd Mon Sep 17 00:00:00 2001 From: Micooz Date: Wed, 22 Apr 2015 17:04:37 +0800 Subject: [PATCH] Convert src/* to UTF-8. --- src/core/chars_identify.cpp | 114 +++++++-------- src/core/chars_recognise.cpp | 4 +- src/core/chars_segment.cpp | 52 +++---- src/core/core_func.cpp | 90 ++++++------ src/core/plate_detect.cpp | 8 +- src/core/plate_locate.cpp | 262 +++++++++++++++++----------------- src/core/plate_recognize.cpp | 20 +-- src/include/chars_identify.h | 18 +-- src/include/chars_recognise.h | 22 +-- src/include/chars_segment.h | 38 ++--- src/include/core_func.h | 24 ++-- src/include/plate_detect.h | 20 +-- src/include/plate_locate.h | 72 +++++----- src/include/plate_recognize.h | 18 +-- src/main.cpp | 142 +++++++++--------- src/train/ann_train.cpp | 44 +++--- src/util/learn_prepare.cpp | 24 ++-- 17 files changed, 486 insertions(+), 486 deletions(-) diff --git a/src/core/chars_identify.cpp b/src/core/chars_identify.cpp index 411322b..94eb933 100644 --- a/src/core/chars_identify.cpp +++ b/src/core/chars_identify.cpp @@ -8,27 +8,27 @@ namespace easypr{ #define NDEBUG - //中国车牌 + //涓浗杞︾墝 const char strCharacters[] = {'0','1','2','3','4','5',\ - '6','7','8','9','A','B', 'C', 'D', 'E','F', 'G', 'H', /* 没有I */\ - 'J', 'K', 'L', 'M', 'N', /* 没有O */ 'P', 'Q', 'R', 'S', 'T', \ + '6','7','8','9','A','B', 'C', 'D', 'E','F', 'G', 'H', /* 娌℃湁I */\ + 'J', 'K', 'L', 'M', 'N', /* 娌℃湁O */ 'P', 'Q', 'R', 'S', 'T', \ 'U','V', 'W', 'X', 'Y', 'Z'}; - const int numCharacter = 34; /* 没有I和0,10个数字与24个英文字符之和 */ + const int numCharacter = 34; /* 娌℃湁I鍜0,10涓暟瀛椾笌24涓嫳鏂囧瓧绗︿箣鍜 */ - //以下都是我训练时用到的中文字符数据,并不全面,有些省份没有训练数据所以没有字符 - //有些后面加数字2的表示在训练时常看到字符的一种变形,也作为训练数据存储 + //浠ヤ笅閮芥槸鎴戣缁冩椂鐢ㄥ埌鐨勪腑鏂囧瓧绗︽暟鎹紝骞朵笉鍏ㄩ潰锛屾湁浜涚渷浠芥病鏈夎缁冩暟鎹墍浠ユ病鏈夊瓧绗 + //鏈変簺鍚庨潰鍔犳暟瀛2鐨勮〃绀哄湪璁粌鏃跺父鐪嬪埌瀛楃鐨勪竴绉嶅彉褰紝涔熶綔涓鸿缁冩暟鎹瓨鍌 const string strChinese[] = { - "zh_cuan" /* 川 */, "zh_e" /* 鄂 */, "zh_gan" /* 赣*/, \ - "zh_gan1"/*甘*/,"zh_gui"/* 贵 */,"zh_gui1"/* 桂 */,\ - "zh_hei" /* 黑 */, "zh_hu" /* 沪 */, "zh_ji" /* 冀 */, \ - "zh_jin" /* 津 */, "zh_jing" /* 京 */,"zh_jl" /* 吉 */, \ - "zh_liao" /* 辽 */, "zh_lu" /* 鲁 */, "zh_meng" /* 蒙 */,\ - "zh_min" /* 闽 */, "zh_ning" /* 宁 */, "zh_qing" /* 青 */,\ - "zh_qiong" /* 琼 */, "zh_shan" /* 陕 */,"zh_su" /* 苏 */, \ - "zh_sx" /* 晋 */, "zh_wan" /* 皖 */, "zh_xiang" /* 湘 */,\ - "zh_xin" /* 新 */,"zh_yu" /* 豫 */, "zh_yu1" /* 渝 */,\ - "zh_yue" /* 粤 */, "zh_yun" /* 云 */, "zh_zang" /* 藏 */,\ - "zh_zhe" /* 浙 */}; + "zh_cuan" /* 宸 */, "zh_e" /* 閯 */, "zh_gan" /* 璧*/, \ + "zh_gan1"/*鐢*/,"zh_gui"/* 璐 */,"zh_gui1"/* 妗 */,\ + "zh_hei" /* 榛 */, "zh_hu" /* 娌 */, "zh_ji" /* 鍐 */, \ + "zh_jin" /* 娲 */, "zh_jing" /* 浜 */,"zh_jl" /* 鍚 */, \ + "zh_liao" /* 杈 */, "zh_lu" /* 椴 */, "zh_meng" /* 钂 */,\ + "zh_min" /* 闂 */, "zh_ning" /* 瀹 */, "zh_qing" /* 闈 */,\ + "zh_qiong" /* 鐞 */, "zh_shan" /* 闄 */,"zh_su" /* 鑻 */, \ + "zh_sx" /* 鏅 */, "zh_wan" /* 鐨 */, "zh_xiang" /* 婀 */,\ + "zh_xin" /* 鏂 */,"zh_yu" /* 璞 */, "zh_yu1" /* 娓 */,\ + "zh_yue" /* 绮 */, "zh_yun" /* 浜 */, "zh_zang" /* 钘 */,\ + "zh_zhe" /* 娴 */}; const int numChinese = 31; const int numAll = 65; /* 34+20=54 */ @@ -42,37 +42,37 @@ CCharsIdentify::CCharsIdentify() if (m_map.empty()) { - m_map.insert(pair("zh_cuan","川")); - m_map.insert(pair("zh_e","鄂")); - m_map.insert(pair("zh_gan","赣")); - m_map.insert(pair("zh_gan1","甘")); - m_map.insert(pair("zh_gui","贵")); - m_map.insert(pair("zh_gui1","桂")); - m_map.insert(pair("zh_hei","黑")); - m_map.insert(pair("zh_hu","沪")); - m_map.insert(pair("zh_ji","冀")); - m_map.insert(pair("zh_jin","津")); - m_map.insert(pair("zh_jing","京")); - m_map.insert(pair("zh_jl","吉")); - m_map.insert(pair("zh_liao","辽")); - m_map.insert(pair("zh_lu","鲁")); - m_map.insert(pair("zh_meng","蒙")); - m_map.insert(pair("zh_min","闽")); - m_map.insert(pair("zh_ning","宁")); - m_map.insert(pair("zh_qing","青")); - m_map.insert(pair("zh_qiong","琼")); - m_map.insert(pair("zh_shan","陕")); - m_map.insert(pair("zh_su","苏")); - m_map.insert(pair("zh_sx","晋")); - m_map.insert(pair("zh_wan","皖")); - m_map.insert(pair("zh_xiang","湘")); - m_map.insert(pair("zh_xin","新")); - m_map.insert(pair("zh_yu","豫")); - m_map.insert(pair("zh_yu1","渝")); - m_map.insert(pair("zh_yue","粤")); - m_map.insert(pair("zh_yun","云")); - m_map.insert(pair("zh_zang","藏")); - 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_gan1","鐢")); + m_map.insert(pair("zh_gui","璐")); + m_map.insert(pair("zh_gui1","妗")); + m_map.insert(pair("zh_hei","榛")); + m_map.insert(pair("zh_hu","娌")); + m_map.insert(pair("zh_ji","鍐")); + m_map.insert(pair("zh_jin","娲")); + m_map.insert(pair("zh_jing","浜")); + m_map.insert(pair("zh_jl","鍚")); + m_map.insert(pair("zh_liao","杈")); + m_map.insert(pair("zh_lu","椴")); + m_map.insert(pair("zh_meng","钂")); + m_map.insert(pair("zh_min","闂")); + m_map.insert(pair("zh_ning","瀹")); + m_map.insert(pair("zh_qing","闈")); + m_map.insert(pair("zh_qiong","鐞")); + m_map.insert(pair("zh_shan","闄")); + m_map.insert(pair("zh_su","鑻")); + m_map.insert(pair("zh_sx","鏅")); + m_map.insert(pair("zh_wan","鐨")); + m_map.insert(pair("zh_xiang","婀")); + m_map.insert(pair("zh_xin","鏂")); + m_map.insert(pair("zh_yu","璞")); + m_map.insert(pair("zh_yu1","娓")); + m_map.insert(pair("zh_yue","绮")); + m_map.insert(pair("zh_yun","浜")); + m_map.insert(pair("zh_zang","钘")); + m_map.insert(pair("zh_zhe","娴")); } } @@ -93,9 +93,9 @@ void CCharsIdentify::LoadModel(string s) int CCharsIdentify::classify(Mat f, bool isChinses,bool isSpeci){ int result = -1; Mat output(1, numAll, CV_32FC1); - ann.predict(f, output);//使用ann对字符做判断 + ann.predict(f, output);//浣跨敤ann瀵瑰瓧绗﹀仛鍒ゆ柇 - if (!isChinses)//对中文字符的判断 + if (!isChinses)//瀵逛腑鏂囧瓧绗︾殑鍒ゆ柇 {if(isSpeci) {result = 0; float maxVal = -2; @@ -118,7 +118,7 @@ int CCharsIdentify::classify(Mat f, bool isChinses,bool isSpeci){ { float val = output.at(j); //cout << "j:" << j << "val:"<< val << endl; - if (val > maxVal)//求得中文字符权重最大的那个,也就是通过ann认为最可能的字符 + if (val > maxVal)//姹傚緱涓枃瀛楃鏉冮噸鏈澶х殑閭d釜锛屼篃灏辨槸閫氳繃ann璁や负鏈鍙兘鐨勫瓧绗 { maxVal = val; result = j; @@ -126,7 +126,7 @@ int CCharsIdentify::classify(Mat f, bool isChinses,bool isSpeci){ } } } - else//对数字和英文字母的判断 + else//瀵规暟瀛楀拰鑻辨枃瀛楁瘝鐨勫垽鏂 { result = numCharacter; @@ -150,7 +150,7 @@ int CCharsIdentify::classify(Mat f) { int result = -1; Mat output(1, numAll, CV_32FC1); - ann.predict(f, output);//使用ann对字符做判断 + ann.predict(f, output);//浣跨敤ann瀵瑰瓧绗﹀仛鍒ゆ柇 @@ -160,7 +160,7 @@ int CCharsIdentify::classify(Mat f) float val = output.at(j); //cout << "j:" << j << "val:"<< val << endl; if (val > maxVal) - //求得中文字符权重最大的那个,也就是通过ann认为最可能的字符 + //姹傚緱涓枃瀛楃鏉冮噸鏈澶х殑閭d釜锛屼篃灏辨槸閫氳繃ann璁や负鏈鍙兘鐨勫瓧绗 { maxVal = val; result = j; @@ -190,7 +190,7 @@ string CCharsIdentify::charsIdentify(Mat input) { Mat f = features(input, m_predictSize); string result = ""; - int index = classify(f);//使用ann来判别那个字符 + int index = classify(f);//浣跨敤ann鏉ュ垽鍒偅涓瓧绗 if (index >= numCharacter) { @@ -208,12 +208,12 @@ string CCharsIdentify::charsIdentify(Mat input) } -//输入当个字符Mat,生成字符的string +//杈撳叆褰撲釜瀛楃Mat,鐢熸垚瀛楃鐨剆tring string CCharsIdentify::charsIdentify(Mat input, bool isChinese,bool isSpeci) { Mat f = features(input, m_predictSize); string result = ""; - int index = classify(f, isChinese,isSpeci);//使用ann来判别那个字符 + int index = classify(f, isChinese,isSpeci);//浣跨敤ann鏉ュ垽鍒偅涓瓧绗 if (!isChinese) { diff --git a/src/core/chars_recognise.cpp b/src/core/chars_recognise.cpp index aab9cf0..cd04a78 100644 --- a/src/core/chars_recognise.cpp +++ b/src/core/chars_recognise.cpp @@ -23,7 +23,7 @@ namespace easypr{ } int CCharsRecognise::charsRecognise(Mat plate, string& plateLicense, int index) { - //车牌字符方块集合 + //杞︾墝瀛楃鏂瑰潡闆嗗悎 vector matVec; string plateIdentify = ""; @@ -37,7 +37,7 @@ namespace easypr{ Mat charMat = matVec[j]; bool isChinses = false; bool isSpeci=false; - //默认首个字符块是中文字符 + //榛樿棣栦釜瀛楃鍧楁槸涓枃瀛楃 if (j == 0) isChinses = true; if(j==1) diff --git a/src/core/chars_segment.cpp b/src/core/chars_segment.cpp index 32e9e9f..a10863a 100644 --- a/src/core/chars_segment.cpp +++ b/src/core/chars_segment.cpp @@ -14,7 +14,7 @@ namespace easypr{ m_LiuDingSize = DEFAULT_LIUDING_SIZE; m_theMatWidth = DEFAULT_MAT_WIDTH; - //!车牌颜色判断参数 + //锛佽溅鐗岄鑹插垽鏂弬鏁 m_ColorThreshold = DEFAULT_COLORTHRESHOLD; m_BluePercent = DEFAULT_BLUEPERCEMT; m_WhitePercent = DEFAULT_WHITEPERCEMT; @@ -22,7 +22,7 @@ namespace easypr{ m_debug = DEFAULT_DEBUG; } - //! 字符尺寸验证 + //! 瀛楃灏哄楠岃瘉 bool CCharsSegment::verifyCharSizes(Mat r){ //Char sizes 45x90 float aspect = 45.0f / 90.0f; @@ -46,12 +46,12 @@ namespace easypr{ return false; } - //! 字符预处理 + //! 瀛楃棰勫鐞 Mat CCharsSegment::preprocessChar(Mat in){ //Remap image int h = in.rows; int w = in.cols; - int charSize = CHAR_SIZE; //统一每个字符的大小 + int charSize = CHAR_SIZE; //缁熶竴姣忎釜瀛楃鐨勫ぇ灏 Mat transformMat = Mat::eye(2, 3, CV_32F); int m = max(w, h); transformMat.at(0, 2) = m / 2 - w / 2; @@ -74,7 +74,7 @@ namespace easypr{ int staticIndex = 0; int iTag = 0; - //! 字符分割与排序 + //! 瀛楃鍒嗗壊涓庢帓搴 int CCharsSegment::charsSegment(Mat input, vector& resultVec) { if (!input.data) @@ -84,7 +84,7 @@ namespace easypr{ int h = input.rows; Mat tmpMat = input(Rect(w*0.1,h*0.1,w*0.8,h*0.8)); - //判断车牌颜色以此确认threshold方法 + //鍒ゆ柇杞︾墝棰滆壊浠ユ纭threshold鏂规硶 Color plateType = getPlateType(tmpMat, true); Mat input_grey; @@ -134,7 +134,7 @@ namespace easypr{ imwrite(ss.str(), img_threshold); } - //去除车牌上方的柳钉以及下方的横线等干扰 + //鍘婚櫎杞︾墝涓婃柟鐨勬煶閽変互鍙婁笅鏂圭殑妯嚎绛夊共鎵 if(!clearLiuDing(img_threshold)) { return -3; @@ -162,7 +162,7 @@ namespace easypr{ vector vecRect; //Remove patch that are no inside limits of aspect ratio and area. - //将不符合特定尺寸的图块排除出去 + //灏嗕笉绗﹀悎鐗瑰畾灏哄鐨勫浘鍧楁帓闄ゅ嚭鍘 while (itc != contours.end()) { Rect mr = boundingRect(Mat(*itc)); @@ -177,7 +177,7 @@ namespace easypr{ return -3; vector sortedRect; - ////对符合尺寸的图块按照从左到右进行排序 + ////瀵圭鍚堝昂瀵哥殑鍥惧潡鎸夌収浠庡乏鍒板彸杩涜鎺掑簭 SortRect(vecRect, sortedRect); /*vector sortedRect(vecRect); @@ -189,7 +189,7 @@ namespace easypr{ );*/ int specIndex = 0; - //获得指示城市的特定Rect,如苏A的"A" + //鑾峰緱鎸囩ず鍩庡競鐨勭壒瀹歊ect,濡傝嫃A鐨"A" specIndex = GetSpecificRect(sortedRect); if (m_debug) @@ -203,9 +203,9 @@ namespace easypr{ } } - //根据特定Rect向左反推出中文字符 - //这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect,因此仅能 - //退过特定算法来指定 + //鏍规嵁鐗瑰畾Rect鍚戝乏鍙嶆帹鍑轰腑鏂囧瓧绗 + //杩欐牱鍋氱殑涓昏鍘熷洜鏄牴鎹甪indContours鏂规硶寰堥毦鎹曟崏鍒颁腑鏂囧瓧绗︾殑鍑嗙‘Rect锛屽洜姝や粎鑳 + //閫杩囩壒瀹氱畻娉曟潵鎸囧畾 Rect chineseRect; if (specIndex < sortedRect.size()) chineseRect = GetChineseRect(sortedRect[specIndex]); @@ -221,9 +221,9 @@ namespace easypr{ } - //新建一个全新的排序Rect - //将中文字符Rect第一个加进来,因为它肯定是最左边的 - //其余的Rect只按照顺序去6个,车牌只可能是7个字符!这样可以避免阴影导致的“1”字符 + //鏂板缓涓涓叏鏂扮殑鎺掑簭Rect + //灏嗕腑鏂囧瓧绗ect绗竴涓姞杩涙潵锛屽洜涓哄畠鑲畾鏄渶宸﹁竟鐨 + //鍏朵綑鐨凴ect鍙寜鐓ч『搴忓幓6涓紝杞︾墝鍙彲鑳芥槸7涓瓧绗︼紒杩欐牱鍙互閬垮厤闃村奖瀵艰嚧鐨勨1鈥濆瓧绗 vector newSortedRect; newSortedRect.push_back(chineseRect); RebuildRect(sortedRect, newSortedRect, specIndex); @@ -254,7 +254,7 @@ namespace easypr{ return 0; } - //! 将Rect按位置从左到右进行排序 + //! 灏哛ect鎸変綅缃粠宸﹀埌鍙宠繘琛屾帓搴 int CCharsSegment::SortRect(const vector& vecRect, vector& out) { vector orderIndex; @@ -298,7 +298,7 @@ namespace easypr{ return 0; } - //! 根据特殊车牌来构造猜测中文字符的位置和大小 + //! 鏍规嵁鐗规畩杞︾墝鏉ユ瀯閫犵寽娴嬩腑鏂囧瓧绗︾殑浣嶇疆鍜屽ぇ灏 Rect CCharsSegment::GetChineseRect(const Rect rectSpe) { int height = rectSpe.height; @@ -314,7 +314,7 @@ namespace easypr{ return a; } - //! 找出指示城市的字符的Rect,例如苏A7003X,就是"A"的位置 + //! 鎵惧嚭鎸囩ず鍩庡競鐨勫瓧绗︾殑Rect锛屼緥濡傝嫃A7003X锛屽氨鏄"A"鐨勪綅缃 int CCharsSegment::GetSpecificRect(const vector& vecRect) { vector xpositions; @@ -341,8 +341,8 @@ namespace easypr{ Rect mr = vecRect[i]; int midx = mr.x + mr.width / 2; - //如果一个字符有一定的大小,并且在整个车牌的1/7到2/7之间,则是我们要找的特殊字符 - //当前字符和下个字符的距离在一定的范围内 + //濡傛灉涓涓瓧绗︽湁涓瀹氱殑澶у皬锛屽苟涓斿湪鏁翠釜杞︾墝鐨1/7鍒2/7涔嬮棿锛屽垯鏄垜浠鎵剧殑鐗规畩瀛楃 + //褰撳墠瀛楃鍜屼笅涓瓧绗︾殑璺濈鍦ㄤ竴瀹氱殑鑼冨洿鍐 if ((mr.width > maxWidth * 0.8 || mr.height > maxHeight * 0.8) && (midx < int(m_theMatWidth / 7) * 2 && midx > int(m_theMatWidth / 7) * 1)) { @@ -353,17 +353,17 @@ namespace easypr{ return specIndex; } - //! 这个函数做两个事情 - // 1.把特殊字符Rect左边的全部Rect去掉,后面再重建中文字符的位置。 - // 2.从特殊字符Rect开始,依次选择6个Rect,多余的舍去。 + //! 杩欎釜鍑芥暟鍋氫袱涓簨鎯 + // 1.鎶婄壒娈婂瓧绗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/core_func.cpp b/src/core/core_func.cpp index f5994c9..aef1517 100644 --- a/src/core/core_func.cpp +++ b/src/core/core_func.cpp @@ -1,6 +1,6 @@ -// 这个文件定义了EasyPR里所有plate判断的通用函数 -// 所属命名空间为easypr -// 这个部分中的函数轻易不要改动 +// 杩欎釜鏂囦欢瀹氫箟浜咵asyPR閲屾墍鏈塸late鍒ゆ柇鐨勯氱敤鍑芥暟 +// 鎵灞炲懡鍚嶇┖闂翠负easypr +// 杩欎釜閮ㄥ垎涓殑鍑芥暟杞绘槗涓嶈鏀瑰姩 #include "../include/prep.h" #include "../include/core_func.h" @@ -10,30 +10,30 @@ Namespace where all the C++ EasyPR functionality resides */ namespace easypr { - //! 根据一幅图像与颜色模板获取对应的二值图 - //! 输入RGB图像, 颜色模板(蓝色、黄色) - //! 输出灰度图(只有0和255两个值,255代表匹配,0代表不匹配) + //! 鏍规嵁涓骞呭浘鍍忎笌棰滆壊妯℃澘鑾峰彇瀵瑰簲鐨勪簩鍊煎浘 + //! 杈撳叆RGB鍥惧儚, 棰滆壊妯℃澘锛堣摑鑹层侀粍鑹诧級 + //! 杈撳嚭鐏板害鍥撅紙鍙湁0鍜255涓や釜鍊硷紝255浠h〃鍖归厤锛0浠h〃涓嶅尮閰嶏級 Mat colorMatch(const Mat& src, Mat& match, const Color r, const bool adaptive_minsv) { - // S和V的最小值由adaptive_minsv这个bool值判断 - // 如果为true,则最小值取决于H值,按比例衰减 - // 如果为false,则不再自适应,使用固定的最小值minabs_sv - // 默认为false + // S鍜孷鐨勬渶灏忓肩敱adaptive_minsv杩欎釜bool鍊煎垽鏂 + // 濡傛灉涓簍rue锛屽垯鏈灏忓煎彇鍐充簬H鍊硷紝鎸夋瘮渚嬭“鍑 + // 濡傛灉涓篺alse锛屽垯涓嶅啀鑷傚簲锛屼娇鐢ㄥ浐瀹氱殑鏈灏忓糾inabs_sv + // 榛樿涓篺alse const float max_sv = 255; const float minref_sv = 64; const float minabs_sv = 95; - //blue的H范围 + //blue鐨凥鑼冨洿 const int min_blue = 100; //100 const int max_blue = 140; //140 - //yellow的H范围 + //yellow鐨凥鑼冨洿 const int min_yellow = 15; //15 const int max_yellow = 40; //40 Mat src_hsv; - // 转到HSV空间进行处理,颜色搜索主要使用的是H分量进行蓝色与黄色的匹配工作 + // 杞埌HSV绌洪棿杩涜澶勭悊锛岄鑹叉悳绱富瑕佷娇鐢ㄧ殑鏄疕鍒嗛噺杩涜钃濊壊涓庨粍鑹茬殑鍖归厤宸ヤ綔 cvtColor(src, src_hsv, CV_BGR2HSV); vector hsvSplit; @@ -41,7 +41,7 @@ namespace easypr { equalizeHist(hsvSplit[2], hsvSplit[2]); merge(hsvSplit, src_hsv); - //匹配模板基色,切换以查找想要的基色 + //鍖归厤妯℃澘鍩鸿壊,鍒囨崲浠ユ煡鎵炬兂瑕佺殑鍩鸿壊 int min_h = 0; int max_h = 0; switch (r) { @@ -60,10 +60,10 @@ namespace easypr { int channels = src_hsv.channels(); int nRows = src_hsv.rows; - //图像数据列需要考虑通道数的影响; + //鍥惧儚鏁版嵁鍒楅渶瑕佽冭檻閫氶亾鏁扮殑褰卞搷锛 int nCols = src_hsv.cols * channels; - if (src_hsv.isContinuous())//连续存储的数据,按一行处理 + if (src_hsv.isContinuous())//杩炵画瀛樺偍鐨勬暟鎹紝鎸変竴琛屽鐞 { nCols *= nRows; nRows = 1; @@ -99,9 +99,9 @@ namespace easypr { float Hdiff_p = float(Hdiff) / diff_h; - // S和V的最小值由adaptive_minsv这个bool值判断 - // 如果为true,则最小值取决于H值,按比例衰减 - // 如果为false,则不再自适应,使用固定的最小值minabs_sv + // S鍜孷鐨勬渶灏忓肩敱adaptive_minsv杩欎釜bool鍊煎垽鏂 + // 濡傛灉涓簍rue锛屽垯鏈灏忓煎彇鍐充簬H鍊硷紝鎸夋瘮渚嬭“鍑 + // 濡傛灉涓篺alse锛屽垯涓嶅啀鑷傚簲锛屼娇鐢ㄥ浐瀹氱殑鏈灏忓糾inabs_sv float min_sv = 0; if (true == adaptive_minsv) min_sv = minref_sv - minref_sv / 2 * (1 - Hdiff_p); // inref_sv - minref_sv / 2 * (1 - Hdiff_p) @@ -124,7 +124,7 @@ namespace easypr { //cout << "avg_s:" << s_all / count << endl; //cout << "avg_v:" << v_all / count << endl; - // 获取颜色匹配后的二值灰度图 + // 鑾峰彇棰滆壊鍖归厤鍚庣殑浜屽肩伆搴﹀浘 Mat src_grey; vector hsvSplit_done; split(src_hsv, hsvSplit_done); @@ -137,9 +137,9 @@ namespace easypr { bool bFindLeftRightBound1(Mat& bound_threshold,int& posLeft,int& posRight) { - //从两边寻找边界 + //浠庝袱杈瑰鎵捐竟鐣 int span = bound_threshold.rows*0.2; - //左边界检测 + //宸﹁竟鐣屾娴 for (int i=0; i < bound_threshold.cols-span-1;i+=3) { int whiteCount = 0; @@ -162,7 +162,7 @@ namespace easypr { } span = bound_threshold.rows*0.2; - //右边界检测 + //鍙宠竟鐣屾娴 for (int i=bound_threshold.cols-1; i > span;i-=2) { int whiteCount = 0; @@ -204,9 +204,9 @@ namespace easypr { bool bFindLeftRightBound(Mat& bound_threshold,int& posLeft,int& posRight) { - //从两边寻找边界 + //浠庝袱杈瑰鎵捐竟鐣 int span = bound_threshold.rows*0.2; - //左边界检测 + //宸﹁竟鐣屾娴 for (int i=0; i < bound_threshold.cols-span-1;i+=2) { int whiteCount = 0; @@ -229,7 +229,7 @@ namespace easypr { } span = bound_threshold.rows*0.2; - //右边界检测 + //鍙宠竟鐣屾娴 for (int i=bound_threshold.cols-1; i > span;i-=2) { int whiteCount = 0; @@ -262,9 +262,9 @@ namespace easypr { bool bFindLeftRightBound2(Mat& bound_threshold,int& posLeft,int& posRight) { - //从两边寻找边界 + //浠庝袱杈瑰鎵捐竟鐣 int span = bound_threshold.rows*0.2; - //左边界检测 + //宸﹁竟鐣屾娴 for (int i=0; i < bound_threshold.cols-span-1;i+=3) { int whiteCount = 0; @@ -287,7 +287,7 @@ namespace easypr { } span = bound_threshold.rows*0.2; - //右边界检测 + //鍙宠竟鐣屾娴 for (int i=bound_threshold.cols-1; i > span;i-=3) { int whiteCount = 0; @@ -318,12 +318,12 @@ namespace easypr { } - //! 判断一个车牌的颜色 - //! 输入车牌mat与颜色模板 - //! 返回true或fasle + //! 鍒ゆ柇涓涓溅鐗岀殑棰滆壊 + //! 杈撳叆杞︾墝mat涓庨鑹叉ā鏉 + //! 杩斿洖true鎴杅asle bool plateColorJudge(const Mat& src, const Color r, const bool adaptive_minsv) { - // 判断阈值 + // 鍒ゆ柇闃堝 const float thresh = 0.45; Mat src_gray; @@ -339,7 +339,7 @@ namespace easypr { } //getPlateType - //判断车牌的类型 + //鍒ゆ柇杞︾墝鐨勭被鍨 Color getPlateType(const Mat& src, const bool adaptive_minsv) { if (plateColorJudge(src, BLUE, adaptive_minsv) == true) { @@ -370,7 +370,7 @@ namespace easypr { if (img.at(i, j) != img.at(i, j + 1)) jumpCount++; - if (img.at(i,j) == 255) + if (img.at(i, j) == 255) { whiteCount++; } @@ -394,9 +394,9 @@ namespace easypr { } } - //去除车牌上方的钮钉 - //计算每行元素的阶跃数,如果小于X认为是柳丁,将此行全部填0(涂黑) - //X的推荐值为,可根据实际调整 + //鍘婚櫎杞︾墝涓婃柟鐨勯挳閽 + //璁$畻姣忚鍏冪礌鐨勯樁璺冩暟锛屽鏋滃皬浜嶺璁や负鏄煶涓侊紝灏嗘琛屽叏閮ㄥ~0锛堟秱榛戯級 + //X鐨勬帹鑽愬间负锛屽彲鏍规嵁瀹為檯璋冩暣 bool clearLiuDing(Mat& img) { @@ -431,7 +431,7 @@ namespace easypr { } } - ////这样的不是车牌 + ////杩欐牱鐨勪笉鏄溅鐗 if (iCount*1.0/img.rows < 0.5) { return false; @@ -491,7 +491,7 @@ namespace easypr { } - //ok,找到上下边界 + //ok,鎵惧埌涓婁笅杈圭晫 for (int i = mask.rows-1; i >= mask.rows/2; i--) { int jumpCount = 0; @@ -572,7 +572,7 @@ namespace easypr { return thresholdV; } - //! 直方图均衡 + //! 鐩存柟鍥惧潎琛 Mat histeq(Mat in) { Mat out(in.size(), in.type()); @@ -609,7 +609,7 @@ namespace easypr { int numCols=vhist.cols+hhist.cols+lowData.cols*lowData.cols; Mat out=Mat::zeros(1,numCols,CV_32F); - //Asign values to feature,ANN的样本特征为水平、垂直直方图和低分辨率图像所组成的矢量 + //Asign values to feature,ANN鐨勬牱鏈壒寰佷负姘村钩銆佸瀭鐩寸洿鏂瑰浘鍜屼綆鍒嗚鲸鐜囧浘鍍忔墍缁勬垚鐨勭煝閲 int j=0; for(int i=0; i(j) =countNonZero(data); //统计这一行或一列中,非零元素的个数,并保存到mhist中 + mhist.at(j) =countNonZero(data); //缁熻杩欎竴琛屾垨涓鍒椾腑锛岄潪闆跺厓绱犵殑涓暟锛屽苟淇濆瓨鍒癿hist涓 } //Normalize histogram @@ -692,7 +692,7 @@ namespace easypr { minMaxLoc(mhist, &min, &max); if (max>0) - mhist.convertTo(mhist, -1, 1.0f / max, 0);//用mhist直方图中的最大值,归一化直方图 + mhist.convertTo(mhist, -1, 1.0f / max, 0);//鐢╩hist鐩存柟鍥句腑鐨勬渶澶у硷紝褰掍竴鍖栫洿鏂瑰浘 return mhist; } diff --git a/src/core/plate_detect.cpp b/src/core/plate_detect.cpp index dc36a25..d4f0a97 100644 --- a/src/core/plate_detect.cpp +++ b/src/core/plate_detect.cpp @@ -11,7 +11,7 @@ CPlateDetect::CPlateDetect() m_plateLocate = new CPlateLocate(); m_plateJudge = new CPlateJudge(); - // 默认EasyPR在一幅图中定位最多3个车 + // 榛樿EasyPR鍦ㄤ竴骞呭浘涓畾浣嶆渶澶3涓溅 m_maxPlates = 3; } @@ -22,7 +22,7 @@ void CPlateDetect::LoadSVM(string s) int CPlateDetect::plateDetect(Mat src, vector& resultVec, int index) { - //可能是车牌的图块集合 + //鍙兘鏄溅鐗岀殑鍥惧潡闆嗗悎 vector matVec; int resultLo = m_plateLocate->plateLocate(src, matVec); @@ -67,7 +67,7 @@ int CPlateDetect::plateDetectDeep(Mat src, vector& resultVec, bool showD vector all_result_Plates; - //如果颜色查找找到n个以上(包含n个)的车牌,就不再进行Sobel查找了。 + //濡傛灉棰滆壊鏌ユ壘鎵惧埌n涓互涓婏紙鍖呭惈n涓級鐨勮溅鐗岋紝灏变笉鍐嶈繘琛孲obel鏌ユ壘浜嗐 const int color_find_max = m_maxPlates; m_plateLocate->plateColorLocate(src, color_Plates, index); @@ -104,7 +104,7 @@ int CPlateDetect::plateDetectDeep(Mat src, vector& resultVec, bool showD for (int i = 0; i < all_result_Plates.size(); i++) { - // 把截取的车牌图像依次放到左上角 + // 鎶婃埅鍙栫殑杞︾墝鍥惧儚渚濇鏀惧埌宸︿笂瑙 CPlate plate = all_result_Plates[i]; resultVec.push_back(plate); } diff --git a/src/core/plate_locate.cpp b/src/core/plate_locate.cpp index 3bf12be..968b12d 100644 --- a/src/core/plate_locate.cpp +++ b/src/core/plate_locate.cpp @@ -27,8 +27,8 @@ CPlateLocate::CPlateLocate() m_labItem = NULL; } -//! 生活模式与工业模式切换 -//! 如果为真,则设置各项参数为定位生活场景照片(如百度图片)的参数,否则恢复默认值。 +//! 鐢熸椿妯″紡涓庡伐涓氭ā寮忓垏鎹 +//! 濡傛灉涓虹湡锛屽垯璁剧疆鍚勯」鍙傛暟涓哄畾浣嶇敓娲诲満鏅収鐗囷紙濡傜櫨搴﹀浘鐗囷級鐨勫弬鏁帮紝鍚﹀垯鎭㈠榛樿鍊笺 void CPlateLocate::setLifemode(bool param) { if(param == true) @@ -54,12 +54,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 //Real car plate size: 136 * 32, aspect 4 float aspect = m_aspect; @@ -85,7 +85,7 @@ bool CPlateLocate::verifySizes(RotatedRect mr) return true; } -//! 显示最终生成的车牌图像,便于判断是否成功进行了旋转。 +//! 鏄剧ず鏈缁堢敓鎴愮殑杞︾墝鍥惧儚锛屼究浜庡垽鏂槸鍚︽垚鍔熻繘琛屼簡鏃嬭浆銆 Mat CPlateLocate::showResultMat(Mat src, Size rect_size, Point2f center, int index) { Mat img_crop; @@ -115,17 +115,17 @@ Mat CPlateLocate::showResultMat(Mat src, Size rect_size, Point2f center, int ind } -// !基于HSV空间的颜色搜索方法 +// !鍩轰簬HSV绌洪棿鐨勯鑹叉悳绱㈡柟娉 int CPlateLocate::colorSearch(const Mat& src, const Color r, Mat& out, vector& outRects, int index) { Mat match_grey; - // width值对最终结果影响很大,可以考虑进行多次colorSerch,每次不同的值 - // 另一种解决方案就是在结果输出到SVM之前,进行线与角的再纠正 + // width鍊煎鏈缁堢粨鏋滃奖鍝嶅緢澶э紝鍙互鑰冭檻杩涜澶氭colorSerch锛屾瘡娆′笉鍚岀殑鍊 + // 鍙︿竴绉嶈В鍐虫柟妗堝氨鏄湪缁撴灉杈撳嚭鍒癝VM涔嬪墠锛岃繘琛岀嚎涓庤鐨勫啀绾犳 const int color_morph_width = 10; const int color_morph_height = 2; - // 进行颜色查找 + // 杩涜棰滆壊鏌ユ壘 colorMatch(src, match_grey, r, false); @@ -144,14 +144,14 @@ int CPlateLocate::colorSearch(const Mat& src, const Color r, Mat& out, vector > contours; - // 注意,findContours会改变src_threshold - // 因此要输出src_threshold必须在这之前使用copyTo方法 + // 娉ㄦ剰锛宖indContours浼氭敼鍙榮rc_threshold + // 鍥犳瑕佽緭鍑簊rc_threshold蹇呴』鍦ㄨ繖涔嬪墠浣跨敤copyTo鏂规硶 findContours(src_threshold, contours, // a vector of contours - CV_RETR_EXTERNAL, // 提取外部轮廓 + CV_RETR_EXTERNAL, // 鎻愬彇澶栭儴杞粨 CV_CHAIN_APPROX_NONE); // all pixels of each contours vector>::iterator itc = contours.begin(); @@ -159,7 +159,7 @@ int CPlateLocate::colorSearch(const Mat& src, const Color r, Mat& out, vector>& outRects) { Mat src_threshold; - //soble操作,得到二值图像 + //soble鎿嶄綔锛屽緱鍒颁簩鍊煎浘鍍 sobelOper(src, src_threshold, m_GaussianBlurSize, m_MorphSizeWidth, m_MorphSizeHeight); @@ -258,7 +258,7 @@ int CPlateLocate::sobelFrtSearch(const Mat& src, vector>& outRects) vector< vector< Point> > contours; findContours(src_threshold, contours, // a vector of contours - CV_RETR_EXTERNAL, // 提取外部轮廓 + CV_RETR_EXTERNAL, // 鎻愬彇澶栭儴杞粨 CV_CHAIN_APPROX_NONE); // all pixels of each contours vector>::iterator itc = contours.begin(); @@ -269,7 +269,7 @@ int CPlateLocate::sobelFrtSearch(const Mat& src, vector>& outRects) { RotatedRect mr = minAreaRect(Mat(*itc)); - // 需要进行大小尺寸判断 + // 闇瑕佽繘琛屽ぇ灏忓昂瀵稿垽鏂 if (!verifySizes(mr)) itc = contours.erase(itc); else { @@ -297,16 +297,16 @@ int CPlateLocate::sobelFrtSearch(const Mat& src, vector>& outRects) -//! Sobel第二次搜索,对断裂的部分进行再次的处理 -//! 对大小和形状做限制,生成参考坐标 +//! Sobel绗簩娆℃悳绱,瀵规柇瑁傜殑閮ㄥ垎杩涜鍐嶆鐨勫鐞 +//! 瀵瑰ぇ灏忓拰褰㈢姸鍋氶檺鍒讹紝鐢熸垚鍙傝冨潗鏍 int CPlateLocate::sobelSecSearchPart( Mat& bound, Point2f refpoint, vector& outRects) { Mat bound_threshold; - ////! 第二次参数比一次精细,但针对的是得到的外接矩阵之后的图像,再sobel得到二值图像 + ////! 绗簩娆″弬鏁版瘮涓娆$簿缁嗭紝浣嗛拡瀵圭殑鏄緱鍒扮殑澶栨帴鐭╅樀涔嬪悗鐨勫浘鍍忥紝鍐峴obel寰楀埌浜屽煎浘鍍 sobelOperT(bound, bound_threshold, 3, 6, 2); - ////二值化去掉两边的边界 + ////浜屽煎寲鍘绘帀涓よ竟鐨勮竟鐣 //Mat mat_gray; //cvtColor(bound,mat_gray,CV_BGR2GRAY); @@ -327,7 +327,7 @@ int CPlateLocate::sobelSecSearchPart( Mat& bound, Point2f refpoint, vector > contours; findContours(bound_threshold, contours, // a vector of contours - CV_RETR_EXTERNAL, // 提取外部轮廓 + CV_RETR_EXTERNAL, // 鎻愬彇澶栭儴杞粨 CV_CHAIN_APPROX_NONE); // all pixels of each contours vector>::iterator itc = contours.begin(); @@ -386,13 +386,13 @@ int CPlateLocate::sobelSecSearchPart( Mat& bound, Point2f refpoint, vector& outRects) { Mat bound_threshold; - //! 第二次参数比一次精细,但针对的是得到的外接矩阵之后的图像,再sobel得到二值图像 + //! 绗簩娆″弬鏁版瘮涓娆$簿缁嗭紝浣嗛拡瀵圭殑鏄緱鍒扮殑澶栨帴鐭╅樀涔嬪悗鐨勫浘鍍忥紝鍐峴obel寰楀埌浜屽煎浘鍍 sobelOper(bound, bound_threshold, 3, 10, 3); //Mat tempBoundThread = bound_threshold.clone(); @@ -403,7 +403,7 @@ int CPlateLocate::sobelSecSearch(Mat& bound, Point2f refpoint, vector > contours; findContours(bound_threshold, contours, // a vector of contours - CV_RETR_EXTERNAL, // 提取外部轮廓 + CV_RETR_EXTERNAL, // 鎻愬彇澶栭儴杞粨 CV_CHAIN_APPROX_NONE); // all pixels of each contours vector>::iterator itc = contours.begin(); @@ -465,8 +465,8 @@ int CPlateLocate::sobelSecSearch(Mat& bound, Point2f refpoint, vector& inRects, vector& outPlates) { @@ -611,7 +611,7 @@ int CPlateLocate::deskew(const Mat& src, const Mat& src_b, vector& } else { - // 角度在5到60度之间的,首先需要旋转 rotation + // 瑙掑害鍦5鍒60搴︿箣闂寸殑锛岄鍏堥渶瑕佹棆杞 rotation Mat rotated_mat; Mat rotated_mat_b; @@ -621,12 +621,12 @@ int CPlateLocate::deskew(const Mat& src, const Mat& src_b, vector& if (!rotation(bound_mat_b, rotated_mat_b, roi_rect_size, roi_ref_center, roi_angle)) continue; - // 如果图片偏斜,还需要视角转换 affine + // 濡傛灉鍥剧墖鍋忔枩锛岃繕闇瑕佽瑙掕浆鎹 affine double roi_slope = 0; //imshow("1roated_mat",rotated_mat); //imshow("rotated_mat_b",rotated_mat_b); if (isdeflection(rotated_mat_b, roi_angle, roi_slope)) - {/*cout<<"roi_slope的大小"<& DeleteNotArea(deskew_mat); - //如果图像大于我们所要求的图像,对图像进行一个大小变更 + //濡傛灉鍥惧儚澶т簬鎴戜滑鎵瑕佹眰鐨勫浘鍍忥紝瀵瑰浘鍍忚繘琛屼竴涓ぇ灏忓彉鏇 if (deskew_mat.cols >= WIDTH || deskew_mat.rows >= HEIGHT) resize(deskew_mat, plate_mat, plate_mat.size(), 0, 0, INTER_AREA); else @@ -664,7 +664,7 @@ int CPlateLocate::deskew(const Mat& src, const Mat& src_b, vector& return 0; } -//! 旋转操作 +//! 鏃嬭浆鎿嶄綔 bool CPlateLocate::rotation(Mat& in, Mat& out, const Size rect_size, const Point2f center, const double angle) { Mat in_large; @@ -713,8 +713,8 @@ bool CPlateLocate::rotation(Mat& in, Mat& out, const Size rect_size, const Point } -//! 是否偏斜 -//! 输入二值化图像,输出判断结果 +//! 鏄惁鍋忔枩 +//! 杈撳叆浜屽煎寲鍥惧儚锛岃緭鍑哄垽鏂粨鏋 bool CPlateLocate::isdeflection(const Mat& in, const double angle, double& slope) {/*imshow("in",in); waitKey(0);*/ @@ -748,19 +748,19 @@ waitKey(0);*/ //cout << "len[0]:" << len[0] << endl; //cout << "len[1]:" << len[1] << endl; //cout << "len[2]:" << len[2] << endl; - //len[0]/len[1]/len[2]这三个应该是取车牌边线的值,来计算车牌边线的斜率 + //len[0]/len[1]/len[2]杩欎笁涓簲璇ユ槸鍙栬溅鐗岃竟绾跨殑鍊硷紝鏉ヨ绠楄溅鐗岃竟绾跨殑鏂滅巼 double maxlen = max(len[2], len[0]); double minlen = min(len[2], len[0]); double difflen = abs(len[2] - len[0]); //cout << "nCols:" << nCols << endl; double PI = 3.14159265; - //angle是根据水平那根直线的斜率转换过来的角度 + //angle鏄牴鎹按骞抽偅鏍圭洿绾跨殑鏂滅巼杞崲杩囨潵鐨勮搴 double g = tan(angle * PI / 180.0); if (maxlen - len[1] > nCols/32 || len[1] - minlen > nCols/32 ) { - // 如果斜率为正,则底部在下,反之在上 - double slope_can_1 = double(len[2] - len[0]) / double(comp_index[1]);//求直线的斜率 + // 濡傛灉鏂滅巼涓烘锛屽垯搴曢儴鍦ㄤ笅锛屽弽涔嬪湪涓 + double slope_can_1 = double(len[2] - len[0]) / double(comp_index[1]);//姹傜洿绾跨殑鏂滅巼 double slope_can_2 = double(len[1] - len[0]) / double(comp_index[0]); double slope_can_3 = double(len[2] - len[1]) / double(comp_index[0]); //cout<<"angle:"< 0) { - //右偏型,新起点坐标系在xiff/2位置 + //鍙冲亸鍨嬶紝鏂拌捣鐐瑰潗鏍囩郴鍦▁iff/2浣嶇疆 plTri[0] = Point2f(0, 0); plTri[1] = Point2f(width - xiff - 1, 0); plTri[2] = Point2f(0 + xiff, height - 1); @@ -812,7 +812,7 @@ void CPlateLocate::affine(const Mat& in, Mat& out, const double slope) } else { - //左偏型,新起点坐标系在 -xiff/2位置 + //宸﹀亸鍨嬶紝鏂拌捣鐐瑰潗鏍囩郴鍦 -xiff/2浣嶇疆 plTri[0] = Point2f(0 + xiff, 0); plTri[1] = Point2f(width - 1, 0); plTri[2] = Point2f(0, height - 1); @@ -832,7 +832,7 @@ void CPlateLocate::affine(const Mat& in, Mat& out, const double slope) affine_mat.create(height, width, TYPE); if (in.rows > HEIGHT || in.cols > WIDTH) - warpAffine(in, affine_mat, warp_mat, affine_mat.size(), CV_INTER_AREA);//仿射变换 + warpAffine(in, affine_mat, warp_mat, affine_mat.size(), CV_INTER_AREA);//浠垮皠鍙樻崲 else warpAffine(in, affine_mat, warp_mat, affine_mat.size(), CV_INTER_CUBIC); @@ -843,16 +843,16 @@ void CPlateLocate::affine(const Mat& in, Mat& out, const double slope) } -//! 计算一个安全的Rect -//! 如果不存在,返回false +//! 璁$畻涓涓畨鍏ㄧ殑Rect +//! 濡傛灉涓嶅瓨鍦紝杩斿洖false bool CPlateLocate::calcSafeRect(const RotatedRect& roi_rect, const Mat& src, Rect_& safeBoundRect) { Rect_ boudRect = roi_rect.boundingRect(); - // boudRect的左上的x和y有可能小于0 + // boudRect鐨勫乏涓婄殑x鍜寉鏈夊彲鑳藉皬浜0 float tl_x = boudRect.x > 0 ? boudRect.x : 0; float tl_y = boudRect.y > 0 ? boudRect.y : 0; - // boudRect的右下的x和y有可能大于src的范围 + // boudRect鐨勫彸涓嬬殑x鍜寉鏈夊彲鑳藉ぇ浜巗rc鐨勮寖鍥 float br_x = boudRect.x + boudRect.width < src.cols ? boudRect.x + boudRect.width - 1 : src.cols - 1; float br_y = boudRect.y + boudRect.height < src.rows ? @@ -864,7 +864,7 @@ bool CPlateLocate::calcSafeRect(const RotatedRect& roi_rect, const Mat& src, Rec if (roi_width <= 0 || roi_height <= 0) return false; - // 新建一个mat,确保地址不越界,以防mat定位roi时抛异常 + // 鏂板缓涓涓猰at锛岀‘淇濆湴鍧涓嶈秺鐣岋紝浠ラ槻mat瀹氫綅roi鏃舵姏寮傚父 safeBoundRect = Rect_(tl_x, tl_y, roi_width, roi_height); return true; @@ -895,10 +895,10 @@ int CPlateLocate::deskewOld(Mat src, vector& inRects, { Rect_ boudRect = minRect.boundingRect(); - // boudRect的左上的x和y有可能小于0 + // boudRect鐨勫乏涓婄殑x鍜寉鏈夊彲鑳藉皬浜0 float tl_x = boudRect.x > 0 ? boudRect.x : 0; float tl_y = boudRect.y > 0 ? boudRect.y : 0; - // boudRect的右上的x和y有可能大于src的范围 + // boudRect鐨勫彸涓婄殑x鍜寉鏈夊彲鑳藉ぇ浜巗rc鐨勮寖鍥 float br_x = boudRect.x + boudRect.width < src.cols ? boudRect.x + boudRect.width - 1 : src.cols - 1; float br_y = boudRect.y + boudRect.height < src.rows ? @@ -910,7 +910,7 @@ int CPlateLocate::deskewOld(Mat src, vector& inRects, if (roi_width <= 0 || roi_height <= 0) continue; - // 新建一个mat,确保地址不越界,以防mat定位roi时抛异常 + // 鏂板缓涓涓猰at锛岀‘淇濆湴鍧涓嶈秺鐣岋紝浠ラ槻mat瀹氫綅roi鏃舵姏寮傚父 Rect_ roiRect = Rect_(tl_x, tl_y, roi_width, roi_height); Mat src_mat = src(roiRect); @@ -923,19 +923,19 @@ int CPlateLocate::deskewOld(Mat src, vector& inRects, Mat img_crop; if (0.0 == angle || 90.0 == angle || -90.0 == angle || -0.0 == angle) { - // 如果角度等于这些值,则不需要旋转,直接就是正矩形 - // 以免带来旋转与裁剪中的线性插值带来的误差与模糊 + // 濡傛灉瑙掑害绛変簬杩欎簺鍊硷紝鍒欎笉闇瑕佹棆杞紝鐩存帴灏辨槸姝g煩褰 + // 浠ュ厤甯︽潵鏃嬭浆涓庤鍓腑鐨勭嚎鎬ф彃鍊煎甫鏉ョ殑璇樊涓庢ā绯 img_crop = src_mat; } else if (angle - 5 < 0 && angle + 5 > 0) { - // 如果角度小于5度,则不必旋转,直接显示 - // 以免带来旋转与裁剪中的线性插值带来的误差与模糊 + // 濡傛灉瑙掑害灏忎簬5搴︼紝鍒欎笉蹇呮棆杞紝鐩存帴鏄剧ず + // 浠ュ厤甯︽潵鏃嬭浆涓庤鍓腑鐨勭嚎鎬ф彃鍊煎甫鏉ョ殑璇樊涓庢ā绯 img_crop = src_mat; } else { - // 如果角度在5度到45度之间,则需要旋转 + // 濡傛灉瑙掑害鍦5搴﹀埌45搴︿箣闂达紝鍒欓渶瑕佹棆杞 //vector rects_tmp; //deskewP(src_mat, BLUE, rects_tmp); @@ -1049,7 +1049,7 @@ int CPlateLocate::deskewOld(Mat src, vector& inRects, } -// !基于颜色信息的车牌定位 +// !鍩轰簬棰滆壊淇℃伅鐨勮溅鐗屽畾浣 int CPlateLocate::plateColorLocate(Mat src, vector& candPlates, int index) { vector rects_color_blue; @@ -1057,13 +1057,13 @@ int CPlateLocate::plateColorLocate(Mat src, vector& candPlates, int inde vector plates; Mat src_b; - // 查找蓝色车牌 - // 查找颜色匹配车牌 + // 鏌ユ壘钃濊壊杞︾墝 + // 鏌ユ壘棰滆壊鍖归厤杞︾墝 colorSearch(src, BLUE, src_b, rects_color_blue, index); - // 进行抗扭斜处理 + // 杩涜鎶楁壄鏂滃鐞 deskew(src, src_b, rects_color_blue, plates); - // 查找黄色车牌 + // 鏌ユ壘榛勮壊杞︾墝 colorSearch(src, YELLOW, src_b, rects_color_yellow, index); deskew(src, src_b, rects_color_yellow, plates); @@ -1075,8 +1075,8 @@ int CPlateLocate::plateColorLocate(Mat src, vector& candPlates, int inde return 0; } -//! Sobel运算 -//! 输入彩色图像,输出二值化图像 +//! Sobel杩愮畻 +//! 杈撳叆褰╄壊鍥惧儚锛岃緭鍑轰簩鍊煎寲鍥惧儚 int CPlateLocate::sobelOperT(const Mat& in, Mat& out, int blurSize, int morphW, int morphH) { Mat mat_blur; @@ -1129,7 +1129,7 @@ int CPlateLocate::sobelOperT(const Mat& in, Mat& out, int blurSize, int morphW, return 0; } -// !基于垂直线条的车牌定位 +// !鍩轰簬鍨傜洿绾挎潯鐨勮溅鐗屽畾浣 int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int index) { vector rects_sobel; @@ -1138,20 +1138,20 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde vector> bound_rects; - // Sobel第一次粗略搜索 + // Sobel绗竴娆$矖鐣ユ悳绱 sobelFrtSearch(src, bound_rects); vector> bound_rects_part; - //对不符合要求的区域进行扩展 + //瀵逛笉绗﹀悎瑕佹眰鐨勫尯鍩熻繘琛屾墿灞 for (int i=0;i 1.0 && bound_rects[i].height < 120) { Rect_ itemRect = bound_rects[i]; - //宽度过小,进行扩展 + //瀹藉害杩囧皬锛岃繘琛屾墿灞 itemRect.x = itemRect.x-itemRect.height*(4-fRatio); if (itemRect.x < 0) { @@ -1170,7 +1170,7 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde } } - //对断裂的部分进行二次处理 + //瀵规柇瑁傜殑閮ㄥ垎杩涜浜屾澶勭悊 for (int i = 0; i < bound_rects_part.size(); i++) { Rect_ bound_rect = bound_rects_part[i]; @@ -1185,7 +1185,7 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde Rect safe_bound_rect(x, y, width, height); Mat bound_mat = src(safe_bound_rect); - // Sobel第二次精细搜索 + // Sobel绗簩娆$簿缁嗘悳绱 sobelSecSearchPart(bound_mat, refpoint, rects_sobel); } @@ -1203,7 +1203,7 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde Rect safe_bound_rect(x, y, width, height); Mat bound_mat = src(safe_bound_rect); - // Sobel第二次精细搜索 + // Sobel绗簩娆$簿缁嗘悳绱 sobelSecSearch(bound_mat, refpoint, rects_sobel); //sobelSecSearchPart(bound_mat, refpoint, rects_sobel); } @@ -1211,7 +1211,7 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde Mat src_b; sobelOper(src, src_b, 3, 10, 3); - // 进行抗扭斜处理 + // 杩涜鎶楁壄鏂滃鐞 deskew(src, src_b, rects_sobel, plates); for (int i = 0; i< plates.size(); i++) @@ -1251,10 +1251,10 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde //! deprected -//! 定位车牌图像 -//! src 原始图像 -//! resultVec 一个Mat的向量,存储所有抓取到的图像 -//! 成功返回0,否则返回-1 +//! 瀹氫綅杞︾墝鍥惧儚 +//! src 鍘熷鍥惧儚 +//! resultVec 涓涓狹at鐨勫悜閲忥紝瀛樺偍鎵鏈夋姄鍙栧埌鐨勫浘鍍 +//! 鎴愬姛杩斿洖0锛屽惁鍒欒繑鍥-1 //int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) //{ // Mat src_blur, src_gray; @@ -1269,7 +1269,7 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde // if( !src.data ) // { return -1; } // -// //测试,三通道划分为单通道 +// //娴嬭瘯锛屼笁閫氶亾鍒掑垎涓哄崟閫氶亾 // //vector channels; // //split(src, channels); // //Mat imageBlue = channels.at(0); @@ -1280,7 +1280,7 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde // // imwrite(ss.str(), imageBlue); // //} // -// //高斯模糊。Size中的数字影响车牌定位的效果。 +// //楂樻柉妯$硦銆係ize涓殑鏁板瓧褰卞搷杞︾墝瀹氫綅鐨勬晥鏋溿 // GaussianBlur( src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize), // 0, 0, BORDER_DEFAULT ); // @@ -1358,11 +1358,11 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde // 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; @@ -1413,10 +1413,10 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde // { // // rotated rectangle drawing // // Get rotation matrix -// // 旋转这部分代码确实可以将某些倾斜的车牌调整正, -// // 但是它也会误将更多正的车牌搞成倾斜!所以综合考虑,还是不使用这段代码。 -// // 2014-08-14,由于新到的一批图片中发现有很多车牌是倾斜的,因此决定再次尝试 -// // 这段代码。 +// // 鏃嬭浆杩欓儴鍒嗕唬鐮佺‘瀹炲彲浠ュ皢鏌愪簺鍊炬枩鐨勮溅鐗岃皟鏁存锛 +// // 浣嗘槸瀹冧篃浼氳灏嗘洿澶氭鐨勮溅鐗屾悶鎴愬炬枩锛佹墍浠ョ患鍚堣冭檻锛岃繕鏄笉浣跨敤杩欐浠g爜銆 +// // 2014-08-14,鐢变簬鏂板埌鐨勪竴鎵瑰浘鐗囦腑鍙戠幇鏈夊緢澶氳溅鐗屾槸鍊炬枩鐨勶紝鍥犳鍐冲畾鍐嶆灏濊瘯 +// // 杩欐浠g爜銆 // float r = (float)minRect.size.width / (float)minRect.size.height; // float angle = minRect.angle; // Size rect_size = minRect.size; @@ -1425,7 +1425,7 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde // angle = 90 + angle; // swap(rect_size.width, rect_size.height); // } -// //如果抓取的方块旋转超过m_angle角度,则不是车牌,放弃处理 +// //濡傛灉鎶撳彇鐨勬柟鍧楁棆杞秴杩噈_angle瑙掑害锛屽垯涓嶆槸杞︾墝锛屾斁寮冨鐞 // if (angle - m_angle < 0 && angle + m_angle > 0) // { // if(1) @@ -1478,12 +1478,12 @@ int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int inde //} -//! 新的定位车牌图像功能 -//! 代码由贡献 -//! 将颜色信息与Sobel信息结合做判断 -//! src 原始图像 -//! resultVec 一个Mat的向量,存储所有抓取到的图像 -//! 成功返回0,否则返回-1 +//! 鏂扮殑瀹氫綅杞︾墝鍥惧儚鍔熻兘 +//! 浠g爜鐢辫础鐚 +//! 灏嗛鑹蹭俊鎭笌Sobel淇℃伅缁撳悎鍋氬垽鏂 +//! src 鍘熷鍥惧儚 +//! resultVec 涓涓狹at鐨勫悜閲忥紝瀛樺偍鎵鏈夋姄鍙栧埌鐨勫浘鍍 +//! 鎴愬姛杩斿洖0锛屽惁鍒欒繑鍥-1 int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) { Mat src_blur, src_gray; @@ -1498,7 +1498,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) return -1; } - //高斯模糊。Size中的数字影响车牌定位的效果。 + //楂樻柉妯$硦銆係ize涓殑鏁板瓧褰卞搷杞︾墝瀹氫綅鐨勬晥鏋溿 GaussianBlur(src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize), 0, 0, BORDER_DEFAULT); @@ -1518,21 +1518,21 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) ss << "image/tmp/debug_gray" << ".jpg"; imwrite(ss.str(), src_gray); } - // RGB颜色初定位 + // RGB棰滆壊鍒濆畾浣 // http://wenku.baidu.com/view/2329e5d2360cba1aa811da65.html?re=view // RGB -> HSV - // 蓝 黄 白 黑 + // 钃 榛 鐧 榛 //H 200~255 25~55 / / //S 0.4~1 0.4~1 0~0.1 / //V 0.3~1 0.3~1 0.9~1 0~0.35 //cvCvtColor(src,dst,CV_BGR2HSV); - //其中,src为三通道的,dst也为三通道的, - //OPENCV 中 H、S、V、顺序分别为3*x+0 3*x+1 3*x+2 - //opencv中的 H分量是 0~180, S分量是0~255, V分量是0~255 - //但是HSV颜色空间却规定的是,H范围0~360,S范围0~1,V范围0~1 - //所以你需要自己转换一下,H*2,S/255, V/255 + //鍏朵腑锛宻rc涓轰笁閫氶亾鐨勶紝dst涔熶负涓夐氶亾鐨勶紝 + //OPENCV 涓 H銆丼銆乂銆侀『搴忓垎鍒负3*x+0 3*x+1 3*x+2 + //opencv涓殑 H鍒嗛噺鏄 0~180锛 S鍒嗛噺鏄0~255锛 V鍒嗛噺鏄0~255 + //浣嗘槸HSV棰滆壊绌洪棿鍗磋瀹氱殑鏄紝H鑼冨洿0~360锛孲鑼冨洿0~1锛孷鑼冨洿0~1 + //鎵浠ヤ綘闇瑕佽嚜宸辫浆鎹竴涓嬶紝H*2锛孲/255, V/255 - // 默认蓝色车牌 + // 榛樿钃濊壊杞︾墝 cv::Mat tmp; cv::cvtColor(src, tmp, CV_BGR2HSV); vector hsvSplit; @@ -1546,7 +1546,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) int nH = hsvSplit[0].at(i, j) * 2; float fS = hsvSplit[1].at(i, j) / 255.0; float fV = hsvSplit[2].at(i, j) / 255.0; - if (nH >= 200 && nH <= 255 && fS >= 0.4 && fS <= 1 && fV >= 0.3 && fV <= 1) // 蓝色 + if (nH >= 200 && nH <= 255 && fS >= 0.4 && fS <= 1 && fV >= 0.3 && fV <= 1) // 钃濊壊 dst_blue.at(i, j) = 255; else dst_blue.at(i, j) = 0; @@ -1555,12 +1555,12 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) //imshow("dst_blue",dst_blue); Mat element_blue = getStructuringElement(MORPH_ELLIPSE, Size(10, 10)); morphologyEx(dst_blue, dst_blue, MORPH_CLOSE, element_blue); - //Find 轮廓 of possibles plates + //Find 杞粨 of possibles plates cv::Mat con_blue = dst_blue.clone(); vector< vector< Point> > contours_blue; findContours(con_blue, contours_blue, // a vector of contours - CV_RETR_EXTERNAL, // 提取外部轮廓 + CV_RETR_EXTERNAL, // 鎻愬彇澶栭儴杞粨 CV_CHAIN_APPROX_NONE); // all pixels of each contours //Start to iterate to each contour founded vector >::iterator itb = contours_blue.begin(); @@ -1601,7 +1601,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) int nH = hsvSplit[0].at(i, j) * 2; float fS = hsvSplit[1].at(i, j) / 255.0; float fV = hsvSplit[2].at(i, j) / 255.0; - if (nH >= 25 && nH <= 55 && fS >= 0.4 && fS <= 1 && fV >= 0.3 && fV <= 1) // 黄色 + if (nH >= 25 && nH <= 55 && fS >= 0.4 && fS <= 1 && fV >= 0.3 && fV <= 1) // 榛勮壊 dst_yellow.at(i, j) = 255; else dst_yellow.at(i, j) = 0; @@ -1610,12 +1610,12 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) Mat element_yellow = getStructuringElement(MORPH_ELLIPSE, Size(10, 10)); morphologyEx(dst_yellow, dst_yellow, MORPH_CLOSE, element_blue); - //Find 轮廓 of possibles plates + //Find 杞粨 of possibles plates cv::Mat con_yellow = dst_yellow.clone(); vector< vector< Point> > contours_yellow; findContours(con_yellow, contours_yellow, // a vector of contours - CV_RETR_EXTERNAL, // 提取外部轮廓 + CV_RETR_EXTERNAL, // 鎻愬彇澶栭儴杞粨 CV_CHAIN_APPROX_NONE); // all pixels of each contours //Start to iterate to each contour founded vector >::iterator ity = contours_yellow.begin(); @@ -1664,7 +1664,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) convertScaleAbs(grad_y, abs_grad_y); /// Total Gradient (approximate) - addWeighted(abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad);//计算两个数组加权值的和 + addWeighted(abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad);//璁$畻涓や釜鏁扮粍鍔犳潈鍊肩殑鍜 //imshow("grad",grad); //Laplacian( src_gray, grad_x, ddepth, 3, scale, delta, BORDER_DEFAULT ); //convertScaleAbs( grad_x, grad ); @@ -1710,16 +1710,16 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) imwrite(ss.str(), img_threshold_yellow); } - //Find 轮廓 of possibles plates + //Find 杞粨 of possibles plates contours_blue.clear(); findContours(img_threshold_blue, contours_blue, // a vector of contours - CV_RETR_EXTERNAL, // 提取外部轮廓 + CV_RETR_EXTERNAL, // 鎻愬彇澶栭儴杞粨 CV_CHAIN_APPROX_NONE); // all pixels of each contours contours_yellow.clear(); findContours(img_threshold_yellow, contours_yellow, // a vector of contours - CV_RETR_EXTERNAL, // 提取外部轮廓 + CV_RETR_EXTERNAL, // 鎻愬彇澶栭儴杞粨 CV_CHAIN_APPROX_NONE); // all pixels of each contours Mat result; @@ -1789,10 +1789,10 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) { // rotated rectangle drawing // Get rotation matrix - // 旋转这部分代码确实可以将某些倾斜的车牌调整正, - // 但是它也会误将更多正的车牌搞成倾斜!所以综合考虑,还是不使用这段代码。 - // 2014-08-14,由于新到的一批图片中发现有很多车牌是倾斜的,因此决定再次尝试 - // 这段代码。 + // 鏃嬭浆杩欓儴鍒嗕唬鐮佺‘瀹炲彲浠ュ皢鏌愪簺鍊炬枩鐨勮溅鐗岃皟鏁存锛 + // 浣嗘槸瀹冧篃浼氳灏嗘洿澶氭鐨勮溅鐗屾悶鎴愬炬枩锛佹墍浠ョ患鍚堣冭檻锛岃繕鏄笉浣跨敤杩欐浠g爜銆 + // 2014-08-14,鐢变簬鏂板埌鐨勪竴鎵瑰浘鐗囦腑鍙戠幇鏈夊緢澶氳溅鐗屾槸鍊炬枩鐨勶紝鍥犳鍐冲畾鍐嶆灏濊瘯 + // 杩欐浠g爜銆 if (m_debug) { Point2f rect_points[4]; @@ -1809,7 +1809,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) 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 74dc889..32a87dc 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,14 +38,14 @@ CPlateRecognize::CPlateRecognize() int CPlateRecognize::plateRecognize(Mat src, vector& licenseVec,int index) { - // 车牌方块集合 + // 杞︾墝鏂瑰潡闆嗗悎 vector plateVec; - // 如果设置了Debug模式,就依次显示所有的图片 + // 濡傛灉璁剧疆浜咲ebug妯″紡锛屽氨渚濇鏄剧ず鎵鏈夌殑鍥剧墖 bool showDetectArea = getPDDebug(); showDetectArea=0; - // 进行深度定位,使用颜色信息与二次Sobel + // 杩涜娣卞害瀹氫綅锛屼娇鐢ㄩ鑹蹭俊鎭笌浜屾Sobel int resultPD = plateDetectDeep(src, plateVec, showDetectArea, 0); Mat result; @@ -64,10 +64,10 @@ int CPlateRecognize::plateRecognize(Mat src, vector& licenseVec,int inde Mat plate = item.getPlateMat(); - //获取车牌颜色 + //鑾峰彇杞︾墝棰滆壊 string plateType = getPlateColor(plate); - //获取车牌号 + //鑾峰彇杞︾墝鍙 string plateIdentify = ""; int resultCR = charsRecognise(plate, plateIdentify); if (resultCR == 0) @@ -88,7 +88,7 @@ int CPlateRecognize::plateRecognize(Mat src, vector& licenseVec,int inde // CvScalar size(cvScalar(8,0.5,0.1)); - // text.setFont(NULL, &size, NULL, &p); // 透明处理 + // text.setFont(NULL, &size, NULL, &p); // 閫忔槑澶勭悊 // text.putText(result, license.c_str(), Point(width,height*(index+1))); @@ -107,14 +107,14 @@ int CPlateRecognize::plateRecognize(Mat src, vector& licenseVec,int inde for (int j = 0; j < 4; j++) { line(result, rect_points[j], rect_points[(j + 1) % 4], Scalar(255, 255, 0), 2, 8); - //颜色定位车牌,黄色方框 + //棰滆壊瀹氫綅杞︾墝锛岄粍鑹叉柟妗 } } else { for( int j = 0; j < 4; j++ ) { - line(result, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,255), 2, 8 );//sobel定位车牌,红色方框 + line(result, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,255), 2, 8 );//sobel瀹氫綅杞︾墝锛岀孩鑹叉柟妗 } } diff --git a/src/include/chars_identify.h b/src/include/chars_identify.h index b1a28a2..03780a7 100644 --- a/src/include/chars_identify.h +++ b/src/include/chars_identify.h @@ -24,34 +24,34 @@ class CCharsIdentify public: CCharsIdentify(); - //! 字符鉴别 + //! 瀛楃閴村埆 string charsIdentify(Mat, bool, bool); string charsIdentify(Mat input); - //! 字符分类 + //! 瀛楃鍒嗙被 int classify(Mat, bool,bool); int classify(Mat f); - //! 装载ANN模型 + //! 瑁呰浇ANN妯″瀷 void LoadModel(); - //! 装载ANN模型 + //! 瑁呰浇ANN妯″瀷 void LoadModel(string s); - //! 设置与读取模型路径 + //! 璁剧疆涓庤鍙栨ā鍨嬭矾寰 inline void setModelPath(string path){ m_path = path; } inline string getModelPath() const{ return m_path; } private: - //!使用的ANN模型 + //锛佷娇鐢ㄧ殑ANN妯″瀷 CvANN_MLP ann; - //! 模型存储路径 + //! 妯″瀷瀛樺偍璺緞 string m_path; - //! 特征尺寸 + //! 鐗瑰緛灏哄 int m_predictSize; - //! 省份对应map + //! 鐪佷唤瀵瑰簲map map m_map; }; diff --git a/src/include/chars_recognise.h b/src/include/chars_recognise.h index d9e64d7..d9bc2a7 100644 --- a/src/include/chars_recognise.h +++ b/src/include/chars_recognise.h @@ -27,34 +27,34 @@ namespace easypr { public: CCharsRecognise(); - //! 字符分割与识别 + //! 瀛楃鍒嗗壊涓庤瘑鍒 int charsRecognise(Mat, String&, int = 0); string charsRecognise(Mat plate); - //! 装载ANN模型 + //! 瑁呰浇ANN妯″瀷 void LoadANN(string s); - //! 是否开启调试模式 + //! 鏄惁寮鍚皟璇曟ā寮 inline void setCRDebug(int param){ m_charsSegment->setDebug(param); } - //! 获取调试模式状态 + //! 鑾峰彇璋冭瘯妯″紡鐘舵 inline int getCRDebug(){ return m_charsSegment->getDebug(); } - //! 获得车牌颜色 + //! 鑾峰緱杞︾墝棰滆壊 inline string getPlateColor(Mat input) const { - string color = "未知"; + string color = "鏈煡"; Color result = getPlateType(input, true); if (BLUE == result) - color = "蓝牌"; + color = "钃濈墝"; if (YELLOW == result) - color = "黄牌"; + color = "榛勭墝"; return color; } - //! 设置变量 + //! 璁剧疆鍙橀噺 inline void setLiuDingSize(int param){ m_charsSegment->setLiuDingSize(param); } inline void setColorThreshold(int param){ m_charsSegment->setColorThreshold(param); } inline void setBluePercent(float param){ m_charsSegment->setBluePercent(param); } @@ -63,10 +63,10 @@ namespace easypr { inline float getWhitePercent() const { return m_charsSegment->getWhitePercent(); } private: - //!字符分割 + //锛佸瓧绗﹀垎鍓 CCharsSegment* m_charsSegment; - //! 字符识别 + //! 瀛楃璇嗗埆 CCharsIdentify* m_charsIdentify; }; diff --git a/src/include/chars_segment.h b/src/include/chars_segment.h index f7fffac..81b6723 100644 --- a/src/include/chars_segment.h +++ b/src/include/chars_segment.h @@ -25,30 +25,30 @@ namespace easypr { public: CCharsSegment(); - //! 字符分割 + //! 瀛楃鍒嗗壊 int charsSegment(Mat, vector&); - //! 字符尺寸验证 + //! 瀛楃灏哄楠岃瘉 bool verifyCharSizes(Mat r); - //! 字符预处理 + //! 瀛楃棰勫鐞 Mat preprocessChar(Mat in); - //! 根据特殊车牌来构造猜测中文字符的位置和大小 + //! 鏍规嵁鐗规畩杞︾墝鏉ユ瀯閫犵寽娴嬩腑鏂囧瓧绗︾殑浣嶇疆鍜屽ぇ灏 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; } @@ -57,38 +57,38 @@ namespace easypr { inline void setWhitePercent(float param){ m_WhitePercent = param; } inline float getWhitePercent() const { return m_WhitePercent; } - //! 是否开启调试模式常量,默认0代表关闭 + //! 鏄惁寮鍚皟璇曟ā寮忓父閲忥紝榛樿0浠h〃鍏抽棴 static const int DEFAULT_DEBUG = 1; - //! preprocessChar所用常量 + //! preprocessChar鎵鐢ㄥ父閲 static const int CHAR_SIZE = 20; static const int HORIZONTAL = 1; static const int VERTICAL = 0; - //! preprocessChar所用常量 + //! preprocessChar鎵鐢ㄥ父閲 static const int DEFAULT_LIUDING_SIZE = 7; static const int DEFAULT_MAT_WIDTH = 136; static const int DEFAULT_COLORTHRESHOLD = 150; - //! 是否开启调试模式 + //! 鏄惁寮鍚皟璇曟ā寮 inline void setDebug(int param){ m_debug = param; } - //! 获取调试模式状态 + //! 鑾峰彇璋冭瘯妯″紡鐘舵 inline int getDebug(){ return m_debug; } private: - //!柳钉判断参数 + //锛佹煶閽夊垽鏂弬鏁 int m_LiuDingSize; - //!车牌大小参数 + //锛佽溅鐗屽ぇ灏忓弬鏁 int m_theMatWidth; - //!车牌颜色判断参数 + //锛佽溅鐗岄鑹插垽鏂弬鏁 int m_ColorThreshold; float m_BluePercent; float m_WhitePercent; - //! 是否开启调试模式,0关闭,非0开启 + //! 鏄惁寮鍚皟璇曟ā寮忥紝0鍏抽棴锛岄潪0寮鍚 int m_debug; }; diff --git a/src/include/core_func.h b/src/include/core_func.h index 94cfb79..98ebccb 100644 --- a/src/include/core_func.h +++ b/src/include/core_func.h @@ -8,37 +8,37 @@ namespace easypr { enum Color{ BLUE, YELLOW }; - //! 根据一幅图像与颜色模板获取对应的二值图 - //! 输入RGB图像, 颜色模板(蓝色、黄色) - //! 输出灰度图(只有0和255两个值,255代表匹配,0代表不匹配) + //! 鏍规嵁涓骞呭浘鍍忎笌棰滆壊妯℃澘鑾峰彇瀵瑰簲鐨勪簩鍊煎浘 + //! 杈撳叆RGB鍥惧儚, 棰滆壊妯℃澘锛堣摑鑹层侀粍鑹诧級 + //! 杈撳嚭鐏板害鍥撅紙鍙湁0鍜255涓や釜鍊硷紝255浠h〃鍖归厤锛0浠h〃涓嶅尮閰嶏級 Mat colorMatch(const Mat& src, Mat& match, const Color r, const bool adaptive_minsv); - //! 判断一个车牌的颜色 - //! 输入车牌mat与颜色模板 - //! 返回true或fasle + //! 鍒ゆ柇涓涓溅鐗岀殑棰滆壊 + //! 杈撳叆杞︾墝mat涓庨鑹叉ā鏉 + //! 杩斿洖true鎴杅asle bool plateColorJudge(const Mat& src, const Color r, const bool adaptive_minsv); bool bFindLeftRightBound(Mat& bound_threshold,int& posLeft,int& posRight); bool bFindLeftRightBound1(Mat& bound_threshold,int& posLeft,int& posRight); bool bFindLeftRightBound2(Mat& bound_threshold,int& posLeft,int& posRight); - //去除车牌上方的钮钉 - //计算每行元素的阶跃数,如果小于X认为是柳丁,将此行全部填0(涂黑) - //X的推荐值为,可根据实际调整 + //鍘婚櫎杞︾墝涓婃柟鐨勯挳閽 + //璁$畻姣忚鍏冪礌鐨勯樁璺冩暟锛屽鏋滃皬浜嶺璁や负鏄煶涓侊紝灏嗘琛屽叏閮ㄥ~0锛堟秱榛戯級 + //X鐨勬帹鑽愬间负锛屽彲鏍规嵁瀹為檯璋冩暣 bool clearLiuDing(Mat& img); void clearLiuDingOnly(Mat& img); void clearLiuDing(Mat mask,int& top,int& bottom); - //! 获得车牌颜色 + //! 鑾峰緱杞︾墝棰滆壊 Color getPlateType(const Mat& src, const bool adaptive_minsv); - //! 直方图均衡 + //! 鐩存柟鍥惧潎琛 Mat histeq(Mat in); Mat features(Mat in, int sizeData); int ThresholdOtsu(Mat mat); - // !获取垂直和水平方向直方图 + // 锛佽幏鍙栧瀭鐩村拰姘村钩鏂瑰悜鐩存柟鍥 Mat ProjectedHistogram(Mat img, int t); } /*! \namespace easypr*/ diff --git a/src/include/plate_detect.h b/src/include/plate_detect.h index c26bd86..0c96cf1 100644 --- a/src/include/plate_detect.h +++ b/src/include/plate_detect.h @@ -29,27 +29,27 @@ class CPlateDetect public: CPlateDetect(); - //! 车牌检测:车牌定位与判断 + //! 杞︾墝妫娴嬶細杞︾墝瀹氫綅涓庡垽鏂 int plateDetect(Mat, vector&, int index = 0); - //! 深度车牌检测,使用颜色与二次Sobel法综合 + //! 娣卞害杞︾墝妫娴嬶紝浣跨敤棰滆壊涓庝簩娆obel娉曠患鍚 int plateDetectDeep(Mat src, vector& resultVec, bool showDetectArea = true, int index = 0); int showResult(const Mat& result); - //! 装载SVM模型 + //! 瑁呰浇SVM妯″瀷 void LoadSVM(string s); - //! 生活模式与工业模式切换 + //! 鐢熸椿妯″紡涓庡伐涓氭ā寮忓垏鎹 inline void setPDLifemode(bool param){m_plateLocate->setLifemode(param);} - //! 是否开启调试模式 + //! 鏄惁寮鍚皟璇曟ā寮 inline void setPDDebug(int param){ m_plateLocate->setDebug(param);} - //! 获取调试模式状态 + //! 鑾峰彇璋冭瘯妯″紡鐘舵 inline int getPDDebug(){ return m_plateLocate->getDebug();} - //! 设置与读取变量 + //! 璁剧疆涓庤鍙栧彉閲 inline void setGaussianBlurSize(int param){ m_plateLocate->setGaussianBlurSize(param);} inline int getGaussianBlurSize() const{ return m_plateLocate->getGaussianBlurSize();} @@ -73,13 +73,13 @@ public: inline float getMaxPlates() const { return m_maxPlates; } private: - //! 设置一幅图中最多有多少车牌 + //! 璁剧疆涓骞呭浘涓渶澶氭湁澶氬皯杞︾墝 int m_maxPlates; - //! 车牌定位 + //! 杞︾墝瀹氫綅 CPlateLocate* m_plateLocate; - //! 车牌判断 + //! 杞︾墝鍒ゆ柇 CPlateJudge* m_plateJudge; }; diff --git a/src/include/plate_locate.h b/src/include/plate_locate.h index f7edc1b..c6878c4 100644 --- a/src/include/plate_locate.h +++ b/src/include/plate_locate.h @@ -30,66 +30,66 @@ public: enum LocateType { SOBEL, COLOR }; - //! Sobel第一次搜索 - //! 不限制大小和形状,获取的BoundRect进入下一步 + //! Sobel绗竴娆℃悳绱 + //! 涓嶉檺鍒跺ぇ灏忓拰褰㈢姸锛岃幏鍙栫殑BoundRect杩涘叆涓嬩竴姝 int sobelFrtSearch(const Mat& src, vector>& outRects); - //! Sobel第二次搜索 - //! 对大小和形状做限制,生成参考坐标 + //! Sobel绗簩娆℃悳绱 + //! 瀵瑰ぇ灏忓拰褰㈢姸鍋氶檺鍒讹紝鐢熸垚鍙傝冨潗鏍 int sobelSecSearch( Mat& bound, Point2f refpoint, vector& outRects); int sobelSecSearchPart( Mat& bound, Point2f refpoint, vector& outRects); - //! 抗扭斜处理 + //! 鎶楁壄鏂滃鐞 int deskew(const Mat& src, const Mat& src_b, vector& inRects, vector& outPlates); - //! 是否偏斜 - //! 输入二值化图像,输出判断结果 + //! 鏄惁鍋忔枩 + //! 杈撳叆浜屽煎寲鍥惧儚锛岃緭鍑哄垽鏂粨鏋 bool isdeflection(const Mat& in, const double angle, double& slope); - //! Sobel运算 - //! 输入彩色图像,输出二值化图像 + //! Sobel杩愮畻 + //! 杈撳叆褰╄壊鍥惧儚锛岃緭鍑轰簩鍊煎寲鍥惧儚 int sobelOper(const Mat& in, Mat& out, int blurSize, int morphW, int morphH); - //! 计算一个安全的Rect + //! 璁$畻涓涓畨鍏ㄧ殑Rect bool calcSafeRect(const RotatedRect& roi_rect, const Mat& src, Rect_& safeBoundRect); - //! 旋转操作 + //! 鏃嬭浆鎿嶄綔 bool rotation(Mat& in, Mat& out, const Size rect_size, const Point2f center, const double angle); - //! 扭变操作 + //! 鎵彉鎿嶄綔 void affine(const Mat& in, Mat& out, const double slope); - //! 颜色定位法 + //! 棰滆壊瀹氫綅娉 int plateColorLocate(Mat src, vector& candPlates, int index = 0); - //! Sobel定位法 + //! Sobel瀹氫綅娉 int plateSobelLocate(Mat src, vector& candPlates, int index = 0); int sobelOperT(const Mat& in, Mat& out, int blurSize, int morphW, int morphH); - //! Color搜索 + //! Color鎼滅储 int colorSearch(const Mat& src, const Color r, Mat& out, vector& outRects, int index = 0); - //! 未使用函数与代码 - //! 开始------------ + //! 鏈娇鐢ㄥ嚱鏁颁笌浠g爜 + //! 寮濮------------ bool sobelJudge(Mat roi); int deskewOld(Mat src, vector& inRects, vector& outRects, vector& outMats, LocateType locateType); bool verifyCharSizes(Mat r); - //! 结束------------ - //! 未使用函数与代码 + //! 缁撴潫------------ + //! 鏈娇鐢ㄥ嚱鏁颁笌浠g爜 - //! 车牌定位 + //! 杞︾墝瀹氫綅 int plateLocate(Mat, vector&, int = 0 ); - //! 车牌的尺寸验证 + //! 杞︾墝鐨勫昂瀵搁獙璇 bool verifySizes(RotatedRect mr); - //! 结果车牌显示 + //! 缁撴灉杞︾墝鏄剧ず Mat showResultMat(Mat src, Size rect_size, Point2f center, int index); - //! 生活模式与工业模式切换 + //! 鐢熸椿妯″紡涓庡伐涓氭ā寮忓垏鎹 void setLifemode(bool param); - //! 设置与读取变量 + //! 璁剧疆涓庤鍙栧彉閲 inline void setGaussianBlurSize(int param){ m_GaussianBlurSize = param;} inline int getGaussianBlurSize() const{ return m_GaussianBlurSize;} @@ -109,13 +109,13 @@ public: inline void setJudgeAngle(int param){ m_angle = param;} - //! 是否开启调试模式 + //! 鏄惁寮鍚皟璇曟ā寮 inline void setDebug(int param){ m_debug = param;} - //! 获取调试模式状态 + //! 鑾峰彇璋冭瘯妯″紡鐘舵 inline int getDebug(){ return m_debug;} - //! PlateLocate所用常量 + //! PlateLocate鎵鐢ㄥ父閲 static const int DEFAULT_GAUSSIANBLUR_SIZE = 5; static const int SOBEL_SCALE = 1; static const int SOBEL_DELTA = 0; @@ -125,39 +125,39 @@ public: static const int DEFAULT_MORPH_SIZE_WIDTH = 17;//17 static const int DEFAULT_MORPH_SIZE_HEIGHT = 3;//3 - //! showResultMat所用常量 + //! showResultMat鎵鐢ㄥ父閲 static const int WIDTH = 136; static const int HEIGHT = 36; static const int TYPE = CV_8UC3; - //! verifySize所用常量 + //! verifySize鎵鐢ㄥ父閲 static const int DEFAULT_VERIFY_MIN = 1;//3 static const int DEFAULT_VERIFY_MAX = 24;//20 - //! 角度判断所用常量 + //! 瑙掑害鍒ゆ柇鎵鐢ㄥ父閲 static const int DEFAULT_ANGLE = 60;//30 - //! 是否开启调试模式常量,默认0代表关闭 + //! 鏄惁寮鍚皟璇曟ā寮忓父閲忥紝榛樿0浠h〃鍏抽棴 static const int DEFAULT_DEBUG = 1; protected: - //! 高斯模糊所用变量 + //! 楂樻柉妯$硦鎵鐢ㄥ彉閲 int m_GaussianBlurSize; - //! 连接操作所用变量 + //! 杩炴帴鎿嶄綔鎵鐢ㄥ彉閲 int m_MorphSizeWidth; int m_MorphSizeHeight; - //! verifySize所用变量 + //! verifySize鎵鐢ㄥ彉閲 float m_error; float m_aspect; int m_verifyMin; int m_verifyMax; - //! 角度判断所用变量 + //! 瑙掑害鍒ゆ柇鎵鐢ㄥ彉閲 int m_angle; - //! 是否开启调试模式,0关闭,非0开启 + //! 鏄惁寮鍚皟璇曟ā寮忥紝0鍏抽棴锛岄潪0寮鍚 int m_debug; LabInfo * m_labItem; diff --git a/src/include/plate_recognize.h b/src/include/plate_recognize.h index 210e728..8381711 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&, int index = 0); - //! 生活模式与工业模式切换 + //! 鐢熸椿妯″紡涓庡伐涓氭ā寮忓垏鎹 inline void setLifemode(bool param) { CPlateDetect::setPDLifemode(param); } - //! 是否开启调试模式 + //! 鏄惁寮鍚皟璇曟ā寮 inline void setDebug(int param) { CPlateDetect::setPDDebug(param); CCharsRecognise::setCRDebug(param); } - ////! 车牌定位与判断 + ////! 杞︾墝瀹氫綅涓庡垽鏂 //int plateDetect(Mat, vector&); - ////! 字符分割与识别 + ////! 瀛楃鍒嗗壊涓庤瘑鍒 //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/main.cpp b/src/main.cpp index b803d74..6149aa2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,18 +20,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; @@ -57,7 +57,7 @@ int main(int argc, char *argv[]) cout << "////////////////////////////////////"<< endl; cout << selectOption.str(); cout << "////////////////////////////////////"<< endl; - cout << "请选择一项操作:"; + cout << "璇烽夋嫨涓椤规搷浣:"; int select = -1; bool isRepeat = true; @@ -84,28 +84,28 @@ int main(int argc, char *argv[]) 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,如果有一天(zhoushiwei),学习奋斗,袁承志,圣城小石匠,goldriver,Micooz,梦里时光,Rain Wang,ahccoms,星夜落尘,海豚嘎嘎" << endl; - cout << "还有很多的同学对本项目也给予了鼓励与支持,在此也一并表示真诚的谢意!" << endl; + cout << "鏈」鐩湪寤鸿杩囩▼涓紝鍙楀埌浜嗗緢澶氫汉鐨勫府鍔╋紝鍏朵腑浠ヤ笅鏄鏈」鐩仛鍑虹獊鍑鸿础鐚殑" << endl; + cout << "(璐$尞鍖呮嫭鏈夌泭寤鸿锛屼唬鐮佽皟浼橈紝鏁版嵁鎻愪緵绛夌瓑,鎺掑悕鎸夋椂闂撮『搴)锛" << endl; + cout << "taotao1233锛岄偙閿﹀北锛屽攼澶т緺锛宩sxyhelu锛屽鏋滄湁涓澶(zhoushiwei)锛屽涔犲鏂楋紝琚佹壙蹇楋紝鍦e煄灏忕煶鍖狅紝goldriver锛孧icooz锛屾ⅵ閲屾椂鍏夛紝Rain Wang锛宎hccoms锛屾槦澶滆惤灏橈紝娴疯睔鍢庡槑" << endl; + cout << "杩樻湁寰堝鐨勫悓瀛﹀鏈」鐩篃缁欎簣浜嗛紦鍔变笌鏀寔锛屽湪姝や篃涓骞惰〃绀虹湡璇氱殑璋㈡剰锛" << endl; cout << endl; break; case 8: isExit = true; break; default: - cout << "输入错误,请重新输入:"; + cout << "杈撳叆閿欒锛岃閲嶆柊杈撳叆:"; isRepeat = true; break; } @@ -113,18 +113,18 @@ int main(int argc, char *argv[]) } return 0; } -// /EasyPR 训练命令行 结束 +// /EasyPR 璁粌鍛戒护琛 缁撴潫 //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// -// acurayTestMain 命令行 +// acurayTestMain 鍛戒护琛 const string acuray_option[] = { "1. general_test;" , "2. native_test;" , - "3. 返回;" , + "3. 杩斿洖;" , }; const int acuray_optionCount = 3; @@ -144,7 +144,7 @@ int acurayTestMain() cout << "////////////////////////////////////"<< endl; cout << selectOption.str(); cout << "////////////////////////////////////"<< endl; - cout << "请选择一项操作:"; + cout << "璇烽夋嫨涓椤规搷浣:"; int select = -1; bool isRepeat = true; @@ -164,7 +164,7 @@ int acurayTestMain() isExit = true; break; default: - cout << "输入错误,请重新输入:"; + cout << "杈撳叆閿欒锛岃閲嶆柊杈撳叆:"; isRepeat = true; break; } @@ -173,22 +173,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; @@ -208,7 +208,7 @@ int svmMain() cout << "////////////////////////////////////"<< endl; cout << selectOption.str(); cout << "////////////////////////////////////"<< endl; - cout << "请选择一项操作:"; + cout << "璇烽夋嫨涓椤规搷浣:"; int select = -1; bool isRepeat = true; @@ -240,7 +240,7 @@ int svmMain() isExit = true; break; default: - cout << "输入错误,请重新输入:"; + cout << "杈撳叆閿欒锛岃閲嶆柊杈撳叆:"; isRepeat = true; break; } @@ -249,7 +249,7 @@ int svmMain() return 0; } -// SVM 训练命令行 +// SVM 璁粌鍛戒护琛 //////////////////////////////////////////////////////////// // command line option support @@ -269,29 +269,29 @@ void cmdMain(int argc, char *argv[]) { const char *help[] = { "EasyPR Usage: ", - "--help [ -h ] 显示帮助 ", - "测试模块 ", - "--test_plate_locate [ -tpl ] 车牌定位 ", - "--test_plate_judge [ -tpj ] 车牌判断 ", - "--test_plate_detect [ -tpd ] 车牌检测 ", - "--test_chars_segment [ -tcs ] 字符分隔 ", - "--test_chars_identify [ -tci ] 字符鉴别 ", - "--test_chars_recognize [ -tcr ] 字符识别 ", - "--test_plate_recognize [ -tpr ] 车牌识别 ", - "--test_all [ -ta ] 测试全部 ", - "--general_test [ -gt ] 批量测试-general_test ", - "--native_test [ -nt ] 批量测试-native_test ", - "SVM训练", - "--svm_gen_learndata [ -sgl ] 生成Learndata ", - "--svm_tag_learndata [ -stl ] 标签Learndata ", - "--svm_detect [ -sd ] 车牌检测,可设置-v或-t ", - "--svm_divide [ -v ] 启用分割 ", - "--svm_train [ -t ] 启用训练 ", - "ANN训练(未开放) ", - "GDTS生成 ", - "--gdts [ -gts ] GDTS生成 ", - "--group 开发团队 ", - "--thanks 感谢名单 ", + "--help [ -h ] 鏄剧ず甯姪 ", + "娴嬭瘯妯″潡 ", + "--test_plate_locate [ -tpl ] 杞︾墝瀹氫綅 ", + "--test_plate_judge [ -tpj ] 杞︾墝鍒ゆ柇 ", + "--test_plate_detect [ -tpd ] 杞︾墝妫娴 ", + "--test_chars_segment [ -tcs ] 瀛楃鍒嗛殧 ", + "--test_chars_identify [ -tci ] 瀛楃閴村埆 ", + "--test_chars_recognize [ -tcr ] 瀛楃璇嗗埆 ", + "--test_plate_recognize [ -tpr ] 杞︾墝璇嗗埆 ", + "--test_all [ -ta ] 娴嬭瘯鍏ㄩ儴 ", + "--general_test [ -gt ] 鎵归噺娴嬭瘯-general_test ", + "--native_test [ -nt ] 鎵归噺娴嬭瘯-native_test ", + "SVM璁粌", + "--svm_gen_learndata [ -sgl ] 鐢熸垚Learndata ", + "--svm_tag_learndata [ -stl ] 鏍囩Learndata ", + "--svm_detect [ -sd ] 杞︾墝妫娴嬶紝鍙缃-v鎴-t ", + "--svm_divide [ -v ] 鍚敤鍒嗗壊 ", + "--svm_train [ -t ] 鍚敤璁粌 ", + "ANN璁粌锛堟湭寮鏀撅級 ", + "GDTS鐢熸垚 ", + "--gdts [ -gts ] GDTS鐢熸垚 ", + "--group 寮鍙戝洟闃 ", + "--thanks 鎰熻阿鍚嶅崟 ", " ", "Examples: ", " $ ./EasyPR --test_plate_locate ", @@ -404,23 +404,23 @@ void cmdMain(int argc, char *argv[]) // if (parser.has("group")) { - // 开发团队; + // 寮鍙戝洟闃; 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; } if (parser.has("thanks")) { - // 感谢名单 + // 鎰熻阿鍚嶅崟 cout << endl; - cout << "本项目在建设过程中,受到了很多人的帮助,其中以下是对本项目做出突出贡献的" << endl; - cout << "(贡献包括有益建议,代码调优,数据提供等等,排名按时间顺序):" << endl; - cout << "taotao1233,邱锦山,唐大侠,jsxyhelu,如果有一天(zhoushiwei),学习奋斗,袁承志,圣城小石匠,goldriver,Micooz,梦里时光,Rain Wang,ahccoms,星夜落尘,海豚嘎嘎" << endl; - cout << "还有很多的同学对本项目也给予了鼓励与支持,在此也一并表示真诚的谢意!" << endl; + cout << "鏈」鐩湪寤鸿杩囩▼涓紝鍙楀埌浜嗗緢澶氫汉鐨勫府鍔╋紝鍏朵腑浠ヤ笅鏄鏈」鐩仛鍑虹獊鍑鸿础鐚殑" << endl; + cout << "(璐$尞鍖呮嫭鏈夌泭寤鸿锛屼唬鐮佽皟浼橈紝鏁版嵁鎻愪緵绛夌瓑,鎺掑悕鎸夋椂闂撮『搴)锛" << endl; + cout << "taotao1233锛岄偙閿﹀北锛屽攼澶т緺锛宩sxyhelu锛屽鏋滄湁涓澶(zhoushiwei)锛屽涔犲鏂楋紝琚佹壙蹇楋紝鍦e煄灏忕煶鍖狅紝goldriver锛孧icooz锛屾ⅵ閲屾椂鍏夛紝Rain Wang锛宎hccoms锛屾槦澶滆惤灏橈紝娴疯睔鍢庡槑" << endl; + cout << "杩樻湁寰堝鐨勫悓瀛﹀鏈」鐩篃缁欎簣浜嗛紦鍔变笌鏀寔锛屽湪姝や篃涓骞惰〃绀虹湡璇氱殑璋㈡剰锛" << endl; cout << endl; break; } diff --git a/src/train/ann_train.cpp b/src/train/ann_train.cpp index 6d69808..57397ba 100644 --- a/src/train/ann_train.cpp +++ b/src/train/ann_train.cpp @@ -1,4 +1,4 @@ -// ann_train.cpp : ann模型的训练文件,主要用在OCR中 +// ann_train.cpp : ann妯″瀷鐨勮缁冩枃浠讹紝涓昏鐢ㄥ湪OCR涓 #include #include @@ -33,30 +33,30 @@ using namespace easypr; CvANN_MLP ann; -//中国车牌 +//涓浗杞︾墝 const char strCharacters[] = {'0','1','2','3','4','5',\ - '6','7','8','9','A','B', 'C', 'D', 'E','F', 'G', 'H', /* 没有I */\ - 'J', 'K', 'L', 'M', 'N', /* 没有O */ 'P', 'Q', 'R', 'S', 'T', \ + '6','7','8','9','A','B', 'C', 'D', 'E','F', 'G', 'H', /* 娌℃湁I */\ + 'J', 'K', 'L', 'M', 'N', /* 娌℃湁O */ 'P', 'Q', 'R', 'S', 'T', \ 'U','V', 'W', 'X', 'Y', 'Z'}; -const int numCharacter = 34; /* 没有I和O,10个数字与24个英文字符之和 */ +const int numCharacter = 34; /* 娌℃湁I鍜孫,10涓暟瀛椾笌24涓嫳鏂囧瓧绗︿箣鍜 */ const int numNeurons = 20; const int predictSize = 10; -//以下都是我训练时用到的中文字符数据,并不全面,有些省份没有训练数据所以没有字符 -//有些后面加数字2的表示在训练时常看到字符的一种变形,也作为训练数据存储 +//浠ヤ笅閮芥槸鎴戣缁冩椂鐢ㄥ埌鐨勪腑鏂囧瓧绗︽暟鎹紝骞朵笉鍏ㄩ潰锛屾湁浜涚渷浠芥病鏈夎缁冩暟鎹墍浠ユ病鏈夊瓧绗 +//鏈変簺鍚庨潰鍔犳暟瀛2鐨勮〃绀哄湪璁粌鏃跺父鐪嬪埌瀛楃鐨勪竴绉嶅彉褰紝涔熶綔涓鸿缁冩暟鎹瓨鍌 const string strChinese[] = { - "zh_cuan" /* 川 */, "zh_e" /* 鄂 */, "zh_gan" /* 赣*/, \ - "zh_gan1"/*甘*/,"zh_gui"/* 贵 */,"zh_gui1"/* 桂 */,\ - "zh_hei" /* 黑 */, "zh_hu" /* 沪 */, "zh_ji" /* 冀 */, \ - "zh_jin" /* 津 */, "zh_jing" /* 京 */,"zh_jl" /* 吉 */, \ - "zh_liao" /* 辽 */, "zh_lu" /* 鲁 */, "zh_meng" /* 蒙 */,\ - "zh_min" /* 闽 */, "zh_ning" /* 宁 */, "zh_qing" /* 青 */,\ - "zh_qiong" /* 琼 */, "zh_shan" /* 陕 */,"zh_su" /* 苏 */, \ - "zh_sx" /* 晋 */, "zh_wan" /* 皖 */, "zh_xiang" /* 湘 */,\ - "zh_xin" /* 新 */,"zh_yu" /* 豫 */, "zh_yu1" /* 渝 */,\ - "zh_yue" /* 粤 */, "zh_yun" /* 云 */, "zh_zang" /* 藏 */,\ - "zh_zhe" /* 浙 */}; + "zh_cuan" /* 宸 */, "zh_e" /* 閯 */, "zh_gan" /* 璧*/, \ + "zh_gan1"/*鐢*/,"zh_gui"/* 璐 */,"zh_gui1"/* 妗 */,\ + "zh_hei" /* 榛 */, "zh_hu" /* 娌 */, "zh_ji" /* 鍐 */, \ + "zh_jin" /* 娲 */, "zh_jing" /* 浜 */,"zh_jl" /* 鍚 */, \ + "zh_liao" /* 杈 */, "zh_lu" /* 椴 */, "zh_meng" /* 钂 */,\ + "zh_min" /* 闂 */, "zh_ning" /* 瀹 */, "zh_qing" /* 闈 */,\ + "zh_qiong" /* 鐞 */, "zh_shan" /* 闄 */,"zh_su" /* 鑻 */, \ + "zh_sx" /* 鏅 */, "zh_wan" /* 鐨 */, "zh_xiang" /* 婀 */,\ + "zh_xin" /* 鏂 */,"zh_yu" /* 璞 */, "zh_yu1" /* 娓 */,\ + "zh_yue" /* 绮 */, "zh_yun" /* 浜 */, "zh_zang" /* 钘 */,\ + "zh_zhe" /* 娴 */}; const int numChinese = 31; const int numAll = 65; /* 34+20=54 */ @@ -145,7 +145,7 @@ int saveTrainData() trainingDataf10.push_back(f10); trainingDataf15.push_back(f15); trainingDataf20.push_back(f20); - trainingLabels.push_back(i); //每一幅字符图片所对应的字符类别索引下标 + trainingLabels.push_back(i); //姣忎竴骞呭瓧绗﹀浘鐗囨墍瀵瑰簲鐨勫瓧绗︾被鍒储寮曚笅鏍 } } @@ -245,7 +245,7 @@ int annMain() saveTrainData(); - //可根据需要训练不同的predictSize或者neurons的ANN模型 + //鍙牴鎹渶瑕佽缁冧笉鍚岀殑predictSize鎴栬卬eurons鐨凙NN妯″瀷 //for (int i = 2; i <= 2; i ++) //{ // int size = i * 5; @@ -256,8 +256,8 @@ int annMain() // } //} - //这里演示只训练model文件夹下的ann.xml,此模型是一个predictSize=10,neurons=40的ANN模型。 - //根据机器的不同,训练时间不一样,但一般需要10分钟左右,所以慢慢等一会吧。 + //杩欓噷婕旂ず鍙缁僲odel鏂囦欢澶逛笅鐨刟nn.xml锛屾妯″瀷鏄竴涓猵redictSize=10,neurons=40鐨凙NN妯″瀷銆 + //鏍规嵁鏈哄櫒鐨勪笉鍚岋紝璁粌鏃堕棿涓嶄竴鏍凤紝浣嗕竴鑸渶瑕10鍒嗛挓宸﹀彸锛屾墍浠ユ參鎱㈢瓑涓浼氬惂銆 saveModel(10, 40); cout << "To be end." << endl; diff --git a/src/util/learn_prepare.cpp b/src/util/learn_prepare.cpp index 92e36fa..aae857f 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; -//! 将以下路径改成你的位置 +//! 灏嗕互涓嬭矾寰勬敼鎴愪綘鐨勪綅缃 const char * notlabelPath = "F:/data/easypr-data/notlabel"; const char * hasPaltePath = "F:/data/easypr-data/learn/hasPlate/"; const char * noPlatePath = "F:/data/easypr-data/learn/noPlate/"; -//! 读取not label data,生成learn data +//! 璇诲彇not label data锛岀敓鎴恖earn data void label_data() { - ////获取该路径下的所有文件 + ////鑾峰彇璇ヨ矾寰勪笅鐨勬墍鏈夋枃浠 auto files = Utils::getFiles(notlabelPath); CPlateLocate lo;