Commit 5a456a2a authored by yaoht's avatar yaoht
Browse files

init commit

parent a63911bb
Pipeline #990 canceled with stages
person
bicycle
car
motorbike
aeroplane
bus
train
truck
boat
traffic light
fire hydrant
stop sign
parking meter
bench
bird
cat
dog
horse
sheep
cow
elephant
bear
zebra
giraffe
backpack
umbrella
handbag
tie
suitcase
frisbee
skis
snowboard
sports ball
kite
baseball bat
baseball glove
skateboard
surfboard
tennis racket
bottle
wine glass
cup
fork
knife
spoon
bowl
banana
apple
sandwich
orange
broccoli
carrot
hot dog
pizza
donut
cake
chair
sofa
pottedplant
bed
diningtable
toilet
tvmonitor
laptop
mouse
remote
keyboard
cell phone
microwave
oven
toaster
sink
refrigerator
book
clock
vase
scissors
teddy bear
hair drier
toothbrush
// 常用定义
#ifndef __COMMON_DEFINITION_H__
#define __COMMON_DEFINITION_H__
#include <opencv2/opencv.hpp>
namespace migraphxSamples
{
// 路径分隔符(Linux:‘/’,Windows:’\\’)
#ifdef _WIN32
#define PATH_SEPARATOR '\\'
#else
#define PATH_SEPARATOR '/'
#endif
#define CONFIG_FILE "../Resource/Configuration.xml"
typedef enum _ErrorCode
{
SUCCESS = 0, // 0
MODEL_NOT_EXIST, // 模型不存在
CONFIG_FILE_NOT_EXIST, // 配置文件不存在
FAIL_TO_LOAD_MODEL, // 加载模型失败
FAIL_TO_OPEN_CONFIG_FILE, // 加载配置文件失败
IMAGE_ERROR, // 图像错误
} ErrorCode;
typedef struct _ResultOfPrediction
{
float confidence;
int label;
_ResultOfPrediction() : confidence(0.0f), label(0) {}
} ResultOfPrediction;
typedef struct _ResultOfDetection
{
cv::Rect boundingBox;
float confidence;
int classID;
std::string className;
bool exist;
_ResultOfDetection() : confidence(0.0f), classID(0), exist(true) {}
} ResultOfDetection;
typedef struct _InitializationParameterOfDetector
{
std::string parentPath;
std::string configFilePath;
} InitializationParameterOfDetector;
}
#endif
#include <CommonUtility.h>
namespace migraphxSamples
{
bool CompareConfidence(const ResultOfDetection &L, const ResultOfDetection &R)
{
return L.confidence > R.confidence;
}
bool CompareArea(const ResultOfDetection &L, const ResultOfDetection &R)
{
return L.boundingBox.area() > R.boundingBox.area();
}
void NMS(std::vector<ResultOfDetection> &detections, float IOUThreshold)
{
// sort
std::sort(detections.begin(), detections.end(), CompareConfidence);
for (int i = 0; i < detections.size(); ++i)
{
if (detections[i].exist)
{
for (int j = i + 1; j < detections.size(); ++j)
{
if (detections[j].exist)
{
// compute IOU
float intersectionArea = (detections[i].boundingBox & detections[j].boundingBox).area();
float intersectionRate = intersectionArea / (detections[i].boundingBox.area() + detections[j].boundingBox.area() - intersectionArea);
if (intersectionRate > IOUThreshold)
{
detections[j].exist = false;
}
}
}
}
}
}
}
// 常用工具
#ifndef __COMMON_UTILITY_H__
#define __COMMON_UTILITY_H__
#include <CommonDefinition.h>
namespace migraphxSamples
{
// 排序规则: 按照置信度或者按照面积排序
bool CompareConfidence(const ResultOfDetection &L, const ResultOfDetection &R);
bool CompareArea(const ResultOfDetection &L, const ResultOfDetection &R);
// 非极大抑制
void NMS(std::vector<ResultOfDetection> &detections, float IOUThreshold);
}
#endif
#include <Filesystem.h>
#include <algorithm>
#include <sys/stat.h>
#include <sys/types.h>
#include <fstream>
#ifdef _WIN32
#include <io.h>
#include <direct.h>
#include <Windows.h>
#else
#include <unistd.h>
#include <dirent.h>
#endif
// 路径分隔符(Linux:‘/’,Windows:’\\’)
#ifdef _WIN32
#define PATH_SEPARATOR '\\'
#else
#define PATH_SEPARATOR '/'
#endif
using namespace std;
namespace migraphxSamples
{
static std::vector<std::string> SplitString(std::string str, std::string separator)
{
std::string::size_type pos;
std::vector<std::string> result;
str += separator; // 扩展字符串以方便操作
int size = str.size();
for (int i = 0; i < size; i++)
{
pos = str.find(separator, i);
if (pos < size)
{
std::string s = str.substr(i, pos - i);
result.push_back(s);
i = pos + separator.size() - 1;
}
}
return result;
}
#if defined _WIN32 || defined WINCE
const char dir_separators[] = "/\\";
struct dirent
{
const char *d_name;
};
struct DIR
{
#ifdef WINRT
WIN32_FIND_DATAW data;
#else
WIN32_FIND_DATAA data;
#endif
HANDLE handle;
dirent ent;
#ifdef WINRT
DIR() {}
~DIR()
{
if (ent.d_name)
delete[] ent.d_name;
}
#endif
};
DIR *opendir(const char *path)
{
DIR *dir = new DIR;
dir->ent.d_name = 0;
#ifdef WINRT
string full_path = string(path) + "\\*";
wchar_t wfull_path[MAX_PATH];
size_t copied = mbstowcs(wfull_path, full_path.c_str(), MAX_PATH);
CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
dir->handle = ::FindFirstFileExW(wfull_path, FindExInfoStandard,
&dir->data, FindExSearchNameMatch, NULL, 0);
#else
dir->handle = ::FindFirstFileExA((string(path) + "\\*").c_str(),
FindExInfoStandard, &dir->data, FindExSearchNameMatch, NULL, 0);
#endif
if (dir->handle == INVALID_HANDLE_VALUE)
{
/*closedir will do all cleanup*/
delete dir;
return 0;
}
return dir;
}
dirent *readdir(DIR *dir)
{
#ifdef WINRT
if (dir->ent.d_name != 0)
{
if (::FindNextFileW(dir->handle, &dir->data) != TRUE)
return 0;
}
size_t asize = wcstombs(NULL, dir->data.cFileName, 0);
CV_Assert((asize != 0) && (asize != (size_t)-1));
char *aname = new char[asize + 1];
aname[asize] = 0;
wcstombs(aname, dir->data.cFileName, asize);
dir->ent.d_name = aname;
#else
if (dir->ent.d_name != 0)
{
if (::FindNextFileA(dir->handle, &dir->data) != TRUE)
return 0;
}
dir->ent.d_name = dir->data.cFileName;
#endif
return &dir->ent;
}
void closedir(DIR *dir)
{
::FindClose(dir->handle);
delete dir;
}
#else
#include <dirent.h>
#include <sys/stat.h>
const char dir_separators[] = "/";
#endif
static bool isDir(const string &path, DIR *dir)
{
#if defined _WIN32 || defined WINCE
DWORD attributes;
BOOL status = TRUE;
if (dir)
attributes = dir->data.dwFileAttributes;
else
{
WIN32_FILE_ATTRIBUTE_DATA all_attrs;
#ifdef WINRT
wchar_t wpath[MAX_PATH];
size_t copied = mbstowcs(wpath, path.c_str(), MAX_PATH);
CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
status = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &all_attrs);
#else
status = ::GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &all_attrs);
#endif
attributes = all_attrs.dwFileAttributes;
}
return status && ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
#else
(void)dir;
struct stat stat_buf;
if (0 != stat(path.c_str(), &stat_buf))
return false;
int is_dir = S_ISDIR(stat_buf.st_mode);
return is_dir != 0;
#endif
}
bool IsDirectory(const string &path)
{
return isDir(path, NULL);
}
bool Exists(const string &path)
{
#if defined _WIN32 || defined WINCE
BOOL status = TRUE;
{
WIN32_FILE_ATTRIBUTE_DATA all_attrs;
#ifdef WINRT
wchar_t wpath[MAX_PATH];
size_t copied = mbstowcs(wpath, path.c_str(), MAX_PATH);
CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
status = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &all_attrs);
#else
status = ::GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &all_attrs);
#endif
}
return !!status;
#else
struct stat stat_buf;
return (0 == stat(path.c_str(), &stat_buf));
#endif
}
bool IsPathSeparator(char c)
{
return c == '/' || c == '\\';
}
string JoinPath(const string &base, const string &path)
{
if (base.empty())
return path;
if (path.empty())
return base;
bool baseSep = IsPathSeparator(base[base.size() - 1]);
bool pathSep = IsPathSeparator(path[0]);
string result;
if (baseSep && pathSep)
{
result = base + path.substr(1);
}
else if (!baseSep && !pathSep)
{
result = base + PATH_SEPARATOR + path;
}
else
{
result = base + path;
}
return result;
}
static bool wildcmp(const char *string, const char *wild)
{
const char *cp = 0, *mp = 0;
while ((*string) && (*wild != '*'))
{
if ((*wild != *string) && (*wild != '?'))
{
return false;
}
wild++;
string++;
}
while (*string)
{
if (*wild == '*')
{
if (!*++wild)
{
return true;
}
mp = wild;
cp = string + 1;
}
else if ((*wild == *string) || (*wild == '?'))
{
wild++;
string++;
}
else
{
wild = mp;
string = cp++;
}
}
while (*wild == '*')
{
wild++;
}
return *wild == 0;
}
static void glob_rec(const string &directory, const string &wildchart, std::vector<string> &result,
bool recursive, bool includeDirectories, const string &pathPrefix)
{
DIR *dir;
if ((dir = opendir(directory.c_str())) != 0)
{
/* find all the files and directories within directory */
try
{
struct dirent *ent;
while ((ent = readdir(dir)) != 0)
{
const char *name = ent->d_name;
if ((name[0] == 0) || (name[0] == '.' && name[1] == 0) || (name[0] == '.' && name[1] == '.' && name[2] == 0))
continue;
string path = JoinPath(directory, name);
string entry = JoinPath(pathPrefix, name);
if (isDir(path, dir))
{
if (recursive)
glob_rec(path, wildchart, result, recursive, includeDirectories, entry);
if (!includeDirectories)
continue;
}
if (wildchart.empty() || wildcmp(name, wildchart.c_str()))
result.push_back(entry);
}
}
catch (...)
{
closedir(dir);
throw;
}
closedir(dir);
}
else
{
printf("could not open directory: %s", directory.c_str());
}
}
void GetFileNameList(const string &directory, const string &pattern, std::vector<string> &result, bool recursive, bool addPath)
{
// split pattern
vector<string> patterns = SplitString(pattern, ",");
result.clear();
for (int i = 0; i < patterns.size(); ++i)
{
string eachPattern = patterns[i];
std::vector<string> eachResult;
glob_rec(directory, eachPattern, eachResult, recursive, true, directory);
for (int j = 0; j < eachResult.size(); ++j)
{
if (IsDirectory(eachResult[j]))
continue;
if (addPath)
{
result.push_back(eachResult[j]);
}
else
{
result.push_back(GetFileName(eachResult[j]));
}
}
}
std::sort(result.begin(), result.end());
}
void GetFileNameList2(const string &directory, const string &pattern, std::vector<string> &result, bool recursive, bool addPath)
{
// split pattern
vector<string> patterns = SplitString(pattern, ",");
result.clear();
for (int i = 0; i < patterns.size(); ++i)
{
string eachPattern = patterns[i];
std::vector<string> eachResult;
glob_rec(directory, eachPattern, eachResult, recursive, true, directory);
for (int j = 0; j < eachResult.size(); ++j)
{
string filePath = eachResult[j];
if (IsDirectory(filePath))
{
filePath = filePath + "/";
for (int k = 0; k < filePath.size(); ++k)
{
if (IsPathSeparator(filePath[k]))
{
filePath[k] = '/';
}
}
}
if (addPath)
{
result.push_back(filePath);
}
else
{
if (!IsDirectory(filePath))
{
result.push_back(GetFileName(filePath));
}
}
}
}
std::sort(result.begin(), result.end());
}
void RemoveAll(const string &path)
{
if (!Exists(path))
return;
if (IsDirectory(path))
{
std::vector<string> entries;
GetFileNameList2(path, string(), entries, false, true);
for (size_t i = 0; i < entries.size(); i++)
{
const string &e = entries[i];
RemoveAll(e);
}
#ifdef _MSC_VER
bool result = _rmdir(path.c_str()) == 0;
#else
bool result = rmdir(path.c_str()) == 0;
#endif
if (!result)
{
printf("can't remove directory: %s\n", path.c_str());
}
}
else
{
#ifdef _MSC_VER
bool result = _unlink(path.c_str()) == 0;
#else
bool result = unlink(path.c_str()) == 0;
#endif
if (!result)
{
printf("can't remove file: %s\n", path.c_str());
}
}
}
void Remove(const string &directory, const string &extension)
{
DIR *dir;
static int numberOfFiles = 0;
if ((dir = opendir(directory.c_str())) != 0)
{
/* find all the files and directories within directory */
try
{
struct dirent *ent;
while ((ent = readdir(dir)) != 0)
{
const char *name = ent->d_name;
if ((name[0] == 0) || (name[0] == '.' && name[1] == 0) || (name[0] == '.' && name[1] == '.' && name[2] == 0))
continue;
string path = JoinPath(directory, name);
if (isDir(path, dir))
{
Remove(path, extension);
}
// �ж���չ��
if (extension.empty() || wildcmp(name, extension.c_str()))
{
RemoveAll(path);
++numberOfFiles;
printf("%s deleted! number of deleted files:%d\n", path.c_str(), numberOfFiles);
}
}
}
catch (...)
{
closedir(dir);
throw;
}
closedir(dir);
}
else
{
printf("could not open directory: %s", directory.c_str());
}
// ����RemoveAllɾ��Ŀ¼
RemoveAll(directory);
}
string GetFileName(const string &path)
{
string fileName;
int indexOfPathSeparator = -1;
for (int i = path.size() - 1; i >= 0; --i)
{
if (IsPathSeparator(path[i]))
{
fileName = path.substr(i + 1, path.size() - i - 1);
indexOfPathSeparator = i;
break;
}
}
if (indexOfPathSeparator == -1)
{
fileName = path;
}
return fileName;
}
string GetFileName_NoExtension(const string &path)
{
string fileName = GetFileName(path);
string fileName_NoExtension;
for (int i = fileName.size() - 1; i > 0; --i)
{
if (fileName[i] == '.')
{
fileName_NoExtension = fileName.substr(0, i);
break;
}
}
return fileName_NoExtension;
}
string GetExtension(const string &path)
{
string fileName;
for (int i = path.size() - 1; i >= 0; --i)
{
if (path[i] == '.')
{
fileName = path.substr(i, path.size() - i);
break;
}
}
return fileName;
}
string GetParentPath(const string &path)
{
string fileName;
for (int i = path.size() - 1; i >= 0; --i)
{
if (IsPathSeparator(path[i]))
{
fileName = path.substr(0, i + 1);
break;
}
}
return fileName;
}
static bool CreateDirectory(const string &path)
{
#if defined WIN32 || defined _WIN32 || defined WINCE
#ifdef WINRT
wchar_t wpath[MAX_PATH];
size_t copied = mbstowcs(wpath, path.c_str(), MAX_PATH);
CV_Assert((copied != MAX_PATH) && (copied != (size_t)-1));
int result = CreateDirectoryA(wpath, NULL) ? 0 : -1;
#else
int result = _mkdir(path.c_str());
#endif
#elif defined __linux__ || defined __APPLE__
int result = mkdir(path.c_str(), 0777);
#else
int result = -1;
#endif
if (result == -1)
{
return IsDirectory(path);
}
return true;
}
bool CreateDirectories(const string &directoryPath)
{
string path = directoryPath;
for (;;)
{
char last_char = path.empty() ? 0 : path[path.length() - 1];
if (IsPathSeparator(last_char))
{
path = path.substr(0, path.length() - 1);
continue;
}
break;
}
if (path.empty() || path == "./" || path == ".\\" || path == ".")
return true;
if (IsDirectory(path))
return true;
size_t pos = path.rfind('/');
if (pos == string::npos)
pos = path.rfind('\\');
if (pos != string::npos)
{
string parent_directory = path.substr(0, pos);
if (!parent_directory.empty())
{
if (!CreateDirectories(parent_directory))
return false;
}
}
return CreateDirectory(path);
}
bool CopyFile(const string srcPath, const string dstPath)
{
std::ifstream srcFile(srcPath, ios::binary);
std::ofstream dstFile(dstPath, ios::binary);
if (!srcFile.is_open())
{
printf("can not open %s\n", srcPath.c_str());
return false;
}
if (!dstFile.is_open())
{
printf("can not open %s\n", dstPath.c_str());
return false;
}
if (srcPath == dstPath)
{
printf("src can not be same with dst\n");
return false;
}
char buffer[2048];
unsigned int numberOfBytes = 0;
while (srcFile)
{
srcFile.read(buffer, 2048);
dstFile.write(buffer, srcFile.gcount());
numberOfBytes += srcFile.gcount();
}
srcFile.close();
dstFile.close();
return true;
}
bool CopyDirectories(string srcPath, const string dstPath)
{
if (srcPath == dstPath)
{
printf("src can not be same with dst\n");
return false;
}
// ȥ������·���ָ���
srcPath = srcPath.substr(0, srcPath.size() - 1);
vector<string> fileNameList;
GetFileNameList2(srcPath, "", fileNameList, true, true);
string parentPathOfSrc = GetParentPath(srcPath);
int length = parentPathOfSrc.size();
// create all directories
for (int i = 0; i < fileNameList.size(); ++i)
{
// create directory
string srcFilePath = fileNameList[i];
string subStr = srcFilePath.substr(length, srcFilePath.size() - length);
string dstFilePath = dstPath + subStr;
string parentPathOfDst = GetParentPath(dstFilePath);
CreateDirectories(parentPathOfDst);
}
// copy file
for (int i = 0; i < fileNameList.size(); ++i)
{
string srcFilePath = fileNameList[i];
if (IsDirectory(srcFilePath))
{
continue;
}
string subStr = srcFilePath.substr(length, srcFilePath.size() - length);
string dstFilePath = dstPath + subStr;
// copy file
CopyFile(srcFilePath, dstFilePath);
// process
double process = (1.0 * (i + 1) / fileNameList.size()) * 100;
printf("%s done! %f% \n", GetFileName(fileNameList[i]).c_str(), process);
}
printf("all done!(the number of files:%d)\n", fileNameList.size());
return true;
}
}
// 文件以及目录处理
#ifndef __FILE_SYSTEM_H__
#define __FILE_SYSTEM_H__
#include <string>
#include <vector>
namespace migraphxSamples
{
// 路径是否存在
bool Exists(const std::string &path);
// 路径是否为目录
bool IsDirectory(const std::string &path);
// 是否是路径分隔符(Linux:‘/’,Windows:’\\’)
bool IsPathSeparator(char c);
// 路径拼接
std::string JoinPath(const std::string &base, const std::string &path);
// 创建多级目录,注意:创建多级目录的时候,目标目录是不能有文件存在的
bool CreateDirectories(const std::string &directoryPath);
/** 生成符合指定模式的文件名列表(支持递归遍历)
*
* pattern: 模式,比如"*.jpg","*.png","*.jpg,*.png"
* addPath:是否包含父路径
* 注意:
1. 多个模式使用","分割,比如"*.jpg,*.png"
2. 支持通配符'*','?' ,比如第一个字符是7的所有文件名:"7*.*", 以512结尾的所有jpg文件名:"*512.jpg"
3. 使用"*.jpg",而不是".jpg"
4. 空string表示返回所有结果
5. 不能返回子目录名
*
*/
void GetFileNameList(const std::string &directory, const std::string &pattern, std::vector<std::string> &result, bool recursive, bool addPath);
// 与GetFileNameList的区别在于如果有子目录,在addPath为true的时候会返回子目录路径(目录名最后有"/")
void GetFileNameList2(const std::string &directory, const std::string &pattern, std::vector<std::string> &result, bool recursive, bool addPath);
// 删除文件或者目录,支持递归删除
void Remove(const std::string &directory, const std::string &extension = "");
/** 获取路径的文件名和扩展名
*
* 示例:path为D:/1/1.txt,则GetFileName()为1.txt,GetFileName_NoExtension()为1,GetExtension()为.txt,GetParentPath()为D:/1/
*/
std::string GetFileName(const std::string &path);
std::string GetFileName_NoExtension(const std::string &path);
std::string GetExtension(const std::string &path);
std::string GetParentPath(const std::string &path);
// 拷贝文件
bool CopyFile(const std::string srcPath, const std::string dstPath);
/** 拷贝目录
*
* 示例:CopyDirectories("D:/0/1/2/","E:/3/");实现把D:/0/1/2/目录拷贝到E:/3/目录中(即拷贝完成后的目录结构为E:/3/2/)
* 注意:
1.第一个参数的最后不能加”/”
2.不能拷贝隐藏文件
*/
bool CopyDirectories(std::string srcPath, const std::string dstPath);
}
#endif
// 简易日志
#ifndef __SIMPLE_LOG_H__
#define __SIMPLE_LOG_H__
#include <time.h>
#include <string>
#include <map>
#include <thread>
#include <mutex>
#if (defined WIN32 || defined _WIN32)
#include <Windows.h>
#else
#include <sys/time.h>
#endif
using namespace std;
/** 简易日志
*
* 不依赖于其他第三方库,只需要包含一个头文件就可以使用。提供了4种日志级别,包括INFO,DEBUG,WARN和ERROR。
*
* 示例1:
// 初始化日志,在./Log/目录下创建两个日志文件log1.log和log2.log(注意:目录./Log/需要存在,否则日志创建失败)
LogManager::GetInstance()->Initialize("./Log/","log1");
LogManager::GetInstance()->Initialize("./Log/","log2");
// 写日志
string log = "Hello World";
LOG_INFO(LogManager::GetInstance()->GetLogFile("log1"), "%s\n", log.c_str()); // 写入log1.log
LOG_INFO(LogManager::GetInstance()->GetLogFile("log2"), "%s\n", log.c_str()); // 写入log2.log
// 关闭日志
LogManager::GetInstance()->Close("log1");
LogManager::GetInstance()->Close("log2");
* 示例2:
// 将日志输出到控制台
string log = "Hello World";
LOG_INFO(stdout, "%s\n", log.c_str());
* 注意:
1. 需要C++11
2. 多线程的时候需要加锁(打开#define LOG_MUTEX),否则会导致日志显示混乱
*/
// #define LOG_MUTEX // 加锁
class LogManager
{
private:
LogManager() {}
public:
~LogManager() {}
inline void Initialize(const string &parentPath, const string &logName)
{
// 日志名为空表示输出到控制台
if (logName.size() == 0)
return;
// 查找该日志文件,如果没有则创建
std::map<string, FILE *>::const_iterator iter = logMap.find(logName);
if (iter == logMap.end())
{
string pathOfLog = parentPath + logName + ".log";
FILE *logFile = fopen(pathOfLog.c_str(), "a"); // w:覆盖原有文件,a:追加
if (logFile != NULL)
{
logMap.insert(std::make_pair(logName, logFile));
}
}
}
inline FILE *GetLogFile(const string &logName)
{
std::map<string, FILE *>::const_iterator iter = logMap.find(logName);
if (iter == logMap.end())
{
return NULL;
}
return (*iter).second;
}
inline void Close(const string &logName)
{
std::map<string, FILE *>::const_iterator iter = logMap.find(logName);
if (iter == logMap.end())
{
return;
}
fclose((*iter).second);
logMap.erase(iter);
}
inline std::mutex &GetLogMutex()
{
return logMutex;
}
// Singleton
static LogManager *GetInstance()
{
static LogManager logManager;
return &logManager;
}
private:
std::map<string, FILE *> logMap;
std::mutex logMutex;
};
#ifdef LOG_MUTEX
#define LOCK LogManager::GetInstance()->GetLogMutex().lock()
#define UNLOCK LogManager::GetInstance()->GetLogMutex().unlock()
#else
#define LOCK
#define UNLOCK
#endif
// log time
typedef struct _LogTime
{
string year;
string month;
string day;
string hour;
string minute;
string second;
string millisecond; // ms
string microsecond; // us
string weekDay;
} LogTime;
inline LogTime GetTime()
{
LogTime currentTime;
#if (defined WIN32 || defined _WIN32)
SYSTEMTIME systemTime;
GetLocalTime(&systemTime);
char temp[8] = {0};
sprintf(temp, "%04d", systemTime.wYear);
currentTime.year = string(temp);
sprintf(temp, "%02d", systemTime.wMonth);
currentTime.month = string(temp);
sprintf(temp, "%02d", systemTime.wDay);
currentTime.day = string(temp);
sprintf(temp, "%02d", systemTime.wHour);
currentTime.hour = string(temp);
sprintf(temp, "%02d", systemTime.wMinute);
currentTime.minute = string(temp);
sprintf(temp, "%02d", systemTime.wSecond);
currentTime.second = string(temp);
sprintf(temp, "%03d", systemTime.wMilliseconds);
currentTime.millisecond = string(temp);
sprintf(temp, "%d", systemTime.wDayOfWeek);
currentTime.weekDay = string(temp);
#else
struct timeval tv;
struct tm *p;
gettimeofday(&tv, NULL);
p = localtime(&tv.tv_sec);
char temp[8] = {0};
sprintf(temp, "%04d", 1900 + p->tm_year);
currentTime.year = string(temp);
sprintf(temp, "%02d", 1 + p->tm_mon);
currentTime.month = string(temp);
sprintf(temp, "%02d", p->tm_mday);
currentTime.day = string(temp);
sprintf(temp, "%02d", p->tm_hour);
currentTime.hour = string(temp);
sprintf(temp, "%02d", p->tm_min);
currentTime.minute = string(temp);
sprintf(temp, "%02d", p->tm_sec);
currentTime.second = string(temp);
sprintf(temp, "%03d", (int)(tv.tv_usec / 1000));
currentTime.millisecond = string(temp);
sprintf(temp, "%03d", (int)(tv.tv_usec % 1000));
currentTime.microsecond = string(temp);
sprintf(temp, "%d", p->tm_wday);
currentTime.weekDay = string(temp);
#endif
return currentTime;
}
#define LOG_TIME(logFile) \
do \
{ \
LogTime currentTime = GetTime(); \
fprintf(((logFile == NULL) ? stdout : logFile), "%s-%s-%s %s:%s:%s.%s\t", currentTime.year.c_str(), currentTime.month.c_str(), currentTime.day.c_str(), currentTime.hour.c_str(), currentTime.minute.c_str(), currentTime.second.c_str(), currentTime.millisecond.c_str()); \
} while (0)
#define LOG_INFO(logFile, logInfo, ...) \
do \
{ \
LOCK; \
LOG_TIME(logFile); \
fprintf(((logFile == NULL) ? stdout : logFile), "INFO\t"); \
fprintf(((logFile == NULL) ? stdout : logFile), "[%s:%d (%s) ]: ", __FILE__, __LINE__, __FUNCTION__); \
fprintf(((logFile == NULL) ? stdout : logFile), logInfo, ##__VA_ARGS__); \
fflush(logFile); \
UNLOCK; \
} while (0)
#define LOG_DEBUG(logFile, logInfo, ...) \
do \
{ \
LOCK; \
LOG_TIME(logFile); \
fprintf(((logFile == NULL) ? stdout : logFile), "DEBUG\t"); \
fprintf(((logFile == NULL) ? stdout : logFile), "[%s:%d (%s) ]: ", __FILE__, __LINE__, __FUNCTION__); \
fprintf(((logFile == NULL) ? stdout : logFile), logInfo, ##__VA_ARGS__); \
fflush(logFile); \
UNLOCK; \
} while (0)
#define LOG_ERROR(logFile, logInfo, ...) \
do \
{ \
LOCK; \
LOG_TIME(logFile); \
fprintf(((logFile == NULL) ? stdout : logFile), "ERROR\t"); \
fprintf(((logFile == NULL) ? stdout : logFile), "[%s:%d (%s) ]: ", __FILE__, __LINE__, __FUNCTION__); \
fprintf(((logFile == NULL) ? stdout : logFile), logInfo, ##__VA_ARGS__); \
fflush(logFile); \
UNLOCK; \
} while (0)
#define LOG_WARN(logFile, logInfo, ...) \
do \
{ \
LOCK; \
LOG_TIME(logFile); \
fprintf(((logFile == NULL) ? stdout : logFile), "WARN\t"); \
fprintf(((logFile == NULL) ? stdout : logFile), "[%s:%d (%s) ]: ", __FILE__, __LINE__, __FUNCTION__); \
fprintf(((logFile == NULL) ? stdout : logFile), logInfo, ##__VA_ARGS__); \
fflush(logFile); \
UNLOCK; \
} while (0)
#endif // __SIMPLE_LOG_H__
#include <YOLOV9.h>
#include <migraphx/onnx.hpp>
#include <migraphx/gpu/target.hpp>
#include <migraphx/quantization.hpp>
#include <Filesystem.h>
#include <SimpleLog.h>
namespace migraphxSamples
{
DetectorYOLOV9::DetectorYOLOV9()
{
}
DetectorYOLOV9::~DetectorYOLOV9()
{
configurationFile.release();
}
ErrorCode DetectorYOLOV9::Initialize(InitializationParameterOfDetector initializationParameterOfDetector, bool dynamic)
{
// 读取配置文件
std::string configFilePath = initializationParameterOfDetector.configFilePath;
if (Exists(configFilePath) == false)
{
LOG_ERROR(stdout, "no configuration file!\n");
return CONFIG_FILE_NOT_EXIST;
}
if (!configurationFile.open(configFilePath, cv::FileStorage::READ))
{
LOG_ERROR(stdout, "fail to open configuration file\n");
return FAIL_TO_OPEN_CONFIG_FILE;
}
LOG_INFO(stdout, "succeed to open configuration file\n");
// 获取配置文件参数
cv::FileNode netNode = configurationFile["DetectorYOLOV9"];
if (dynamic)
{
modelPath = (std::string)netNode["ModelPathDynamic"];
}
else
{
modelPath = (std::string)netNode["ModelPathStatic"];
}
std::string pathOfClassNameFile = (std::string)netNode["ClassNameFile"];
yolov9Parameter.confidenceThreshold = (float)netNode["ConfidenceThreshold"];
yolov9Parameter.nmsThreshold = (float)netNode["NMSThreshold"];
yolov9Parameter.numberOfClasses = (int)netNode["NumberOfClasses"];
useFP16 = (bool)(int)netNode["UseFP16"];
if (dynamic)
{
// 加载模型
if (Exists(modelPath) == false)
{
LOG_ERROR(stdout, "%s not exist!\n", modelPath.c_str());
return MODEL_NOT_EXIST;
}
migraphx::onnx_options onnx_options;
onnx_options.map_input_dims["images"] = {1, 3, 1024, 1024};
net = migraphx::parse_onnx(modelPath, onnx_options);
LOG_INFO(stdout, "succeed to load model: %s\n", GetFileName(modelPath).c_str());
// 获取模型输入/输出节点信息
std::cout << "inputs:" << std::endl;
std::unordered_map<std::string, migraphx::shape> inputs = net.get_inputs();
for (auto i : inputs)
{
std::cout << i.first << ":" << i.second << std::endl;
}
std::cout << "outputs:" << std::endl;
std::unordered_map<std::string, migraphx::shape> outputs = net.get_outputs();
for (auto i : outputs)
{
std::cout << i.first << ":" << i.second << std::endl;
}
inputName = inputs.begin()->first;
inputShape = inputs.begin()->second;
int N = inputShape.lens()[0];
int C = inputShape.lens()[1];
int H = inputShape.lens()[2];
int W = inputShape.lens()[3];
inputSize = cv::Size(W, H);
// log
LOG_INFO(stdout, "InputMaxSize:%dx%d\n", inputSize.width, inputSize.height);
}
else
{
// 加载模型
if (Exists(modelPath) == false)
{
LOG_ERROR(stdout, "%s not exist!\n", modelPath.c_str());
return MODEL_NOT_EXIST;
}
net = migraphx::parse_onnx(modelPath);
LOG_INFO(stdout, "succeed to load model: %s\n", GetFileName(modelPath).c_str());
// 获取模型输入/输出节点信息
std::cout << "inputs:" << std::endl;
std::unordered_map<std::string, migraphx::shape> inputs = net.get_inputs();
for (auto i : inputs)
{
std::cout << i.first << ":" << i.second << std::endl;
}
std::cout << "outputs:" << std::endl;
std::unordered_map<std::string, migraphx::shape> outputs = net.get_outputs();
for (auto i : outputs)
{
std::cout << i.first << ":" << i.second << std::endl;
}
inputName = inputs.begin()->first;
inputShape = inputs.begin()->second;
int N = inputShape.lens()[0];
int C = inputShape.lens()[1];
int H = inputShape.lens()[2];
int W = inputShape.lens()[3];
inputSize = cv::Size(W, H);
// log
LOG_INFO(stdout, "InputSize:%dx%d\n", inputSize.width, inputSize.height);
}
LOG_INFO(stdout, "InputName:%s\n", inputName.c_str());
LOG_INFO(stdout, "ConfidenceThreshold:%f\n", yolov9Parameter.confidenceThreshold);
LOG_INFO(stdout, "NMSThreshold:%f\n", yolov9Parameter.nmsThreshold);
LOG_INFO(stdout, "NumberOfClasses:%d\n", yolov9Parameter.numberOfClasses);
// 设置模型为GPU模式
migraphx::target gpuTarget = migraphx::gpu::target{};
// 量化
if (useFP16)
{
migraphx::quantize_fp16(net);
}
// 编译模型
migraphx::compile_options options;
options.device_id = 0;
options.offload_copy = true;
net.compile(gpuTarget, options);
LOG_INFO(stdout, "succeed to compile model: %s\n", GetFileName(modelPath).c_str());
// warm up
std::unordered_map<std::string, migraphx::argument> inputData;
inputData[inputName] = migraphx::argument{inputShape};
net.eval(inputData);
// 读取类别名
if (!pathOfClassNameFile.empty())
{
std::ifstream classNameFile(pathOfClassNameFile);
std::string line;
while (getline(classNameFile, line))
{
classNames.push_back(line);
}
}
else
{
classNames.resize(yolov9Parameter.numberOfClasses);
}
return SUCCESS;
}
ErrorCode DetectorYOLOV9::Detect(const cv::Mat &srcImage, std::vector<std::size_t> &relInputShape, std::vector<ResultOfDetection> &resultsOfDetection, bool dynamic)
{
if (srcImage.empty() || srcImage.type() != CV_8UC3)
{
LOG_ERROR(stdout, "image error!\n");
return IMAGE_ERROR;
}
// 数据预处理并转换为NCHW格式
inputSize = cv::Size(relInputShape[3], relInputShape[2]);
cv::Mat inputBlob;
cv::dnn::blobFromImage(srcImage,
inputBlob,
1 / 255.0,
inputSize,
cv::Scalar(0, 0, 0),
true,
false);
// 创建输入数据
migraphx::parameter_map inputData;
if (dynamic)
{
inputData[inputName] = migraphx::argument{migraphx::shape(inputShape.type(), relInputShape), (float *)inputBlob.data};
}
else
{
inputData[inputName] = migraphx::argument{inputShape, (float *)inputBlob.data};
}
// 推理
std::vector<migraphx::argument> inferenceResults = net.eval(inputData);
// 获取推理结果
std::vector<cv::Mat> outs;
migraphx::argument result = inferenceResults[0];
// 转换为cv::Mat
migraphx::shape outputShape = result.get_shape();
int shape[] = {outputShape.lens()[0], outputShape.lens()[1], outputShape.lens()[2]};
cv::Mat out(3, shape, CV_32F);
memcpy(out.data, result.data(), sizeof(float) * outputShape.elements());
outs.push_back(out);
// 获取先验框的个数
// yolov5 has an output of shape (batchSize, 25200, 85) (Num classes + box[x,y,w,h] + confidence[c])
// yolov9 has an output of shape (batchSize, 84, 8400) (Num classes + box[x,y,w,h])
int numProposal = outs[0].size[2];
int numOut = outs[0].size[1];
// 变换输出的维度
outs[0] = outs[0].reshape(1, numOut);
cv::transpose(outs[0], outs[0]);
float *data = (float *)outs[0].data;
// 生成先验框
std::vector<float> confidences;
std::vector<cv::Rect> boxes;
std::vector<int> classIds;
float ratioh = (float)srcImage.rows / inputSize.height, ratiow = (float)srcImage.cols / inputSize.width;
// 计算x,y,w,h
for (int n = 0; n < numProposal; n++)
{
float *classes_scores = data + 4;
cv::Mat scores(1, classNames.size(), CV_32FC1, classes_scores);
cv::Point class_id;
double maxClassScore;
cv::minMaxLoc(scores, 0, &maxClassScore, 0, &class_id);
if (maxClassScore > yolov9Parameter.confidenceThreshold)
{
confidences.push_back(maxClassScore);
classIds.push_back(class_id.x);
float x = data[0];
float y = data[1];
float w = data[2];
float h = data[3];
int left = int((x - 0.5 * w) * ratiow);
int top = int((y - 0.5 * h) * ratioh);
int width = int(w * ratiow);
int height = int(h * ratioh);
boxes.push_back(cv::Rect(left, top, width, height));
}
data += numOut;
}
// 执行non maximum suppression消除冗余重叠boxes
std::vector<int> indices;
cv::dnn::NMSBoxes(boxes, confidences, yolov9Parameter.confidenceThreshold, yolov9Parameter.nmsThreshold, indices);
for (size_t i = 0; i < indices.size(); ++i)
{
int idx = indices[i];
int classID = classIds[idx];
string className = classNames[classID];
float confidence = confidences[idx];
cv::Rect box = boxes[idx];
ResultOfDetection result;
result.boundingBox = box;
result.confidence = confidence; // confidence
result.classID = classID; // label
result.className = className;
resultsOfDetection.push_back(result);
}
return SUCCESS;
}
}
#ifndef __DETECTOR_YOLOV9_H__
#define __DETECTOR_YOLOV9_H__
#include <migraphx/program.hpp>
#include <CommonDefinition.h>
namespace migraphxSamples
{
typedef struct _YOLOV9Parameter
{
int numberOfClasses;
float confidenceThreshold;
float nmsThreshold;
} YOLOV9Parameter;
class DetectorYOLOV9
{
public:
DetectorYOLOV9();
~DetectorYOLOV9();
ErrorCode Initialize(InitializationParameterOfDetector initializationParameterOfDetector, bool dynamic);
ErrorCode Detect(const cv::Mat &srcImage, std::vector<std::size_t> &relInputShape, std::vector<ResultOfDetection> &resultsOfDetection, bool dynamic);
private:
cv::FileStorage configurationFile;
migraphx::program net;
cv::Size inputSize;
std::string inputName;
std::string modelPath;
migraphx::shape inputShape;
bool useFP16;
std::vector<std::string> classNames;
YOLOV9Parameter yolov9Parameter;
};
}
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SimpleLog.h>
#include <Filesystem.h>
#include <YOLOV9.h>
void MIGraphXSamplesUsage(char *programName)
{
printf("Usage : %s <index> \n", programName);
printf("index:\n");
printf("\t 0) YOLOV9 sample.\n");
printf("\t 1) YOLOV9 Dynamic sample.\n");
}
void Sample_YOLOV9();
void Sample_YOLOV9_Dynamic();
int main(int argc, char *argv[])
{
if (argc < 2 || argc > 2)
{
MIGraphXSamplesUsage(argv[0]);
return -1;
}
if (!strncmp(argv[1], "-h", 2))
{
MIGraphXSamplesUsage(argv[0]);
return 0;
}
switch (*argv[1])
{
case '0':
{
Sample_YOLOV9();
break;
}
case '1':
{
Sample_YOLOV9_Dynamic();
break;
}
default:
{
MIGraphXSamplesUsage(argv[0]);
break;
}
}
return 0;
}
void Sample_YOLOV9()
{
// 创建YOLOV9检测器
migraphxSamples::DetectorYOLOV9 detector;
migraphxSamples::InitializationParameterOfDetector initParamOfDetectorYOLOV9;
initParamOfDetectorYOLOV9.configFilePath = CONFIG_FILE;
migraphxSamples::ErrorCode errorCode = detector.Initialize(initParamOfDetectorYOLOV9, false);
if (errorCode != migraphxSamples::SUCCESS)
{
LOG_ERROR(stdout, "fail to initialize detector!\n");
exit(-1);
}
LOG_INFO(stdout, "succeed to initialize detector\n");
// 读取测试图片
cv::Mat srcImage = cv::imread("../Resource/Images/image_test.jpg", 1);
// 静态推理固定尺寸
std::vector<std::size_t> inputShape = {1, 3, 640, 640};
// 推理
std::vector<migraphxSamples::ResultOfDetection> predictions;
double time1 = cv::getTickCount();
detector.Detect(srcImage, inputShape, predictions, false);
double time2 = cv::getTickCount();
double elapsedTime = (time2 - time1) * 1000 / cv::getTickFrequency();
LOG_INFO(stdout, "inference time:%f ms\n", elapsedTime);
// 获取推理结果
LOG_INFO(stdout, "========== Detection Results ==========\n");
for (int i = 0; i < predictions.size(); ++i)
{
migraphxSamples::ResultOfDetection result = predictions[i];
cv::rectangle(srcImage, result.boundingBox, cv::Scalar(0, 255, 255), 2);
std::string label = cv::format("%.2f", result.confidence);
label = result.className + " " + label;
int left = predictions[i].boundingBox.x;
int top = predictions[i].boundingBox.y;
int baseLine;
cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
top = max(top, labelSize.height);
cv::putText(srcImage, label, cv::Point(left, top - 10), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 255), 2);
LOG_INFO(stdout, "box:%d %d %d %d,label:%d,confidence:%f\n", predictions[i].boundingBox.x,
predictions[i].boundingBox.y, predictions[i].boundingBox.width, predictions[i].boundingBox.height, predictions[i].classID, predictions[i].confidence);
}
cv::imwrite("Result.jpg", srcImage);
LOG_INFO(stdout, "Detection results have been saved to ./Result.jpg\n");
}
void Sample_YOLOV9_Dynamic()
{
// 创建YOLOV9检测器
migraphxSamples::DetectorYOLOV9 detector;
migraphxSamples::InitializationParameterOfDetector initParamOfDetectorYOLOV9;
initParamOfDetectorYOLOV9.configFilePath = CONFIG_FILE;
migraphxSamples::ErrorCode errorCode = detector.Initialize(initParamOfDetectorYOLOV9, true);
if (errorCode != migraphxSamples::SUCCESS)
{
LOG_ERROR(stdout, "fail to initialize detector!\n");
exit(-1);
}
LOG_INFO(stdout, "succeed to initialize detector\n");
// 读取测试图像
std::vector<cv::Mat> srcImages;
cv::String folder = "../Resource/Images/DynamicPics";
std::vector<cv::String> imagePathList;
cv::glob(folder, imagePathList);
for (int i = 0; i < imagePathList.size(); ++i)
{
cv::Mat srcImage = cv::imread(imagePathList[i], 1);
srcImages.push_back(srcImage);
}
// 设置动态推理shape
std::vector<std::vector<std::size_t>> inputShapes;
inputShapes.push_back({1, 3, 416, 416});
inputShapes.push_back({1, 3, 608, 608});
for (int i = 0; i < srcImages.size(); ++i)
{
// 推理
std::vector<migraphxSamples::ResultOfDetection> predictions;
double time1 = cv::getTickCount();
detector.Detect(srcImages[i], inputShapes[i], predictions, true);
double time2 = cv::getTickCount();
double elapsedTime = (time2 - time1) * 1000 / cv::getTickFrequency();
LOG_INFO(stdout, "inference image%d time:%f ms\n", i, elapsedTime);
// 获取推理结果
LOG_INFO(stdout, "========== Detection Image%d Results ==========\n", i);
for (int j = 0; j < predictions.size(); ++j)
{
migraphxSamples::ResultOfDetection result = predictions[j];
cv::rectangle(srcImages[i], result.boundingBox, cv::Scalar(0, 255, 255), 2);
std::string label = cv::format("%.2f", result.confidence);
label = result.className + " " + label;
int left = predictions[j].boundingBox.x;
int top = predictions[j].boundingBox.y;
int baseLine;
cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
top = max(top, labelSize.height);
cv::putText(srcImages[i], label, cv::Point(left, top - 10), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 255), 2);
LOG_INFO(stdout, "box:%d %d %d %d,label:%d,confidence:%f\n", predictions[j].boundingBox.x,
predictions[j].boundingBox.y, predictions[j].boundingBox.width, predictions[j].boundingBox.height, predictions[j].classID, predictions[j].confidence);
}
std::string imgName = cv::format("Result%d.jpg", i);
cv::imwrite(imgName, srcImages[i]);
LOG_INFO(stdout, "Detection results have been saved to ./Result%d.jpg\n", i);
}
}
\ No newline at end of file
FROM image.sourcefind.cn:5000/dcu/admin/base/migraphx:4.0.0-centos7.6-dtk23.04.1-py38-latest
RUN source /opt/dtk/env.sh
#模型唯一标识符
modelCode=1546
#模型名称
modelName=yolov9_migraphx
#模型描述
modelDescription=YOLOv9引入了可编程梯度信息 (PGI) 和广义高效层聚合网络 (GELAN) 等开创性技术,标志着实时目标检测领域的重大进步。
#应用场景
appScenario=推理,目标检测,交通,教育,化工
#框架类型
frameType=migraphx
\ No newline at end of file
./3rdParty/opencv-3.4.11_mini.tar.gz
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment