|
|
|
@ -1,127 +1,127 @@
|
|
|
|
|
#include "easypr/util/util.h"
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
#ifdef OS_WINDOWS
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#include <direct.h>
|
|
|
|
|
#include <io.h>
|
|
|
|
|
#define PATH_DELIMITER '\\'
|
|
|
|
|
// #ifdef OS_WINDOWS
|
|
|
|
|
#include <windows.h> // 包含windows.h头文件,用于Windows平台的系统调用
|
|
|
|
|
#include <direct.h> // 包含direct.h头文件,用于Windows平台的目录操作
|
|
|
|
|
#include <io.h> // 包含io.h头文件,用于Windows平台的IO操作
|
|
|
|
|
#define PATH_DELIMITER '\\' // 定义路径分隔符为'\\'
|
|
|
|
|
#ifdef min
|
|
|
|
|
#undef min
|
|
|
|
|
#undef min // 如果已经定义了min,取消其定义
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef max
|
|
|
|
|
#undef max
|
|
|
|
|
#undef max // 如果已经定义了max,取消其定义
|
|
|
|
|
#endif
|
|
|
|
|
#elif defined(OS_LINUX) || defined(OS_UNIX)
|
|
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <dirent.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <cstring> // 包含cstring头文件,用于字符串操作
|
|
|
|
|
#include <dirent.h> // 包含dirent.h头文件,用于目录操作
|
|
|
|
|
#include <sys/stat.h> // 包含sys/stat.h头文件,用于文件状态检查
|
|
|
|
|
#include <unistd.h> // 包含unistd.h头文件,用于Unix标准的系统调用
|
|
|
|
|
|
|
|
|
|
#define PATH_DELIMITER '/'
|
|
|
|
|
#define PATH_DELIMITER '/' // 定义路径分隔符为'/'
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef OS_UNIX
|
|
|
|
|
|
|
|
|
|
#include <sys/timeb.h>
|
|
|
|
|
#include <sys/timeb.h> // 包含sys/timeb.h头文件,用于时间操作
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <list>
|
|
|
|
|
#include <opencv2/highgui/highgui.hpp>
|
|
|
|
|
#include <list> // 包含list头文件,用于list数据结构
|
|
|
|
|
#include <opencv2/highgui/highgui.hpp> // 包含opencv的highgui模块,用于图像IO操作
|
|
|
|
|
|
|
|
|
|
namespace easypr {
|
|
|
|
|
namespace easypr { // 定义easypr命名空间
|
|
|
|
|
|
|
|
|
|
long Utils::getTimestamp() {
|
|
|
|
|
long Utils::getTimestamp() { // 定义获取时间戳的函数
|
|
|
|
|
#ifdef OS_WINDOWS
|
|
|
|
|
return static_cast<long>(cv::getTickCount());
|
|
|
|
|
return static_cast<long>(cv::getTickCount()); // Windows平台下,使用opencv的getTickCount函数获取时间戳
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef OS_LINUX
|
|
|
|
|
struct timespec ts;
|
|
|
|
|
struct timespec ts; // 定义timespec结构体,用于获取时间
|
|
|
|
|
|
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &ts); // 获取当前时间
|
|
|
|
|
|
|
|
|
|
return (ts.tv_sec * 1e3 + ts.tv_nsec / 1e6);
|
|
|
|
|
return (ts.tv_sec * 1e3 + ts.tv_nsec / 1e6); // 返回毫秒级的时间戳
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#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.
|
|
|
|
|
struct timeb tb;
|
|
|
|
|
ftime(&tb);
|
|
|
|
|
return long(tb.time * 1e3 + tb.millitm);
|
|
|
|
|
struct timeb tb; // 定义timeb结构体,用于获取时间
|
|
|
|
|
ftime(&tb); // 获取当前时间
|
|
|
|
|
return long(tb.time * 1e3 + tb.millitm); // 返回毫秒级的时间戳
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string Utils::getFileName(const std::string &path,
|
|
|
|
|
const bool postfix /* = false */) {
|
|
|
|
|
if (!path.empty()) {
|
|
|
|
|
size_t last_slash = utils::get_last_slash(path);
|
|
|
|
|
size_t last_dot = path.find_last_of('.');
|
|
|
|
|
const bool postfix /* = false */) { // 定义获取文件名的函数
|
|
|
|
|
if (!path.empty()) { // 如果路径不为空
|
|
|
|
|
size_t last_slash = utils::get_last_slash(path); // 获取路径中最后一个斜杠的位置
|
|
|
|
|
size_t last_dot = path.find_last_of('.'); // 获取路径中最后一个点的位置
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
return path.substr(last_slash + 1); // 如果路径有后缀,并且需要返回后缀,返回包含后缀的文件名
|
|
|
|
|
}
|
|
|
|
|
// without postfix
|
|
|
|
|
return path.substr(last_slash + 1, last_dot - last_slash - 1);
|
|
|
|
|
return path.substr(last_slash + 1, last_dot - last_slash - 1); // 如果路径有后缀,但不需要返回后缀,返回不包含后缀的文件名
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
return ""; // 如果路径为空,返回空字符串
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> Utils::splitString(const std::string &str,
|
|
|
|
|
const char delimiter) {
|
|
|
|
|
std::vector<std::string> splited;
|
|
|
|
|
std::string s(str);
|
|
|
|
|
size_t pos;
|
|
|
|
|
const char delimiter) { // 定义字符串分割函数
|
|
|
|
|
std::vector<std::string> splited; // 定义存储分割结果的vector
|
|
|
|
|
std::string s(str); // 复制输入的字符串
|
|
|
|
|
size_t pos; // 定义分割位置
|
|
|
|
|
|
|
|
|
|
while ((pos = s.find(delimiter)) != std::string::npos) {
|
|
|
|
|
std::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));
|
|
|
|
|
if (!sec.empty()) { // 如果子串不为空
|
|
|
|
|
splited.push_back(s.substr(0, pos)); // 将子串添加到分割结果中
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = s.substr(pos + 1);
|
|
|
|
|
s = s.substr(pos + 1); // 更新待分割的字符串
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
splited.push_back(s);
|
|
|
|
|
splited.push_back(s); // 将最后一个子串添加到分割结果中
|
|
|
|
|
|
|
|
|
|
return splited;
|
|
|
|
|
return splited; // 返回分割结果
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> Utils::getFiles(const std::string &folder,
|
|
|
|
|
const bool all /* = true */) {
|
|
|
|
|
std::vector<std::string> files;
|
|
|
|
|
std::list<std::string> subfolders;
|
|
|
|
|
subfolders.push_back(folder);
|
|
|
|
|
const bool all /* = true */) { // 定义获取文件列表的函数
|
|
|
|
|
std::vector<std::string> files; // 定义存储文件列表的vector
|
|
|
|
|
std::list<std::string> subfolders; // 定义存储子文件夹的list
|
|
|
|
|
subfolders.push_back(folder); // 将输入的文件夹添加到子文件夹列表中
|
|
|
|
|
#ifdef OS_WINDOWS
|
|
|
|
|
while (!subfolders.empty()) {
|
|
|
|
|
std::string current_folder(subfolders.back());
|
|
|
|
|
while (!subfolders.empty()) { // 当子文件夹列表不为空时
|
|
|
|
|
std::string current_folder(subfolders.back()); // 获取当前处理的文件夹
|
|
|
|
|
|
|
|
|
|
if (*(current_folder.end() - 1) != '/') {
|
|
|
|
|
current_folder.append("/*");
|
|
|
|
|
current_folder.append("/*"); // 如果当前文件夹的路径不以'/'结尾,添加'/*'
|
|
|
|
|
} else {
|
|
|
|
|
current_folder.append("*");
|
|
|
|
|
current_folder.append("*"); // 如果当前文件夹的路径以'/'结尾,添加'*'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
subfolders.pop_back();
|
|
|
|
|
subfolders.pop_back(); // 从子文件夹列表中移除当前处理的文件夹
|
|
|
|
|
|
|
|
|
|
struct _finddata_t file_info;
|
|
|
|
|
auto file_handler = _findfirst(current_folder.c_str(), &file_info);
|
|
|
|
|
struct _finddata_t file_info; // 定义文件信息结构体
|
|
|
|
|
auto file_handler = _findfirst(current_folder.c_str(), &file_info); // 打开当前文件夹
|
|
|
|
|
|
|
|
|
|
while (file_handler != -1) {
|
|
|
|
|
while (file_handler != -1) { // 当文件夹打开成功时
|
|
|
|
|
if (all &&
|
|
|
|
|
(!strcmp(file_info.name, ".") || !strcmp(file_info.name, ".."))) {
|
|
|
|
|
if (_findnext(file_handler, &file_info) != 0) break;
|
|
|
|
@ -136,7 +136,7 @@ std::vector<std::string> Utils::getFiles(const std::string &folder,
|
|
|
|
|
folder.pop_back();
|
|
|
|
|
folder.append(file_info.name);
|
|
|
|
|
|
|
|
|
|
subfolders.push_back(folder.c_str());
|
|
|
|
|
subfolders.push_back(folder.c_str()); // 如果是子文件夹,并且需要搜索子文件夹,将子文件夹添加到子文件夹列表中
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// it's a file
|
|
|
|
@ -145,24 +145,24 @@ std::vector<std::string> Utils::getFiles(const std::string &folder,
|
|
|
|
|
file_path.assign(current_folder.c_str()).pop_back();
|
|
|
|
|
file_path.append(file_info.name);
|
|
|
|
|
|
|
|
|
|
files.push_back(file_path);
|
|
|
|
|
files.push_back(file_path); // 如果是文件,将文件路径添加到文件列表中
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_findnext(file_handler, &file_info) != 0) break;
|
|
|
|
|
} // while
|
|
|
|
|
_findclose(file_handler);
|
|
|
|
|
_findclose(file_handler); // 关闭文件夹
|
|
|
|
|
}
|
|
|
|
|
#elif defined(OS_LINUX) || defined(OS_UNIX)
|
|
|
|
|
while (!subfolders.empty()) {
|
|
|
|
|
std::string current_folder(subfolders.back());
|
|
|
|
|
while (!subfolders.empty()) { // 当子文件夹列表不为空时
|
|
|
|
|
std::string current_folder(subfolders.back()); // 获取当前处理的文件夹
|
|
|
|
|
|
|
|
|
|
if (*(current_folder.end() - 1) != '/') {
|
|
|
|
|
current_folder.push_back('/');
|
|
|
|
|
current_folder.push_back('/'); // 如果当前文件夹的路径不以'/'结尾,添加'/'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DIR* pdir = opendir(current_folder.c_str());
|
|
|
|
|
DIR* pdir = opendir(current_folder.c_str()); // 打开当前文件夹
|
|
|
|
|
|
|
|
|
|
subfolders.pop_back();
|
|
|
|
|
subfolders.pop_back(); // 从子文件夹列表中移除当前处理的文件夹
|
|
|
|
|
|
|
|
|
|
if (!pdir) {
|
|
|
|
|
continue;
|
|
|
|
@ -170,9 +170,9 @@ std::vector<std::string> Utils::getFiles(const std::string &folder,
|
|
|
|
|
|
|
|
|
|
dirent* dir = NULL;
|
|
|
|
|
|
|
|
|
|
while ((dir = readdir(pdir)) != NULL) {
|
|
|
|
|
while ((dir = readdir(pdir)) != NULL) { // 当读取到文件或文件夹时
|
|
|
|
|
// iterates the current folder, search file & sub folder
|
|
|
|
|
struct stat st;
|
|
|
|
|
struct stat st; // 定义文件状态结构体
|
|
|
|
|
|
|
|
|
|
if (all && (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))) {
|
|
|
|
|
// must ignore . & ..
|
|
|
|
@ -201,93 +201,93 @@ std::vector<std::string> Utils::getFiles(const std::string &folder,
|
|
|
|
|
std::string subfolder(current_folder);
|
|
|
|
|
subfolder.append(dir->d_name);
|
|
|
|
|
|
|
|
|
|
subfolders.push_back(subfolder.c_str());
|
|
|
|
|
subfolders.push_back(subfolder.c_str()); // 如果是子文件夹,并且需要搜索子文件夹,将子文件夹添加到子文件夹列表中
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// it's a file
|
|
|
|
|
files.push_back(file_path);
|
|
|
|
|
files.push_back(file_path); // 如果是文件,将文件路径添加到文件列表中
|
|
|
|
|
}
|
|
|
|
|
} // while
|
|
|
|
|
closedir(pdir);
|
|
|
|
|
closedir(pdir); // 关闭文件夹
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return files;
|
|
|
|
|
return files; // 返回文件列表
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Utils::mkdir(const std::string folder) {
|
|
|
|
|
std::string folder_builder;
|
|
|
|
|
std::string sub;
|
|
|
|
|
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) {
|
|
|
|
|
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);
|
|
|
|
|
if (c == PATH_DELIMITER || it == folder.end() - 1) { // 当遇到路径分隔符或路径结束时
|
|
|
|
|
folder_builder.append(sub); // 将子路径添加到文件夹路径构造器中
|
|
|
|
|
#ifdef OS_WINDOWS
|
|
|
|
|
if (0 != ::_access(folder_builder.c_str(), 0)) {
|
|
|
|
|
if (0 != ::_access(folder_builder.c_str(), 0)) { // 如果文件夹不存在
|
|
|
|
|
#else
|
|
|
|
|
if (0 != ::access(folder_builder.c_str(), 0)) {
|
|
|
|
|
if (0 != ::access(folder_builder.c_str(), 0)) { // 如果文件夹不存在
|
|
|
|
|
#endif
|
|
|
|
|
// this folder not exist
|
|
|
|
|
#ifdef OS_WINDOWS
|
|
|
|
|
if (0 != ::_mkdir(folder_builder.c_str())) {
|
|
|
|
|
if (0 != ::_mkdir(folder_builder.c_str())) { // 如果创建文件夹失败
|
|
|
|
|
#else
|
|
|
|
|
if (0 != ::mkdir(folder_builder.c_str(), S_IRWXU)) {
|
|
|
|
|
if (0 != ::mkdir(folder_builder.c_str(), S_IRWXU)) { // 如果创建文件夹失败
|
|
|
|
|
#endif
|
|
|
|
|
// create failed
|
|
|
|
|
return false;
|
|
|
|
|
return false; // 返回失败
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sub.clear();
|
|
|
|
|
sub.clear(); // 清空子路径
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
return true; // 返回成功
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Utils::imwrite(const std::string &file, const cv::Mat &image) {
|
|
|
|
|
auto folder = file.substr(0, utils::get_last_slash(file));
|
|
|
|
|
Utils::mkdir(folder);
|
|
|
|
|
return cv::imwrite(file, image);
|
|
|
|
|
bool Utils::imwrite(const std::string &file, const cv::Mat &image) { // 定义图像写入函数
|
|
|
|
|
auto folder = file.substr(0, utils::get_last_slash(file)); // 获取文件所在的文件夹
|
|
|
|
|
Utils::mkdir(folder); // 创建文件所在的文件夹
|
|
|
|
|
return cv::imwrite(file, image); // 写入图像
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef OS_WINDOWS
|
|
|
|
|
std::string Utils::utf8_to_gbk(const char* utf8) {
|
|
|
|
|
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
|
|
|
|
|
wchar_t* wszGBK = new wchar_t[len + 1];
|
|
|
|
|
memset(wszGBK, 0, len * 2 + 2);
|
|
|
|
|
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wszGBK, len);
|
|
|
|
|
len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
|
|
|
|
|
char* szGBK = new char[len + 1];
|
|
|
|
|
memset(szGBK, 0, len + 1);
|
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL);
|
|
|
|
|
std::string strTemp(szGBK);
|
|
|
|
|
std::string Utils::utf8_to_gbk(const char* utf8) { // 定义UTF-8到GBK的转换函数
|
|
|
|
|
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0); // 获取转换后的长度
|
|
|
|
|
wchar_t* wszGBK = new wchar_t[len + 1]; // 定义存储转换结果的宽字符数组
|
|
|
|
|
memset(wszGBK, 0, len * 2 + 2); // 初始化宽字符数组
|
|
|
|
|
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wszGBK, len); // 将UTF-8字符串转换为宽字符字符串
|
|
|
|
|
len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL); // 获取转换后的长度
|
|
|
|
|
char* szGBK = new char[len + 1]; // 定义存储转换结果的字符数组
|
|
|
|
|
memset(szGBK, 0, len + 1); // 初始化字符数组
|
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL); // 将宽字符字符串转换为GBK字符串
|
|
|
|
|
std::string strTemp(szGBK); // 将GBK字符串转换为std::string
|
|
|
|
|
if (wszGBK)
|
|
|
|
|
delete[] wszGBK;
|
|
|
|
|
delete[] wszGBK; // 删除宽字符数组
|
|
|
|
|
if (szGBK)
|
|
|
|
|
delete[] szGBK;
|
|
|
|
|
return strTemp;
|
|
|
|
|
delete[] szGBK; // 删除字符数组
|
|
|
|
|
return strTemp; // 返回转换结果
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
std::size_t Utils::get_last_slash(const std::string &path) {
|
|
|
|
|
std::size_t Utils::get_last_slash(const std::string &path) { // 定义获取路径中最后一个斜杠的位置的函数
|
|
|
|
|
#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_1 = path.find_last_of("\\"); // 获取路径中最后一个'\\'的位置
|
|
|
|
|
size_t last_slash_2 = path.find_last_of("/"); // 获取路径中最后一个'/'的位置
|
|
|
|
|
size_t last_slash;
|
|
|
|
|
|
|
|
|
|
if (last_slash_1 != std::string::npos && last_slash_2 != std::string::npos) {
|
|
|
|
|
// C:/path\\to/file.postfix
|
|
|
|
|
last_slash = std::max(last_slash_1, last_slash_2);
|
|
|
|
|
last_slash = std::max(last_slash_1, last_slash_2); // 如果路径中既有'\\'又有'/',取最后出现的一个
|
|
|
|
|
} else {
|
|
|
|
|
// C:\\path\\to\\file.postfix
|
|
|
|
|
// C:/path/to/file.postfix
|
|
|
|
|
last_slash =
|
|
|
|
|
(last_slash_1 == std::string::npos) ? last_slash_2 : last_slash_1;
|
|
|
|
|
(last_slash_1 == std::string::npos) ? last_slash_2 : last_slash_1; // 如果路径中只有'\\'或只有'/',取出现的那一个
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
size_t last_slash = path.find_last_of('/');
|
|
|
|
|
size_t last_slash = path.find_last_of('/'); // 获取路径中最后一个'/'的位置
|
|
|
|
|
#endif
|
|
|
|
|
return last_slash;
|
|
|
|
|
return last_slash; // 返回最后一个斜杠的位置
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace easypr
|