diff --git a/src/include/plate_recognize.h b/src/include/plate_recognize.h index a07a162..7973c2d 100644 --- a/src/include/plate_recognize.h +++ b/src/include/plate_recognize.h @@ -65,4 +65,4 @@ private: } /* \namespace easypr */ -#endif /* endif __PLATE_RECOGNITION_H__ */ \ No newline at end of file +#endif /* endif __PLATE_RECOGNITION_H__ */ diff --git a/src/include/prep.h b/src/include/prep.h index 45c136c..1808bbc 100644 --- a/src/include/prep.h +++ b/src/include/prep.h @@ -17,7 +17,7 @@ #if defined (WIN32) || defined (_WIN32) #include #elif defined (linux) || defined (__linux__) -#include + #endif #include @@ -26,7 +26,7 @@ #include #include #include -#include +#include using namespace std; using namespace cv; diff --git a/src/include/util.h b/src/include/util.h index 00b1e19..cb588cf 100644 --- a/src/include/util.h +++ b/src/include/util.h @@ -1,42 +1,49 @@ - #ifndef __UTIL_H__ #define __UTIL_H__ +#include +#include + #ifdef min - #undef min +#undef min #endif namespace easypr { - - class Utils { - public: - static long getTimestamp(); - - /* - * Get file name from a given path - * bool postfix: including the postfix - */ - static std::string getFileName(const std::string &path, const bool postfix = false); - - /* - * Split the given string into segements by a delimiter - */ - static std::vector splitString(const std::string &str, const char delimiter); - - /* - * returns the smaller of the two numbers - */ - template - static T min(const T &v1, const T &v2) { - return (v1 < v2) ? v1 : v2; - } - - }; - -} -//C++的获取文件夹函数 -void getFiles(std::string path, std::vector& files); +class Utils { + public: + static long getTimestamp(); + + /* + * Get file name from a given path + * bool postfix: including the postfix + */ + static std::string getFileName(const std::string& path, + const bool postfix = false); + + /* + * Split the given string into segements by a delimiter + */ + static std::vector splitString(const std::string& str, + const char delimiter); + + /* + * returns the smaller of the two numbers + */ + template + static T min(const T& v1, const T& v2) { + return (v1 < v2) ? v1 : v2; + } + + /* + * Get files from a given folder + * all: including all sub-folders + */ + static std::vector getFiles(const std::string& folder, + const bool all = true); +}; + +} //! levenshtein距离,用于计算两个车牌的距离 //!EasyPR中用levenshtein距离衡量车牌识别与真实车牌的误差 diff --git a/src/main.cpp b/src/main.cpp index 6db4bb8..62c0d43 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -430,4 +430,4 @@ void cmdMain(int argc, char *argv[]) } catch (const std::exception &err) { cout << err.what() << endl; } -} \ No newline at end of file +} diff --git a/src/test/accuracy_test.cpp b/src/test/accuracy_test.cpp index bdb7995..61b9f27 100644 --- a/src/test/accuracy_test.cpp +++ b/src/test/accuracy_test.cpp @@ -7,203 +7,180 @@ using namespace easypr; -int acurayTest(const string& test_path) -{ - ////获取该路径下的所有文件 - vector files; - getFiles(test_path, files); - - CPlateLocate lo; - CPlateJudge ju; - CPlateRecognize pr; - - pr.LoadANN("model/ann.xml"); - pr.LoadSVM("model/svm.xml"); - pr.setLifemode(true); - pr.setDebug(true); - - // 设置要处理的一张图片中最多有多少车牌 - pr.setMaxPlates(4); - - //CPlateDetect pd; - //pd.LoadSVM("model/svm.xml"); - //pd.setPDLifemode(true); - - int size = files.size(); - //int size = 200; - - if (0 == size) - { - cout << "No File Found in general_test/native_test!" << endl; - return 0; - } - - 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; - - // 开始和结束时间 - time_t begin, end; - time(&begin); - - for (int i = 0; i < size; i++) - { - string filepath = files[i].c_str(); - cout << "------------------" << endl; - - // 获取真实的车牌 - string plateLicense = Utils::getFileName(filepath); - cout << "原牌:" << plateLicense << endl; - - // EasyPR开始判断车牌 - Mat src = imread(filepath); - - vector plateVec; - int result = pr.plateRecognize(src, plateVec); - if (result == 0) - { - int num = plateVec.size(); - - if (num == 0) - { - cout << ""<< "无车牌" < 1) - { - // 多车牌使用diff最小的那个记录 - int mindiff = 10000; - for (int j = 0; j < num; j++) - { - cout << plateVec[j] << " (" << j+1 << ")"< spilt_plate = Utils::splitString(colorplate, ':'); - - int size = spilt_plate.size(); - if (size == 2 && spilt_plate[1] != "") - { - int diff = levenshtein_distance(plateLicense, spilt_plate[size-1]); - if (diff < mindiff) - mindiff = diff; - } - } - - cout << "差距:" << mindiff << "个字符" << endl; - if(mindiff == 0) - { - // 完全匹配 - match_count++; - } - diff_all = diff_all + mindiff; - } - else - { - // 单车牌只计算一次diff - for (int j = 0; j < num; j++) - { - cout << plateVec[j] < spilt_plate = Utils::splitString(colorplate, ':'); - - int size = spilt_plate.size(); - if (size == 2 && spilt_plate[1] != "") - { - int diff = levenshtein_distance(plateLicense, spilt_plate[size-1]); - cout << "差距:" << diff << "个字符" << endl; - - if(diff == 0) - { - // 完全匹配 - match_count++; - } - diff_all = diff_all + diff; - } - } - - } - } - else - { - cout << "错误码:" << result << endl; - count_err++; - } - count_all++; - - } - time(&end); - - cout << "------------------" << endl; - cout << "Easypr accuracy test end!" << endl; - cout << "------------------" << endl; - cout << endl; - cout << "统计参数:" << endl; - cout << "总图片数:" << count_all << "张, "; - cout << "未识出图片:" << count_norecogin << "张, "; - - float count_recogin = count_all - (count_err + count_norecogin); - float count_rate = count_recogin / count_all; - float count_norate = 1 - count_rate; - cout << "定位率:" << count_rate * 100 << "% " << endl; - - diff_avg = diff_all / count_recogin; - match_rate = match_count/ count_recogin * 100; - - cout << "平均字符差距:" << diff_avg << "个, "; - cout << "完全匹配数:" << match_count << "张, "; - cout << "完全匹配率:" << match_rate << "% " << endl; - - - double seconds = difftime(end, begin); - double avgsec = seconds / double(count_all); - - cout << "总时间:" << seconds << "秒, "; - cout << "平均执行时间:" << avgsec << "秒 " << endl; - - cout << endl; - - cout << "------------------" << endl; - - ofstream myfile("run_accuracy.txt", ios::app); - if (myfile.is_open()) - { - time_t t = time(0); // get time now - struct tm * now = localtime(&t); - char buf[80]; - - strftime(buf, sizeof(buf), "%Y-%m-%d %X", now); - myfile << string(buf) << endl; - - myfile << "总图片数:" << count_all << "张, "; - myfile << "未识出图片:" << count_norecogin << "张, "; - myfile << "定位率:" << count_rate * 100 << "% " << endl; - myfile << "平均字符差距:" << diff_avg << "个, "; - myfile << "完全匹配数:" << match_count << "张, "; - myfile << "完全匹配率:" << match_rate << "% " << endl; - myfile << "总时间:" << seconds << "秒, "; - myfile << "平均执行时间:" << avgsec << "秒 " << endl; - myfile.close(); - } - else - cout << "Unable to open file"; - - return 0; +int acurayTest(const string& test_path) { + ////获取该路径下的所有文件 + auto files = Utils::getFiles(test_path); + + // CPlateLocate lo; + // CPlateJudge ju; + CPlateRecognize pr; + + pr.LoadANN("model/ann.xml"); + pr.LoadSVM("model/svm.xml"); + pr.setLifemode(true); + pr.setDebug(true); + + // 设置要处理的一张图片中最多有多少车牌 + pr.setMaxPlates(4); + + // CPlateDetect pd; + // pd.LoadSVM("model/svm.xml"); + // pd.setPDLifemode(true); + + int size = files.size(); + // int size = 200; + + if (0 == size) { + cout << "No File Found in general_test/native_test!" << endl; + return 0; + } + + 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; + + // 开始和结束时间 + time_t begin, end; + time(&begin); + + for (int i = 0; i < size; i++) { + string filepath = files[i].c_str(); + cout << "------------------" << endl; + + // 获取真实的车牌 + string plateLicense = Utils::getFileName(filepath); + cout << "原牌:" << plateLicense << endl; + + // EasyPR开始判断车牌 + Mat src = imread(filepath); + + vector plateVec; + int result = pr.plateRecognize(src, plateVec); + if (result == 0) { + int num = plateVec.size(); + + if (num == 0) { + cout << "无车牌" << endl; + if (plateLicense != "无车牌") count_norecogin++; + } else if (num > 1) { + // 多车牌使用diff最小的那个记录 + int mindiff = 10000; + for (int j = 0; j < num; j++) { + cout << plateVec[j] << " (" << j + 1 << ")" << endl; + string colorplate = plateVec[j]; + + // 计算"蓝牌:苏E7KU22"中冒号后面的车牌大小" + vector spilt_plate = Utils::splitString(colorplate, ':'); + + int size = spilt_plate.size(); + if (size == 2 && spilt_plate[1] != "") { + int diff = + levenshtein_distance(plateLicense, spilt_plate[size - 1]); + if (diff < mindiff) mindiff = diff; + } + } + + cout << "差距:" << mindiff << "个字符" << endl; + if (mindiff == 0) { + // 完全匹配 + match_count++; + } + diff_all = diff_all + mindiff; + } else { + // 单车牌只计算一次diff + for (int j = 0; j < num; j++) { + cout << plateVec[j] << endl; + string colorplate = plateVec[j]; + + // 计算"蓝牌:苏E7KU22"中冒号后面的车牌大小" + vector spilt_plate = Utils::splitString(colorplate, ':'); + + int size = spilt_plate.size(); + if (size == 2 && spilt_plate[1] != "") { + int diff = + levenshtein_distance(plateLicense, spilt_plate[size - 1]); + cout << "差距:" << diff << "个字符" << endl; + + if (diff == 0) { + // 完全匹配 + match_count++; + } + diff_all = diff_all + diff; + } + } + } + } else { + cout << "错误码:" << result << endl; + count_err++; + } + count_all++; + } + time(&end); + + cout << "------------------" << endl; + cout << "Easypr accuracy test end!" << endl; + cout << "------------------" << endl; + cout << endl; + cout << "统计参数:" << endl; + cout << "总图片数:" << count_all << "张, "; + cout << "未识出图片:" << count_norecogin << "张, "; + + float count_recogin = count_all - (count_err + count_norecogin); + float count_rate = count_recogin / count_all; + //float count_norate = 1 - count_rate; + cout << "定位率:" << count_rate * 100 << "% " << endl; + + diff_avg = diff_all / count_recogin; + match_rate = match_count / count_recogin * 100; + + cout << "平均字符差距:" << diff_avg << "个, "; + cout << "完全匹配数:" << match_count << "张, "; + cout << "完全匹配率:" << match_rate << "% " << endl; + + double seconds = difftime(end, begin); + double avgsec = seconds / double(count_all); + + cout << "总时间:" << seconds << "秒, "; + cout << "平均执行时间:" << avgsec << "秒 " << endl; + + cout << endl; + + cout << "------------------" << endl; + + ofstream myfile("run_accuracy.txt", ios::app); + if (myfile.is_open()) { + time_t t = time(0); // get time now + struct tm* now = localtime(&t); + char buf[80]; + + strftime(buf, sizeof(buf), "%Y-%m-%d %X", now); + myfile << string(buf) << endl; + + myfile << "总图片数:" << count_all << "张, "; + myfile << "未识出图片:" << count_norecogin << "张, "; + myfile << "定位率:" << count_rate * 100 << "% " << endl; + myfile << "平均字符差距:" << diff_avg << "个, "; + myfile << "完全匹配数:" << match_count << "张, "; + myfile << "完全匹配率:" << match_rate << "% " << endl; + myfile << "总时间:" << seconds << "秒, "; + myfile << "平均执行时间:" << avgsec << "秒 " << endl; + myfile.close(); + } else { + cout << "Unable to open file"; + } + return 0; } \ No newline at end of file diff --git a/src/train/ann_train.cpp b/src/train/ann_train.cpp index 01d0e76..30b0d44 100644 --- a/src/train/ann_train.cpp +++ b/src/train/ann_train.cpp @@ -16,7 +16,7 @@ #if defined (WIN32) || defined (_WIN32) #include #elif defined (linux) || defined (__linux__) -#include +//#include #endif #include @@ -140,8 +140,7 @@ int saveTrainData() stringstream ss(stringstream::in | stringstream::out); ss << path << "/" << strCharacters[i]; - vector files; - getFiles(ss.str(), files); + auto files = Utils::getFiles(ss.str()); int size = files.size(); for (int j = 0; j < size; j++) @@ -168,9 +167,8 @@ int saveTrainData() cout << "Character: "<< strChinese[i] << "\n"; stringstream ss(stringstream::in | stringstream::out); ss << path << "/" << strChinese[i]; - - vector files; - getFiles(ss.str(), files); + + auto files = Utils::getFiles(ss.str()); int size = files.size(); for (int j = 0; j < size; j++) @@ -276,4 +274,4 @@ int annMain() int end; cin >> end; return 0; -} \ No newline at end of file +} diff --git a/src/train/svm_train.cpp b/src/train/svm_train.cpp index f65f1e7..2c6c8d3 100644 --- a/src/train/svm_train.cpp +++ b/src/train/svm_train.cpp @@ -13,10 +13,9 @@ void learn2HasPlate(float bound = 0.7) { const char * filePath = "train/data/plate_detect_svm/learn/HasPlate"; - vector files; ////获取该路径下的所有文件 - getFiles(filePath, files ); + auto files = Utils::getFiles(filePath); int size = files.size(); if (0 == size) { @@ -60,10 +59,9 @@ void learn2NoPlate(float bound = 0.7) { const char * filePath = "train/data/plate_detect_svm/learn/NoPlate"; - vector files; ////获取该路径下的所有文件 - getFiles(filePath, files ); + auto files = Utils::getFiles(filePath); int size = files.size(); if (0 == size) { cout << "File not found in " << filePath << endl; @@ -107,10 +105,9 @@ void getHasPlateTrain(Mat& trainingImages, vector& trainingLabels, { int label = 1; const char * filePath = "train/data/plate_detect_svm/train/HasPlate"; - vector files; ////获取该路径下的所有文件 - getFiles(filePath, files ); + auto files = Utils::getFiles(filePath); int size = files.size(); if (0 == size) { @@ -139,10 +136,9 @@ void getNoPlateTrain(Mat& trainingImages, vector& trainingLabels, { int label = 0; const char * filePath = "train/data/plate_detect_svm/train/NoPlate"; - vector files; ////获取该路径下的所有文件 - getFiles(filePath, files ); + auto files = Utils::getFiles(filePath); int size = files.size(); if (0 == size) { @@ -169,10 +165,9 @@ void getHasPlateTest(vector& testingImages, vector& testingLabels) { int label = 1; const char * filePath = "train/data/plate_detect_svm/test/HasPlate"; - vector files; ////获取该路径下的所有文件 - getFiles(filePath, files ); + auto files = Utils::getFiles(filePath); int size = files.size(); if (0 == size) { @@ -194,10 +189,9 @@ void getNoPlateTest(vector& testingImages, vector& testingLabels) { int label = 0; const char * filePath = "train/data/plate_detect_svm/test/NoPlate"; - vector files; ////获取该路径下的所有文件 - getFiles(filePath, files ); + auto files = Utils::getFiles(filePath); int size = files.size(); if (0 == size) { diff --git a/src/util/general_test_prepare.cpp b/src/util/general_test_prepare.cpp index f7c07f5..43ff83e 100644 --- a/src/util/general_test_prepare.cpp +++ b/src/util/general_test_prepare.cpp @@ -19,8 +19,7 @@ const string dst_path = "F:/data/easypr-data/tmp-6"; int general_test() { ////获取该路径下的所有文件 - vector files; - getFiles(src_path, files); + auto files = Utils::getFiles(src_path); CPlateLocate lo; CPlateJudge ju; diff --git a/src/util/generate_gdts.cpp b/src/util/generate_gdts.cpp index 459af5a..938ea6b 100644 --- a/src/util/generate_gdts.cpp +++ b/src/util/generate_gdts.cpp @@ -31,8 +31,7 @@ int generate_gdts() string cascadeName="model/haarcascade_frontalface_alt_tree.xml"; ////获取该路径下的所有文件 - vector files; - getFiles(src_path, files); + auto files = Utils::getFiles(src_path); int size = files.size(); if (0 == size) diff --git a/src/util/learn_prepare.cpp b/src/util/learn_prepare.cpp index f18660e..077b3f8 100644 --- a/src/util/learn_prepare.cpp +++ b/src/util/learn_prepare.cpp @@ -24,8 +24,7 @@ char * noPlatePath = "F:/data/easypr-data/learn/noPlate/"; void label_data() { ////获取该路径下的所有文件 - vector files; - getFiles(notlabelPath, files); + auto files = Utils::getFiles(notlabelPath); CPlateLocate lo; CPlateJudge ju; diff --git a/src/util/mc_data_prepare.cpp b/src/util/mc_data_prepare.cpp index 818afdc..fe8a134 100644 --- a/src/util/mc_data_prepare.cpp +++ b/src/util/mc_data_prepare.cpp @@ -9,7 +9,7 @@ #if defined (WIN32) || defined (_WIN32) #include #elif defined (linux) || defined (__linux__) -#include +//#include #endif #include @@ -24,8 +24,6 @@ using namespace easypr; const int LEARANDATA_COUNT = 5000; -void getFiles( string path, vector& files ); - //! 省份对应map map mc_map; @@ -195,8 +193,7 @@ void getLearnData() const char * filePath = "F:/data/easypr-data/rawdata"; ////获取该路径下的所有文件 - vector files; - getFiles(filePath, files ); + auto files = Utils::getFiles(filePath); int size = files.size(); if (0 == size) { @@ -248,8 +245,7 @@ void changeFileName() char * filePath = "F:/data/PlateLocate/pic1"; ////获取该路径下的所有文件 - vector files; - getFiles(filePath, files ); + auto files = Utils::getFiles(filePath); int size = files.size(); if (0 == size) @@ -276,4 +272,4 @@ void changeFileName() } } -} \ No newline at end of file +} diff --git a/src/util/util.cpp b/src/util/util.cpp index c9163c6..122b68d 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -1,168 +1,181 @@ -#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 -#elif defined (__APPLE__) - #include - #include - #include - #include -#endif - -#include -#include -#include - #include "../include/util.h" +#include + +#if defined(WIN32) || defined(_WIN32) +#include +#include +#elif defined(linux) || defined(__linux__) +//#include +//#include +//#include +#include +#include +#include +#elif defined(__APPLE__) +#include +#include +#include +#include +#endif using namespace std; using namespace easypr; -long -Utils::getTimestamp() -{ -#if defined (WIN32) || defined (_WIN32) - return GetTickCount(); +long Utils::getTimestamp() { +#if defined(WIN32) || defined(_WIN32) + return GetTickCount(); #endif - -#if (linux) || defined (__linux__) - struct timespec ts; - - clock_gettime(CLOCK_MONOTONIC, &ts); - - return (ts.tv_sec * 1e3 + ts.tv_nsec / 1e6); + +#if (linux) || defined(__linux__) + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + return (ts.tv_sec * 1e3 + ts.tv_nsec / 1e6); #endif - -#if defined (__APPLE__) - // 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. - struct timeb tb; - ftime(&tb); - return tb.time * 1e3 + tb.millitm; + +#if defined(__APPLE__) + // 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. + struct timeb tb; + ftime(&tb); + return tb.time * 1e3 + tb.millitm; #endif } -std::string -Utils::getFileName(const string &path, const bool postfix /* = false */) -{ - if (!path.empty()) { -#if defined (WIN32) || defined (_WIN32) - size_t last_slash = path.find_last_of('\\'); +std::string Utils::getFileName(const string &path, + const bool postfix /* = false */) { + if (!path.empty()) { +#if defined(WIN32) || defined(_WIN32) + size_t last_slash = path.find_last_of('\\'); #else - size_t last_slash = path.find_last_of('/'); + size_t last_slash = path.find_last_of('/'); #endif - size_t last_dot = path.find_last_of('.'); - - if (last_dot < last_slash || last_dot == string::npos) { - // not found the right dot of the postfix, - // return the file name directly - return path.substr(last_slash + 1); - } else { - // the path has a postfix - if (postfix) { - // return the file name including postfix - return path.substr(last_slash + 1); - } - // without postfix - return path.substr(last_slash + 1, last_dot - last_slash - 1); - } + size_t last_dot = path.find_last_of('.'); + + if (last_dot < last_slash || last_dot == string::npos) { + // not found the right dot of the postfix, + // return the file name directly + return path.substr(last_slash + 1); + } else { + // the path has a postfix + if (postfix) { + // return the file name including postfix + return path.substr(last_slash + 1); + } + // without postfix + return path.substr(last_slash + 1, last_dot - last_slash - 1); } - return ""; + } + return ""; } -vector -Utils::splitString(const string &str, const char delimiter) -{ - vector splited; - string s(str); - size_t pos; - - while ((pos = s.find(delimiter)) != string::npos ) { - string sec = s.substr(0, pos); - - if (!sec.empty()) { - splited.push_back(s.substr(0, pos)); - } - - s = s.substr(pos + 1); +vector Utils::splitString(const string &str, const char delimiter) { + vector splited; + string s(str); + size_t pos; + + while ((pos = s.find(delimiter)) != string::npos) { + string sec = s.substr(0, pos); + + if (!sec.empty()) { + splited.push_back(s.substr(0, pos)); } - - splited.push_back(s); - - return splited; + + s = s.substr(pos + 1); + } + + splited.push_back(s); + + return splited; } -#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); +vector Utils::getFiles(const string &folder, + const bool all /* = true */) { + vector files; +#if defined(WIN32) || defined(_WIN32) + //文件句柄 + 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__) || defined(__APPLE__) + list subfolders; + subfolders.push_back(folder); + + while (!subfolders.empty()) { + string current_folder(subfolders.back()); + + if (*(current_folder.end() - 1) != '/') { + current_folder.push_back('/'); } -} -#elif defined (linux) || defined (__linux__) || defined (__APPLE__) - -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); - } - } + DIR *pdir = opendir(current_folder.c_str()); + + subfolders.pop_back(); + + if (!pdir) { + continue; } - closedir(dirp); -} + + dirent *dir = NULL; + + while ((dir = readdir(pdir)) != NULL) { + // iterates the current folder, search file & sub folder + struct stat st; + + if (all && (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))) { + // must ignore . & .. + continue; + } + + if (!strcmp(dir->d_name, ".DS_Store")) { + // in OSX, 'finder' will create .DS_Store + continue; + } + + string file_path; + + file_path.append(current_folder.c_str()); + file_path.append(dir->d_name); + + if (lstat(file_path.c_str(), &st) < 0) { + // perror("lstat"); + continue; + } + + if (S_ISDIR(st.st_mode)) { + // it's a sub folder + if (all) { + // will search sub folder + string folder(current_folder); + folder.append(dir->d_name); + + subfolders.push_back(folder.c_str()); + } + } else { + // it's a file + files.push_back(file_path); + } + } // while + closedir(pdir); + } #endif + return files; +}