From 8e4ac7db5e7424629261aae9b28d11161a49bc65 Mon Sep 17 00:00:00 2001 From: Micooz Date: Thu, 28 May 2015 13:04:29 +0800 Subject: [PATCH 1/3] Simplify OS detect Macros, add "mkdir()" function to Utils. --- include/easypr/util.h | 12 +++++++++ src/preprocess/mc_data.cpp | 5 ++-- src/train/ann_train.cpp | 16 ++++-------- src/util/util.cpp | 53 +++++++++++++++++++++++++++++++------- 4 files changed, 62 insertions(+), 24 deletions(-) diff --git a/include/easypr/util.h b/include/easypr/util.h index 66e268b..16ccc69 100644 --- a/include/easypr/util.h +++ b/include/easypr/util.h @@ -5,6 +5,14 @@ #include #include +#if defined(WIN32) || defined(_WIN32) +#define OS_WINDOWS +#elif defined(__APPLE__) || defined(APPLE) +#define OS_UNIX +#elif defined(__linux__) || defined(linux) +#define OS_LINUX +#endif + #ifdef min #undef min #endif @@ -89,6 +97,10 @@ class Utils { return prevCol[len2]; } + /* + * Create multi-level directories by given folder. + */ + static bool mkdir(const std::string folder); }; diff --git a/src/preprocess/mc_data.cpp b/src/preprocess/mc_data.cpp index b34d617..f48e8b1 100644 --- a/src/preprocess/mc_data.cpp +++ b/src/preprocess/mc_data.cpp @@ -5,13 +5,12 @@ #include #include "easypr/plate_judge.h" #include "easypr/plate_locate.h" +#include "easypr/util.h" -#if defined (WIN32) || defined (_WIN32) +#ifdef OS_WINDOWS #include #endif -#include "easypr/util.h" - namespace easypr { namespace preprocess { diff --git a/src/train/ann_train.cpp b/src/train/ann_train.cpp index 16a00b4..03e6cef 100644 --- a/src/train/ann_train.cpp +++ b/src/train/ann_train.cpp @@ -1,11 +1,10 @@ // ann_train.cpp : ann模型的训练文件,主要用在OCR中 -#include -#include -#include "opencv2/ml/ml.hpp" -#include "opencv2/highgui/highgui.hpp" +#include +#include "easypr/util.h" +#include "easypr/plate_recognize.h" -#if defined (WIN32) || defined (_WIN32) +#ifdef OS_WINDOWS #include #endif @@ -13,15 +12,10 @@ #include #include -#if defined (WIN32) || defined (_WIN32) +#ifdef OS_WINDOWS #include -#elif defined (linux) || defined (__linux__) -//#include #endif -#include "easypr/plate_recognize.h" -#include "easypr/util.h" - using namespace easypr; using namespace cv; using namespace std; diff --git a/src/util/util.cpp b/src/util/util.cpp index 049c8fa..a96e57b 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -1,17 +1,21 @@ #include "easypr/util.h" -#if defined(WIN32) || defined(_WIN32) +#ifdef OS_WINDOWS #include +#include #include -#elif defined(linux) || defined(__linux__) || defined(__APPLE__) +#define PATH_DELIMITER '\\' +#elif defined(OS_LINUX) || defined(OS_UNIX) #include #include #include +#include +#define PATH_DELIMITER '/' #endif -#if defined(__APPLE__) +#ifdef OS_UNIX #include @@ -23,11 +27,11 @@ using namespace std; using namespace easypr; long Utils::getTimestamp() { -#if defined(WIN32) || defined(_WIN32) +#ifdef OS_WINDOWS return GetTickCount(); #endif -#if (linux) || defined(__linux__) +#ifdef OS_LINUX struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); @@ -35,7 +39,7 @@ long Utils::getTimestamp() { return (ts.tv_sec * 1e3 + ts.tv_nsec / 1e6); #endif -#if defined(__APPLE__) +#ifdef OS_UNIX // there is no function provided by osx to get system tick count. // but considering the purpose by using this function, // we can simply return a millisecond since 1970/1/1 to calc the time elapse. @@ -48,7 +52,7 @@ long Utils::getTimestamp() { std::string Utils::getFileName(const string& path, const bool postfix /* = false */) { if (!path.empty()) { -#if defined(WIN32) || defined(_WIN32) +#ifdef OS_WINDOWS size_t last_slash_1 = path.find_last_of("\\"); size_t last_slash_2 = path.find_last_of("/"); size_t last_slash; @@ -110,7 +114,7 @@ vector Utils::getFiles(const string& folder, vector files; list subfolders; subfolders.push_back(folder); -#if defined(WIN32) || defined(_WIN32) +#ifdef OS_WINDOWS while (!subfolders.empty()) { string current_folder(subfolders.back()); @@ -156,7 +160,7 @@ vector Utils::getFiles(const string& folder, } // while _findclose(file_handler); } -#elif defined(linux) || defined(__linux__) || defined(__APPLE__) +#elif defined(OS_LINUX) || defined(OS_UNIX) while (!subfolders.empty()) { string current_folder(subfolders.back()); @@ -214,7 +218,36 @@ vector Utils::getFiles(const string& folder, } // while closedir(pdir); } - #endif return files; } + +bool Utils::mkdir(const std::string folder) { + std::string folder_builder; + std::string sub; + sub.reserve(folder.size()); + for (auto it = folder.begin(); it != folder.end(); ++it) { + const char c = *it; + sub.push_back(c); + if (c == PATH_DELIMITER || it == folder.end() - 1) { + folder_builder.append(sub); +#ifdef OS_WINDOWS + if (0 != ::_access(folder_builder.c_str(), 0)) { +#else + if (0 != ::access(folder_builder.c_str(), 0)) { +#endif + // this folder not exist +#ifdef OS_WINDOWS + if (0 != ::_mkdir(folder_builder.c_str())) { +#else + if (0 != ::mkdir(folder_builder.c_str(), S_IRWXU)) { +#endif + // create failed + return false; + } + } + sub.clear(); + } + } + return true; +} From 07edd8fee839ce39c1aec0623f3d7b4acf87b775 Mon Sep 17 00:00:00 2001 From: Micooz Date: Thu, 28 May 2015 13:28:34 +0800 Subject: [PATCH 2/3] Add Utils::imwrite() to avoid creation failed by cv::imwrite when folder not exists. --- include/easypr/util.h | 7 +++++++ src/util/util.cpp | 41 +++++++++++++++++++++++++---------------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/include/easypr/util.h b/include/easypr/util.h index 16ccc69..fbe2bc2 100644 --- a/include/easypr/util.h +++ b/include/easypr/util.h @@ -4,6 +4,7 @@ #include #include #include +#include #if defined(WIN32) || defined(_WIN32) #define OS_WINDOWS @@ -102,6 +103,12 @@ class Utils { */ static bool mkdir(const std::string folder); + /* + * Make sure the destination folder exists, + * if not, create it, then call cv::imwrite. + */ + static bool imwrite(const std::string& file, const cv::Mat& image); + }; } // namespace easypr diff --git a/src/util/util.cpp b/src/util/util.cpp index a96e57b..a88864b 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -22,9 +22,9 @@ #endif #include +#include -using namespace std; -using namespace easypr; +namespace easypr { long Utils::getTimestamp() { #ifdef OS_WINDOWS @@ -49,7 +49,7 @@ long Utils::getTimestamp() { #endif } -std::string Utils::getFileName(const string& path, +std::string Utils::getFileName(const std::string& path, const bool postfix /* = false */) { if (!path.empty()) { #ifdef OS_WINDOWS @@ -72,7 +72,7 @@ std::string Utils::getFileName(const string& path, #endif size_t last_dot = path.find_last_of('.'); - if (last_dot < last_slash || last_dot == string::npos) { + if (last_dot < last_slash || last_dot == std::string::npos) { // not found the right dot of the postfix, // return the file name directly return path.substr(last_slash + 1); @@ -89,13 +89,14 @@ std::string Utils::getFileName(const string& path, return ""; } -vector Utils::splitString(const string& str, const char delimiter) { - vector splited; - string s(str); +std::vector Utils::splitString(const std::string& str, + const char delimiter) { + std::vector splited; + std::string s(str); size_t pos; - while ((pos = s.find(delimiter)) != string::npos) { - string sec = s.substr(0, pos); + while ((pos = s.find(delimiter)) != std::string::npos) { + std::string sec = s.substr(0, pos); if (!sec.empty()) { splited.push_back(s.substr(0, pos)); @@ -109,10 +110,10 @@ vector Utils::splitString(const string& str, const char delimiter) { return splited; } -vector Utils::getFiles(const string& folder, - const bool all /* = true */) { - vector files; - list subfolders; +std::vector Utils::getFiles(const std::string& folder, + const bool all /* = true */) { + std::vector files; + std::list subfolders; subfolders.push_back(folder); #ifdef OS_WINDOWS while (!subfolders.empty()) { @@ -162,7 +163,7 @@ vector Utils::getFiles(const string& folder, } #elif defined(OS_LINUX) || defined(OS_UNIX) while (!subfolders.empty()) { - string current_folder(subfolders.back()); + std::string current_folder(subfolders.back()); if (*(current_folder.end() - 1) != '/') { current_folder.push_back('/'); @@ -192,7 +193,7 @@ vector Utils::getFiles(const string& folder, continue; } - string file_path; + std::string file_path; file_path.append(current_folder.c_str()); file_path.append(dir->d_name); @@ -206,7 +207,7 @@ vector Utils::getFiles(const string& folder, // it's a sub folder if (all) { // will search sub folder - string subfolder(current_folder); + std::string subfolder(current_folder); subfolder.append(dir->d_name); subfolders.push_back(subfolder.c_str()); @@ -251,3 +252,11 @@ bool Utils::mkdir(const std::string folder) { } return true; } + +bool Utils::imwrite(const std::string& file, const cv::Mat& image) { + auto folder = file.substr(0, file.find_last_of(PATH_DELIMITER)); + Utils::mkdir(folder); + return cv::imwrite(file, image); +} + +} // namespace easypr \ No newline at end of file From 0789f108dfdc3592456132c0a8002ba0940f433e Mon Sep 17 00:00:00 2001 From: Micooz Date: Thu, 28 May 2015 19:58:16 +0800 Subject: [PATCH 3/3] Change all cv::imwrite() to utils::imwrite(). --- include/easypr/util.h | 2 ++ src/core/chars_segment.cpp | 15 +++++++------ src/core/plate_detect.cpp | 3 ++- src/core/plate_locate.cpp | 45 +++++++++++++++++++------------------- src/preprocess/gdts.cpp | 2 +- src/preprocess/mc_data.cpp | 4 ++-- src/train/svm_train.cpp | 2 +- 7 files changed, 39 insertions(+), 34 deletions(-) diff --git a/include/easypr/util.h b/include/easypr/util.h index fbe2bc2..64f4513 100644 --- a/include/easypr/util.h +++ b/include/easypr/util.h @@ -111,6 +111,8 @@ class Utils { }; +typedef Utils utils; + } // namespace easypr /// general_test_prepare.cpp中方法 diff --git a/src/core/chars_segment.cpp b/src/core/chars_segment.cpp index 4a248ab..98b0c44 100644 --- a/src/core/chars_segment.cpp +++ b/src/core/chars_segment.cpp @@ -1,4 +1,5 @@ #include "easypr/chars_segment.h" +#include "easypr/util.h" /*! \namespace easypr Namespace where all the C++ EasyPR functionality resides @@ -101,7 +102,7 @@ namespace easypr{ int h = input_grey.rows; Mat tmp = input_grey(Rect(w*0.1,h*0.1,w*0.8,h*0.8)); int threadHoldV = ThresholdOtsu(tmp); - imwrite("./tmp/inputgray2.jpg",input_grey); + utils::imwrite("tmp/inputgray2.jpg",input_grey); threshold(input_grey, img_threshold,threadHoldV, 255, CV_THRESH_BINARY); @@ -116,7 +117,7 @@ namespace easypr{ int h = input_grey.rows; Mat tmp = input_grey(Rect(w*0.1,h*0.1,w*0.8,h*0.8)); int threadHoldV = ThresholdOtsu(tmp); - imwrite("./tmp/inputgray2.jpg",input_grey); + utils::imwrite("tmp/inputgray2.jpg",input_grey); threshold(input_grey, img_threshold,threadHoldV, 255, CV_THRESH_BINARY_INV); @@ -132,7 +133,7 @@ namespace easypr{ { std::stringstream ss(std::stringstream::in | std::stringstream::out); ss << "tmp/debug_char_threshold" <& resultVec, int index) { if (1) { std::stringstream ss(std::stringstream::in | std::stringstream::out); ss << "tmp/plate_judge_result_" << i << ".jpg"; - imwrite(ss.str(), img); + utils::imwrite(ss.str(), img); } } } diff --git a/src/core/plate_locate.cpp b/src/core/plate_locate.cpp index 79bb6c0..ac503bf 100644 --- a/src/core/plate_locate.cpp +++ b/src/core/plate_locate.cpp @@ -1,4 +1,5 @@ #include "easypr/plate_locate.h" +#include "easypr/util.h" /*! \namespace easypr Namespace where all the C++ EasyPR functionality resides @@ -90,7 +91,7 @@ Mat CPlateLocate::showResultMat(Mat src, Size rect_size, Point2f center, if (m_debug) { stringstream ss(stringstream::in | stringstream::out); ss << "tmp/debug_crop_" << index << ".jpg"; - imwrite(ss.str(), img_crop); + utils::imwrite(ss.str(), img_crop); } Mat resultResized; @@ -101,7 +102,7 @@ Mat CPlateLocate::showResultMat(Mat src, Size rect_size, Point2f center, if (m_debug) { stringstream ss(stringstream::in | stringstream::out); ss << "tmp/debug_resize_" << index << ".jpg"; - imwrite(ss.str(), resultResized); + utils::imwrite(ss.str(), resultResized); } return resultResized; @@ -134,7 +135,7 @@ int CPlateLocate::colorSearch(const Mat& src, const Color r, Mat& out, morphologyEx(src_threshold, src_threshold, MORPH_CLOSE, element); - imwrite("./tmp/color.jpg", src_threshold); + utils::imwrite("tmp/color.jpg", src_threshold); src_threshold.copyTo(out); @@ -245,7 +246,7 @@ int CPlateLocate::sobelFrtSearch(const Mat& src, m_MorphSizeHeight); - imwrite("tmp/sobelFrtSearch.jpg", src_threshold); + utils::imwrite("tmp/sobelFrtSearch.jpg", src_threshold); vector > contours; @@ -322,14 +323,14 @@ int CPlateLocate::sobelSecSearchPart(Mat& bound, Point2f refpoint, } - imwrite("tmp/repaireimg1.jpg", bound_threshold); + utils::imwrite("tmp/repaireimg1.jpg", bound_threshold); //两边的区域不要 for (int i = 0; i < bound_threshold.rows; i++) { bound_threshold.data[i * bound_threshold.cols + posLeft] = 0; bound_threshold.data[i * bound_threshold.cols + posRight] = 0; } - imwrite("tmp/repaireimg2.jpg", bound_threshold); + utils::imwrite("tmp/repaireimg2.jpg", bound_threshold); } @@ -373,7 +374,7 @@ int CPlateLocate::sobelSecSearch(Mat& bound, Point2f refpoint, //! 第二次参数比一次精细,但针对的是得到的外接矩阵之后的图像,再sobel得到二值图像 sobelOper(bound, bound_threshold, 3, 10, 3); - imwrite("./tmp/sobelSecSearch.jpg", bound_threshold); + utils::imwrite("tmp/sobelSecSearch.jpg", bound_threshold); vector > contours; findContours(bound_threshold, @@ -472,7 +473,7 @@ void DeleteNotArea(Mat& inmat) { threshold(input_grey, img_threshold, threadHoldV, 255, CV_THRESH_BINARY); //threshold(input_grey, img_threshold, 5, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); - imwrite("./tmp/inputgray2.jpg", img_threshold); + utils::imwrite("tmp/inputgray2.jpg", img_threshold); } else if (YELLOW == plateType) { @@ -1024,7 +1025,7 @@ int CPlateLocate::sobelOperT(const Mat& in, Mat& out, int blurSize, int morphW, //mat_gray = m_bilateral.BilateralFilter(mat_gray,6); - imwrite("./tmp/grayblure.jpg", mat_gray); + utils::imwrite("tmp/grayblure.jpg", mat_gray); //equalizeHist(mat_gray, mat_gray); @@ -1044,18 +1045,18 @@ int CPlateLocate::sobelOperT(const Mat& in, Mat& out, int blurSize, int morphW, Mat grad; addWeighted(abs_grad_x, 1, abs_grad_y, 0, 0, grad); - imwrite("./tmp/graygrad.jpg", grad); + utils::imwrite("tmp/graygrad.jpg", grad); Mat mat_threshold; //double otsu_thresh_val = threshold(grad, mat_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); - imwrite("./tmp/grayBINARY.jpg", mat_threshold); + utils::imwrite("tmp/grayBINARY.jpg", mat_threshold); Mat element = getStructuringElement(MORPH_RECT, Size(morphW, morphH)); morphologyEx(mat_threshold, mat_threshold, MORPH_CLOSE, element); - imwrite("./tmp/phologyEx.jpg", mat_threshold); + utils::imwrite("tmp/phologyEx.jpg", mat_threshold); out = mat_threshold; @@ -1175,7 +1176,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) { if (m_debug) { stringstream ss(stringstream::in | stringstream::out); ss << "tmp/debug_GaussianBlur" << ".jpg"; - imwrite(ss.str(), src_blur); + utils::imwrite(ss.str(), src_blur); } /// Convert it to gray @@ -1184,7 +1185,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) { if (m_debug) { stringstream ss(stringstream::in | stringstream::out); ss << "tmp/debug_gray" << ".jpg"; - imwrite(ss.str(), src_gray); + utils::imwrite(ss.str(), src_gray); } // RGB颜色初定位 // http://wenku.baidu.com/view/2329e5d2360cba1aa811da65.html?re=view @@ -1330,9 +1331,9 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) { if (m_debug) { stringstream ss(stringstream::in | stringstream::out); ss << "tmp/debug_Sobel_blue" << ".jpg"; - imwrite(ss.str(), out_blue); + utils::imwrite(ss.str(), out_blue); ss << "tmp/debug_Sobel_yellow" << ".jpg"; - imwrite(ss.str(), out_yellow); + utils::imwrite(ss.str(), out_yellow); } Mat img_threshold_blue; @@ -1346,9 +1347,9 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) { if (m_debug) { stringstream ss(stringstream::in | stringstream::out); ss << "tmp/debug_threshold_blue" << ".jpg"; - imwrite(ss.str(), img_threshold_blue); + utils::imwrite(ss.str(), img_threshold_blue); ss << "tmp/debug_threshold_yellow" << ".jpg"; - imwrite(ss.str(), img_threshold_yellow); + utils::imwrite(ss.str(), img_threshold_yellow); } Mat element = getStructuringElement(MORPH_RECT, Size(m_MorphSizeWidth, @@ -1360,9 +1361,9 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) { if (m_debug) { stringstream ss(stringstream::in | stringstream::out); ss << "tmp/debug_morphology_blue" << ".jpg"; - imwrite(ss.str(), img_threshold_blue); + utils::imwrite(ss.str(), img_threshold_blue); ss << "tmp/debug_morphology_yellow" << ".jpg"; - imwrite(ss.str(), img_threshold_yellow); + utils::imwrite(ss.str(), img_threshold_yellow); } //Find 轮廓 of possibles plates @@ -1391,7 +1392,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) { 1); // with a thickness of 1 stringstream ss(stringstream::in | stringstream::out); ss << "tmp/debug_Contours" << ".jpg"; - imwrite(ss.str(), result); + utils::imwrite(ss.str(), result); } @@ -1471,7 +1472,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) { if (m_debug) { stringstream ss(stringstream::in | stringstream::out); ss << "tmp/debug_result" << ".jpg"; - imwrite(ss.str(), result); + utils::imwrite(ss.str(), result); } return 0; diff --git a/src/preprocess/gdts.cpp b/src/preprocess/gdts.cpp index 4a7684d..1516569 100644 --- a/src/preprocess/gdts.cpp +++ b/src/preprocess/gdts.cpp @@ -55,7 +55,7 @@ int generate_gdts() { std::stringstream ss(std::stringstream::in | std::stringstream::out); ss << dst_path << "/" << filename; - imwrite(ss.str(), dst); + utils::imwrite(ss.str(), dst); } return 0; diff --git a/src/preprocess/mc_data.cpp b/src/preprocess/mc_data.cpp index f48e8b1..9f71d56 100644 --- a/src/preprocess/mc_data.cpp +++ b/src/preprocess/mc_data.cpp @@ -114,7 +114,7 @@ void create_learn_data(const char* raw_data_folder, const char* out_data_folder, } save_to.append(Utils::getFileName(f, true)); - cv::imwrite(save_to, img); + utils::imwrite(save_to, img); std::cout << f << " -> " << save_to << std::endl; } std::cout << "Learn data created successfully!" << std::endl; @@ -168,7 +168,7 @@ void tag_data(const char* source_folder, const char* has_plate_folder, no_plate_folder, filename.c_str(), plate_index); std::cout << "[N] -> " << save_to << std::endl; } - cv::imwrite(save_to, plate); + utils::imwrite(save_to, plate); ++plate_index; } } diff --git a/src/train/svm_train.cpp b/src/train/svm_train.cpp index 2617524..58e2afe 100644 --- a/src/train/svm_train.cpp +++ b/src/train/svm_train.cpp @@ -34,7 +34,7 @@ void Svm::divide(const char* images_folder, float percentage /* = 0.7 */) { } else { sprintf(save_to, "%s/test/%s", images_folder, file_name); } - cv::imwrite(save_to, image); + utils::imwrite(save_to, image); std::cout << f << " -> " << save_to << std::endl; } }