Train_Identify/ai_matrix/myutils/myutils.cpp

822 lines
24 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "myutils.h"
namespace ai_matrix
{
const int TIME_DIFF = 28800; // 8 hour
MyUtils *MyUtils::ins = nullptr;
MyUtils::GarbageCollector MyUtils::gc;
std::mutex MyUtils::mx;
MyUtils *MyUtils::getins()
{
//双层锁,确保线程安全
if (ins == nullptr)
{
std::lock_guard<std::mutex> guard(mx); //防止异常发生不能解锁
if (ins == nullptr)
{
ins = new MyUtils();
}
}
return ins;
}
float MyUtils::getMean(const std::vector<float> &data)
{
int size = data.size();
if (size == 0)
{
return 0;
}
float sum = 0;
for (int i = 0; i < size; i++)
{
sum += data[i];
}
return sum / size;
}
float MyUtils::getMax(const std::vector<float> &data)
{
int size = data.size();
if (size == 0)
{
return 0;
}
float max = 0;
for (int i = 0; i < size; i++)
{
if (i == 0)
{
max = data[i];
}
else if (data[i] > max)
{
max = data[i];
}
}
return max;
}
float MyUtils::getMin(const std::vector<float> &data)
{
int size = data.size();
if (size == 0)
{
return 0;
}
float min = 0;
for (int i = 0; i < size; i++)
{
if (i == 0)
{
min = data[i];
}
else if (data[i] < min)
{
min = data[i];
}
}
return min;
}
float MyUtils::getMedian(const std::vector<float> &data)
{
if (data.size() < 2)
{
return 0;
}
std::vector<float> data_tmp;
int n = data.size();
for (int i = 0; i < n; i++)
{
data_tmp.push_back(data[i]);
}
std::sort(data_tmp.begin(), data_tmp.end(), std::less<float>());
if (n % 2 == 0)
{
return (data_tmp[n / 2] + data_tmp[n / 2 - 1]) / 2;
}
else
{
return data_tmp[(n - 1) / 2];
}
}
std::string MyUtils::get_timestamp_file()
{
time_t timep = time(NULL);
struct tm *p = localtime(&timep);
struct timeval tv;
gettimeofday(&tv, NULL);
int msec = tv.tv_usec / 1000;
char tmp[30] = {0};
sprintf(tmp, "%04d-%02d-%02d-%02d-%02d-%02d-%03d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, msec);
return std::string(tmp);
}
std::string MyUtils::get_date()
{
time_t timep = time(NULL);
struct tm *p = localtime(&timep);
struct timeval tv;
gettimeofday(&tv, NULL);
int msec = tv.tv_usec / 1000;
char tmp[12] = { 0 };
sprintf(tmp, "%04d-%02d-%02d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday);
return std::string(tmp);
}
std::string MyUtils::get_time()
{
time_t timep = time(NULL);
struct tm *p = localtime(&timep);
struct timeval tv;
gettimeofday(&tv, NULL);
int msec = tv.tv_usec / 1000;
char tmp[10] = { 0 };
sprintf(tmp, "%02d-%02d-%02d", p->tm_hour, p->tm_min, p->tm_sec);
return std::string(tmp);
}
std::string MyUtils::get_timestamp_log()
{
time_t timep = time(NULL);
struct tm *p = localtime(&timep);
struct timeval tv;
gettimeofday(&tv, NULL);
int msec = tv.tv_usec / 1000;
char tmp[30] = {0};
sprintf(tmp, "%04d-%02d-%02d %02d:%02d:%02d.%03d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, msec);
return std::string(tmp);
}
std::string MyUtils::create_dir_name(std::string root, std::string name)
{
std::string dir_path = root + "/" + name;
if (access(dir_path.c_str(), F_OK) != 0)
{
if (mkdir(dir_path.c_str(), 0755) != 0) //如果父目录不存在,会创建失败
{
perror("mkdir fail");
return "";
}
}
return dir_path;
}
std::string MyUtils::create_dir_date(std::string root)
{
time_t timep = time(NULL);
struct tm *p = localtime(&timep);
char tmp_date[20] = {0};
sprintf(tmp_date, "%04d-%02d-%02d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday);
std::string dir_path;
dir_path = root + "/" + std::string(tmp_date); //创建日期目录
if (access(dir_path.c_str(), F_OK) != 0)
{
if (mkdir(dir_path.c_str(), 0755) != 0) //如果父目录不存在,会创建失败
{
perror("mkdir fail");
return "";
}
}
return dir_path;
}
std::string MyUtils::create_dir_date_name_time(std::string root, std::string name)
{
time_t timep = time(NULL);
struct tm *p = localtime(&timep);
char tmp_date[20] = {0};
sprintf(tmp_date, "%04d-%02d-%02d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday);
char tmp_time[20] = {0};
sprintf(tmp_time, "%02d-%02d-%02d", p->tm_hour, p->tm_min, p->tm_sec);
std::string dir_path;
dir_path = root + "/" + std::string(tmp_date); //创建日期目录
if (access(dir_path.c_str(), F_OK) != 0)
{
if (mkdir(dir_path.c_str(), 0755) != 0) //如果父目录不存在,会创建失败
{
perror("mkdir fail");
return "";
}
}
dir_path = dir_path + "/" + name + "_" + std::string(tmp_time); //创建点云目录
if (access(dir_path.c_str(), F_OK) != 0)
{
if (mkdir(dir_path.c_str(), 0755) != 0) //如果父目录不存在,会创建失败
{
perror("mkdir fail");
return "";
}
}
return dir_path;
}
std::string MyUtils::create_file_path(std::string root, std::string name, std::string suffix)
{
time_t timep = time(NULL);
struct tm *p = localtime(&timep);
char tmp_date[20] = {0};
sprintf(tmp_date, "%04d-%02d-%02d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday);
char tmp_time[20] = {0};
sprintf(tmp_time, "%02d-%02d-%02d", p->tm_hour, p->tm_min, p->tm_sec);
std::string file_path;
file_path = root + "/" + std::string(tmp_date); //创建日期目录
if (access(file_path.c_str(), F_OK) != 0)
{
if (mkdir(file_path.c_str(), 0755) != 0) //如果父目录不存在,会创建失败
{
perror("mkdir fail");
return "";
}
}
file_path = file_path + "/" + name + "_" + std::string(tmp_time) + suffix; //创建文件
return file_path;
}
//字符串分割函数
std::vector<std::string> MyUtils::split(std::string str, std::string pattern)
{
std::string::size_type pos;
std::vector<std::string> result;
str += pattern; //扩展字符串以方便操作
int size = str.size();
for (int i = 0; i < size; i++)
{
pos = str.find(pattern, i);
if (pos < size)
{
std::string s = str.substr(i, pos - i);
result.push_back(s);
i = pos + pattern.size() - 1;
}
}
return result;
}
std::string MyUtils::getStringFromFloat(float f)
{
std::ostringstream buffer;
buffer << f;
return buffer.str();
}
std::string MyUtils::getStringFromBool(bool b)
{
std::ostringstream buffer;
buffer << b;
return buffer.str();
}
/**
* 拷贝文件
* @param filePath 源文件位置
* @param savePath 将要拷贝的新位置
* @return
*/
bool MyUtils::copyFile(std::string filePath, std::string savePath)
{
FILE *fp, *sp;
fp = fopen(filePath.c_str(), "rb");
sp = fopen(savePath.c_str(), "w+b");
if (!fp || !sp)
{
LogError << "open fial filePath:" << filePath << " or savePath:" << savePath;
return false;
}
void *buffer;
while (!feof(fp))
{
fread(&buffer, 1, 1, fp);
fwrite(&buffer, 1, 1, sp);
}
fclose(fp);
fclose(sp);
return true;
}
std::string& MyUtils::replace_all_distinct(std::string &str, const std::string &old_value, const std::string &new_value)
{
for (std::string::size_type pos(0); pos != std::string::npos; pos += new_value.length()) {
if ((pos = str.find(old_value, pos)) != std::string::npos)
str.replace(pos, old_value.length(), new_value);
else break;
}
return str;
}
/**
* 获取北京当前日期
* inParam : N/A
* outParam: N/A
* return : 日期
*/
std::string MyUtils::GetDate()
{
struct timeval time = {0, 0};
gettimeofday(&time, nullptr);
time_t timep = time.tv_sec + TIME_DIFF;
struct tm *p = gmtime(&timep);
char szTmp[12] = {0};
sprintf(szTmp, "%04d-%02d-%02d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday);
return std::string(szTmp);
}
/**
* 获取北京当前时间
* inParam : N/A
* outParam: N/A
* return : 时间
*/
std::string MyUtils::GetTime()
{
struct timeval time = {0, 0};
gettimeofday(&time, nullptr);
time_t timep = time.tv_sec + TIME_DIFF;
struct tm *p = gmtime(&timep);
char szTmp[10] = {0};
sprintf(szTmp, "%02d-%02d-%02d", p->tm_hour, p->tm_min, p->tm_sec);
return std::string(szTmp);
}
//时间戳转化为时间 毫秒级
std::string MyUtils::Stamp2Time(long long timestamp, bool has_msec)
{
int ms = timestamp % 1000;//取毫秒
time_t tick = (time_t)(timestamp/1000);//转换时间
struct tm tm;
char s[40];
tm = *localtime(&tick);
strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", &tm);
std::string str(s);
if (has_msec)
{
str = str+ "." + std::to_string(ms);
}
return str;
}
/**
* 获取当前时间距1970年的毫秒数
* inParam : N/A
* outParam: N/A
* return : 时间戳
*/
uint64_t MyUtils::GetCurrentTimeMillis()
{
struct timeval tv;
gettimeofday(&tv, NULL);
//printf("tv_sec:%ld, tv_usec:%ld\n", tv.tv_sec, tv.tv_usec);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
/**
* 获取指定时间距1970年的毫秒数 (入参格式YYYY-MM-DD hh-mm-ss)
* inParam : std::string &strDateTime 日期时间
* outParam: N/A
* return : 时间戳
*/
uint64_t MyUtils::GetParamTimeMilliSeconds(std::string &strDateTime)
{
LogDebug << "strDateTime:" << strDateTime;
if (strDateTime.length() != 19)
{
return 0;
}
int iYear = atoi(strDateTime.substr(0, 4).c_str());
int iMon = atoi(strDateTime.substr(5, 2).c_str());
int iDay = atoi(strDateTime.substr(8, 2).c_str());
int iHour = atoi(strDateTime.substr(11, 2).c_str());
int iMin = atoi(strDateTime.substr(14, 2).c_str());
int iSec = atoi(strDateTime.substr(17, 2).c_str());
struct tm stm;
memset(&stm, 0, sizeof(stm));
stm.tm_year = iYear - 1900;
stm.tm_mon = iMon - 1;
stm.tm_mday = iDay;
stm.tm_hour = iHour;
stm.tm_min = iMin;
stm.tm_sec = iSec;
uint64_t i64Ret = (uint64_t)mktime(&stm) * 1000;
LogDebug << iYear << " " << iMon << " " << iDay << " " << iHour << " " << iMin << " " << iSec << " " << i64Ret;
return i64Ret;
}
/**
* Anchor行分割
* inParam : std::string &strLine Anchor一行内容
* : const std::set<char> &setDelimiters 分割符集合
* outParam: N/A
* return : 分割数据
*/
std::vector<float> MyUtils::SplitAnchor(std::string &strLine, const std::set<char> &setDelimiters)
{
std::vector<float> result;
if (strLine.empty())
{
return result;
}
char const *pch = strLine.c_str();
char const *start = pch;
for (; *pch; ++pch)
{
if (setDelimiters.find(*pch) != setDelimiters.end())
{
if (start != pch)
{
std::string tmp(start, pch);
result.push_back(atof(tmp.c_str())); //浮点数
}
start = pch + 1;
}
}
result.push_back(atof(start)); //最后一个内容
return result;
}
/**
* 创建文件夹路径
* inParam : std::string strDirPath :文件夹路径
* outParam: N/A
* return : true/false
*/
bool MyUtils::CreateDirPath(std::string strDirPath)
{
if (strDirPath.back() != '/')
{
strDirPath += "/";
}
if (access(strDirPath.c_str(), F_OK) == 0)
{
return true;
}
std::string::size_type pos = strDirPath.find('/');
while (pos != std::string::npos)
{
std::string strCur = strDirPath.substr(0, pos);
if (!strCur.empty() && access(strCur.c_str(), F_OK) != 0)
{
if (mkdir(strCur.c_str(), 0755) != 0) //如果父目录不存在,会创建失败
{
perror("mkdir fail");
return false;
}
if (chmod(strCur.c_str(), 0777) != 0)
{
perror("chmod fail");
}
}
pos = strDirPath.find('/', pos + 1);
}
return true;
}
#ifdef ASCEND
/**
* 拷贝Device数据到Host
* inParam : void *pDeviceBuffer device内存地址
: uint32_t iBufferSize device内存大小
* outParam: std::shared_ptr<void> *pHostData host内存地址 (size同入参)
* return : N/A
*/
bool MyUtils::MemcpyDeviceToHost(std::shared_ptr<void> *pHostData, const void *pDeviceBuffer, uint32_t iBufferSize)
{
if (pDeviceBuffer == nullptr || iBufferSize == 0)
{
LogError << "MemcpyDeviceToHost fail pDeviceBuffer is null or iBufferSize is 0";
return false;
}
void *pHostBuffer = nullptr;
int iRet = aclrtMallocHost(&pHostBuffer, iBufferSize);
if (iRet != APP_ERR_OK)
{
LogError << "MemcpyDeviceToHost aclrtMallocHost fail, iBufferSize:" << iBufferSize << " iRet:" << iRet;
return false;
}
pHostData->reset(pHostBuffer, aclrtFreeHost);
iRet = aclrtMemcpy(pHostData->get(), iBufferSize, pDeviceBuffer, iBufferSize, ACL_MEMCPY_DEVICE_TO_HOST);
if (iRet != APP_ERR_OK)
{
LogError << "MemcpyDeviceToHost aclrtMemcpy fail, iBufferSize:" << iBufferSize << " iRet:" << iRet;
return false;
}
return true;
}
/**
* 拷贝Host数据到Device
* inParam : void *pHostBuffer host内存地址
: uint32_t iBufferSize host内存大小
: bool bDvppFlag 是否使用dvpp方式申请device内存(默认true)
* outParam: std::shared_ptr<void> *pDeviceData device内存地址 (size同入参)
* return : N/A
*/
bool MyUtils::MemcpyHostToDevice(std::shared_ptr<void> *pDeviceData, const void *pHostBuffer, uint32_t iBufferSize, bool bDvppFlag/*=true*/)
{
if (pHostBuffer == nullptr || iBufferSize == 0)
{
LogError << "MemcpyHostToDevice fail pHostBuffer is null or iBufferSize is 0";
return false;
}
int iRet = APP_ERR_OK;
void *pDeviceBuffer = nullptr;
if (bDvppFlag)
{
int iRet = acldvppMalloc(&pDeviceBuffer, iBufferSize);
if (iRet != APP_ERR_OK)
{
LogError << "MemcpyHostToDevice acldvppMalloc fail, iBufferSize:" << iBufferSize << " iRet:" << iRet;
return false;
}
pDeviceData->reset(pDeviceBuffer, acldvppFree);
}
else
{
int iRet = aclrtMalloc(&pDeviceBuffer, iBufferSize, ACL_MEM_MALLOC_HUGE_FIRST);
if (iRet != APP_ERR_OK)
{
LogError << "MemcpyHostToDevice aclrtMalloc fail, iBufferSize:" << iBufferSize << " iRet:" << iRet;
return false;
}
pDeviceData->reset(pDeviceBuffer, aclrtFree);
}
iRet = aclrtMemcpy(pDeviceData->get(), iBufferSize, pHostBuffer, iBufferSize, ACL_MEMCPY_HOST_TO_DEVICE);
if (iRet != APP_ERR_OK)
{
LogError << "MemcpyHostToDevice aclrtMemcpy fail, iBufferSize:" << iBufferSize << " iRet:" << iRet;
return false;
}
return true;
}
#endif
/**
* 获取指定毫秒数的对应的北京日期时间
* inParam : uint64_t i64MilliSeconds
* outParam: N/A
* return : 日期时间
*/
std::string MyUtils::GetDateTimeByMilliSeconds(uint64_t i64MilliSeconds, bool bFormatFlag/*=false*/)
{
time_t timep = i64MilliSeconds / 1000 + TIME_DIFF;
struct tm *p = gmtime(&timep);
char szTmp[32] = {0};
if (bFormatFlag)
{
sprintf(szTmp, "%04d-%02d-%02d %02d:%02d:%02d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
}
else
{
sprintf(szTmp, "%04d-%02d-%02d %02d-%02d-%02d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
}
return std::string(szTmp);
}
/**
* 校验是否识别该目标
* inParam : std::string &strOneTarget
* outParam: N/A
* return : true/false
*/
bool MyUtils::ChkIsHaveTarget(const std::string &strOneTarget)
{
std::map<int, ai_matrix::DataSourceConfig> mapUseDataSouceCfg = MyYaml::GetIns()->GetUseDataSourceConfig();
bool bFindTarget = false;
for (auto iter = mapUseDataSouceCfg.begin(); iter != mapUseDataSouceCfg.end(); iter++)
{
if (iter->second.strTarget.find(strOneTarget) != std::string::npos)
{
bFindTarget = true;
break;
}
}
return bFindTarget;
}
/**
* 读取json格式文件内容
* inParam : std::string &strFilePath :文件路径
* outParam: Json::Value &jvFileInfo :json格式内容
* return : true/false
*/
bool MyUtils::ReadJsonInfo(Json::Value &jvFileInfo, std::string &strFilePath, int iRetry /*=3*/)
{
std::ifstream ifs(strFilePath.c_str());
int i = 0;
while (!ifs.is_open() && i < iRetry)
{
i++;
usleep(10 * 1000);
ifs.open(strFilePath.c_str());
}
if (!ifs.is_open())
{
// LogWarn << "txt:" << strFilePath << " open fail";
return false;
}
std::string strContent;
getline(ifs, strContent);
ifs.close();
Json::CharReaderBuilder jsrBuilder;
std::shared_ptr<Json::CharReader> reader(jsrBuilder.newCharReader());
JSONCPP_STRING errs;
if (!reader->parse(strContent.data(), strContent.data() + strContent.size(), &jvFileInfo, &errs))
{
LogWarn << "json parse fail content:" << strContent;
return false;
}
return true;
}
/**
* json格式内容写入文件
* inParam : Json::Value &jvFileInfo :json格式内容
: std::string &strFilePath :文件路径
* outParam: N/A
* return : true/false
*/
bool MyUtils::WriteJsonInfo(Json::Value &jvFileInfo, std::string &strFilePath)
{
Json::StreamWriterBuilder jswBuilder;
jswBuilder["indentation"] = "";
std::string strFrameInfo = Json::writeString(jswBuilder, jvFileInfo);
std::ofstream ofs(strFilePath.c_str());
if (!ofs.is_open())
{
LogWarn << "txt:" << strFilePath << " open fail";
return false;
}
ofs.write(strFrameInfo.c_str(), strFrameInfo.length());
ofs.close();
return true;
}
/**
* 获取第1步得分最高框
* inParam : std::vector<stDetection> &vecResult 推理符合结果
* outParam: std::vector<stDetection> &vecResult 每个类别得分最高结果
* return : N/A
*/
void MyUtils::GetMaxScoreResult(std::vector<stDetection> &vecResult)
{
if (vecResult.size() < 2)
{
return;
}
std::map<Target, std::vector<stDetection>> mapResult;
for (size_t i = 0; i < vecResult.size(); i++)
{
stDetection stDTemp = vecResult.at(i);
if (stDTemp.class_id == 0)
{
mapResult[HEAD].emplace_back(stDTemp);
}
else if (stDTemp.class_id == 1)
{
mapResult[PRO].emplace_back(stDTemp);
}
else if ((stDTemp.class_id >= 2 && stDTemp.class_id <= 6) || stDTemp.class_id == 8 || stDTemp.class_id == 15)
{
mapResult[NUM].emplace_back(stDTemp);
}
else if (stDTemp.class_id >= 9 && stDTemp.class_id <= 17 && stDTemp.class_id != 15)
{
mapResult[TRAINSPACE].emplace_back(stDTemp);
}
else if (stDTemp.class_id == 18)
{
mapResult[SPACE].emplace_back(stDTemp);
}
}
//清空之前的结果
vecResult.clear();
// 每个类别中,获取得分最高的框
for (auto iter = mapResult.begin(); iter != mapResult.end(); iter++)
{
int iMaxPos = -1;
for (size_t i = 0; i < iter->second.size(); i++)
{
if (iMaxPos == -1)
{
iMaxPos = i;
}
else if (iter->second.at(i).class_conf > iter->second.at(iMaxPos).class_conf)
{
iMaxPos = i;
}
}
if (iMaxPos >= 0)
{
vecResult.emplace_back(iter->second.at(iMaxPos));
}
}
}
/**
* 获取第二步缩放比例
* inParam : Step1Location &step1Location 第一步大框
: int iModelWidth 模型宽
: int iModelHeight 模型高
* outParam: N/A
* return : 缩放比例
*/
float MyUtils::GetStep2ResizeRatio(Step1Location &step1Location, int iModelWidth, int iModelHeight)
{
uint32_t iCropgWidth = step1Location.fRBX - step1Location.fLTX;
uint32_t iCropHeight = step1Location.fRBY - step1Location.fLTY;
float fRatioW = static_cast<float>(iCropgWidth) / iModelWidth;
float fRatioH = static_cast<float>(iCropHeight) / iModelHeight;
return (fRatioW > fRatioH) ? fRatioW : fRatioH;
}
/**
* 第二步坐标还原
* inParam : SingleData &singleData
: float fResizeRatio 比例
: std::shared_ptr<ProcessData> pProcessData 待处理数据
: Step1Location &step1Location 第一步大框在原图坐标
* outParam: SingleData &singleData
* return : N/A
*/
void MyUtils::Step2ResetLocation(SingleData &singleData, float fResizeRatio,
std::shared_ptr<ProcessData> pProcessData, Step1Location &step1Location)
{
uint32_t iOrigWidth = pProcessData->iWidth;
uint32_t iOrigHeight = pProcessData->iHeight;
singleData.fLTX = singleData.fLTX * fResizeRatio + step1Location.fLTX;
singleData.fLTY = singleData.fLTY * fResizeRatio + step1Location.fLTY;
singleData.fRBX = singleData.fRBX * fResizeRatio + step1Location.fLTX;
singleData.fRBY = singleData.fRBY * fResizeRatio + step1Location.fLTY;
singleData.fLTX = (singleData.fLTX < iOrigWidth) ? singleData.fLTX : iOrigWidth;
singleData.fLTY = (singleData.fLTY < iOrigHeight) ? singleData.fLTY : iOrigHeight;
singleData.fRBX = (singleData.fRBX < iOrigWidth) ? singleData.fRBX : iOrigWidth;
singleData.fRBY = (singleData.fRBY < iOrigHeight) ? singleData.fRBY : iOrigHeight;
}
}