Commit cdb77bf7 authored by liucong's avatar liucong
Browse files

精简代码

parent 76d4e7b9
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
# 设置项目名 # 设置项目名
project(MIGraphX_Samples) project(Unet)
# 设置编译器 # 设置编译器
set(CMAKE_CXX_COMPILER g++) set(CMAKE_CXX_COMPILER g++)
...@@ -12,7 +12,6 @@ set(CMAKE_BUILD_TYPE release) ...@@ -12,7 +12,6 @@ set(CMAKE_BUILD_TYPE release)
# 添加头文件路径 # 添加头文件路径
set(INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Src/ set(INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Src/
${CMAKE_CURRENT_SOURCE_DIR}/Src/Utility/ ${CMAKE_CURRENT_SOURCE_DIR}/Src/Utility/
${CMAKE_CURRENT_SOURCE_DIR}/Src/Segmentation/
$ENV{DTKROOT}/include/ $ENV{DTKROOT}/include/
${CMAKE_CURRENT_SOURCE_DIR}/depend/include/) ${CMAKE_CURRENT_SOURCE_DIR}/depend/include/)
include_directories(${INCLUDE_PATH}) include_directories(${INCLUDE_PATH})
...@@ -37,10 +36,9 @@ link_libraries(${LIBRARY}) ...@@ -37,10 +36,9 @@ link_libraries(${LIBRARY})
# 添加源文件 # 添加源文件
set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Src/main.cpp set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Src/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Src/Sample.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Src/Unet.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Src/Segmentation/Unet.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Src/Utility/CommonUtility.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Src/Utility/CommonUtility.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Src/Utility/Filesystem.cpp) ${CMAKE_CURRENT_SOURCE_DIR}/Src/Utility/Filesystem.cpp)
# 添加可执行目标 # 添加可执行目标
add_executable(MIGraphX_Samples ${SOURCE_FILES}) add_executable(Unet ${SOURCE_FILES})
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
## 模型简介 ## 模型简介
本示例采用了经典的Unet模型进行图像分割,模型下载地址:https://www.dropbox.com/s/3ntkhyk30x05uuv/unet_13_256.onnx, 将unet_13_256.onnx文件保存在Resource/Models/Segmentation文件夹下。模型结构如下图所示,可以通过netron工具, 链接:https://netron.app/, 查看具体的模型结构,该模型的输入shape为[batch_size,3,256,256],输出shape为[batch_size,1,256,256],数据排布为NCHW。 本示例采用了经典的Unet模型进行图像分割,模型下载地址:https://www.dropbox.com/s/3ntkhyk30x05uuv/unet_13_256.onnx, 将unet_13_256.onnx文件保存在Resource/Models文件夹下。模型结构如下图所示,可以通过netron工具, 链接:https://netron.app/, 查看具体的模型结构,该模型的输入shape为[batch_size,3,256,256],输出shape为[batch_size,1,256,256],数据排布为NCHW。
<img src="../Images/Unet_01.png" style="zoom:80%;" align=middle> <img src="./Images/Unet_01.png" style="zoom:80%;" align=middle>
## 模型初始化 ## 模型初始化
...@@ -24,10 +24,14 @@ ErrorCode Unet::Initialize(InitializationParameterOfSegmentation initParamOfSegm ...@@ -24,10 +24,14 @@ ErrorCode Unet::Initialize(InitializationParameterOfSegmentation initParamOfSegm
LOG_INFO(logFile,"succeed to load model: %s\n",GetFileName(modelPath).c_str()); LOG_INFO(logFile,"succeed to load model: %s\n",GetFileName(modelPath).c_str());
// 获取模型输入属性 // 获取模型输入属性
std::pair<std::string, migraphx::shape> inputAttribute=*(net.get_parameter_shapes().begin()); std::pair<std::string, migraphx::shape> inputAttribute=net.get_parameter_shapes();
inputName=inputAttribute.first; inputName=inputAttribute.first;
inputShape=inputAttribute.second; inputShape=inputAttribute.second;
inputSize=cv::Size(inputShape.lens()[3],inputShape.lens()[2]); 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);
// 设置模型为GPU模式 // 设置模型为GPU模式
migraphx::target gpuTarget = migraphx::gpu::target{}; migraphx::target gpuTarget = migraphx::gpu::target{};
...@@ -85,7 +89,7 @@ ErrorCode Unet::Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage) ...@@ -85,7 +89,7 @@ ErrorCode Unet::Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage)
{ {
... ...
// 输入数据 // 创建输入数据
migraphx::parameter_map inputData; migraphx::parameter_map inputData;
inputData[inputName]= migraphx::argument{inputShape, (float*)inputBlob.data}; inputData[inputName]= migraphx::argument{inputShape, (float*)inputBlob.data};
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
## 模型简介 ## 模型简介
本示例采用了经典的Unet模型进行图像分割,模型下载地址:https://www.dropbox.com/s/3ntkhyk30x05uuv/unet_13_256.onnx, 将unet_13_256.onnx文件保存在Resource/Models/Segmentation文件夹下。模型结构如下图所示, 链接:https://netron.app/, 该模型的输入shape为[batch_size,3,256,256],输出shape为[batch_size,1,256,256],数据排布为NCHW。 本示例采用了经典的Unet模型进行图像分割,模型下载地址:https://www.dropbox.com/s/3ntkhyk30x05uuv/unet_13_256.onnx, 将unet_13_256.onnx文件保存在Resource/Models文件夹下。模型结构如下图所示, 链接:https://netron.app/, 该模型的输入shape为[batch_size,3,256,256],输出shape为[batch_size,1,256,256],数据排布为NCHW。
<img src="../Images/Unet_01.png" style="zoom:80%;" align=middle> <img src="./Images/Unet_01.png" style="zoom:80%;" align=middle>
## 预处理 ## 预处理
...@@ -44,13 +44,13 @@ def Preprocessing(pil_img, newW, newH): ...@@ -44,13 +44,13 @@ def Preprocessing(pil_img, newW, newH):
```python ```python
# 加载模型 # 加载模型
model = migraphx.parse_onnx("../../Resource/Models/Segmentation/unet_13_256.onnx") model = migraphx.parse_onnx("../Resource/Models/Segmentation/unet_13_256.onnx")
# 编译模型 # 编译模型
model.compile(migraphx.get_target("gpu"), device_id=0) #device_id: 设置GPU设备,默认为0号设备 model.compile(migraphx.get_target("gpu"), device_id=0) #device_id: 设置GPU设备,默认为0号设备
# 图像预处理 # 图像预处理
img = cv2.imread("../../Resource/Images/car1.jpeg") img = cv2.imread("../Resource/Images/car1.jpeg")
input_img = Preprocessing(img, 256, 256) input_img = Preprocessing(img, 256, 256)
# 模型推理 # 模型推理
......
...@@ -25,7 +25,7 @@ def Sigmoid(x): ...@@ -25,7 +25,7 @@ def Sigmoid(x):
if __name__ == '__main__': if __name__ == '__main__':
# 加载模型 # 加载模型
model = migraphx.parse_onnx("../../Resource/Models/Segmentation/unet_13_256.onnx") model = migraphx.parse_onnx("../../Resource/Models/unet_13_256.onnx")
inputName = model.get_parameter_names() inputName = model.get_parameter_names()
inputShape = model.get_parameter_shapes() inputShape = model.get_parameter_shapes()
print("inputName:{0} \ninputShape:{1}".format(inputName, inputShape)) print("inputName:{0} \ninputShape:{1}".format(inputName, inputShape))
......
import numpy as np
import cv2
import migraphx
def Preprocessing(pil_img, newW, newH):
assert newW > 0 and newH > 0, 'Scale is too small'
img_nd = cv2.cvtColor(pil_img, cv2.COLOR_BGR2RGB) # BGR转换为RGB
img_nd = cv2.resize(img_nd, (newW, newH)) # 将图像尺寸修改为256x256
if len(img_nd.shape) == 2:
img_nd = np.expand_dims(img_nd, axis=2)
img_trans = img_nd.transpose((2, 0, 1)) # HWC转换为CHW
img_trans = np.expand_dims(img_trans, 0) # CHW扩展为NCHW
img_trans = np.ascontiguousarray(img_trans) # 保证内存连续存储
img_trans = img_trans.astype(np.float32) # 转换成浮点型数据
if img_trans.max() > 1:
img = img_trans / 255.0 # 保证数据处于0-1之间的浮点数
return img
def Sigmoid(x):
return 1 / (1 + np.exp(-x))
if __name__ == '__main__':
# 加载模型
model = migraphx.parse_onnx("../Resource/Models/unet_13_256.onnx")
inputName = model.get_parameter_names()
inputShape = model.get_parameter_shapes()
print("inputName:{0} \ninputShape:{1}".format(inputName, inputShape))
# 编译模型
model.compile(migraphx.get_target("gpu"), device_id=0) # device_id: 设置GPU设备,默认为0号设备
# 图像预处理
img = cv2.imread("../Resource/Images/car1.jpeg")
input_img = Preprocessing(img, 256, 256)
# 模型推理
mask = model.run({'inputs':input_img})
output_mask = np.array(mask[0])[0] # 获取推理结果,shape为(1,256,256)
probs = Sigmoid(output_mask) # 计算sigmoid值
# 0/1像素值,当大于0.996时,值为255,小于等于0.996时,值为0
output_mask[probs > 0.996] = 255
output_mask[probs <= 0.996] = 0
output = output_mask.astype(np.uint8)[0] # 将浮点型转换为uint8整型,shape为(256,256)
cv2.imwrite("output.jpg", output) # 保存图像分割结果
...@@ -6,7 +6,11 @@ ...@@ -6,7 +6,11 @@
## 模型结构 ## 模型结构
U-net模型整体为U型结构,主要分为三部分:下采样、上采样以及跳跃连接。首先,在左半部分进行编码阶段,通过卷积和下采样降低图像尺寸,提取一些浅层特征。其次,在右半部分进行解码阶段,通过卷积和上采样来获取一些深层次的特征。其中卷积采用无填充方式来保证结果都是基于没有缺失上下文特征得到的,因此每次经过卷积后,图像的大小会减小。最后,通过concat的方式,将编码阶段获得的feature map同解码阶段获得的feature map结合在一起,得到更加精细的细节,从而根据feature map进行预测分割。 U-net模型整体为U型结构,主要分为三部分:下采样、上采样以及跳跃连接。首先,在左半部分进行编码阶段,通过卷积和下采样降低图像尺寸,提取一些浅层特征。其次,在右半部分进行解码阶段,通过卷积和上采样来获取一些深层次的特征。其中卷积采用无填充方式来保证结果都是基于没有缺失上下文特征得到的,因此每次经过卷积后,图像的大小会减小。最后,通过concat的方式,将编码阶段获得的feature map同解码阶段获得的feature map结合在一起,得到更加精细的细节,从而根据feature map进行预测分割。
## 构建安装 ## Python版本推理
下面介绍如何运行python代码示例,具体推理代码解析,在Doc/Tutorial_Python.md中有详细说明。
### 构建安装
在光源可拉取推理的docker镜像,U-net模型推理的镜像如下: 在光源可拉取推理的docker镜像,U-net模型推理的镜像如下:
...@@ -14,6 +18,39 @@ U-net模型整体为U型结构,主要分为三部分:下采样、上采样 ...@@ -14,6 +18,39 @@ U-net模型整体为U型结构,主要分为三部分:下采样、上采样
docker pull image.sourcefind.cn:5000/dcu/admin/base/custom:ort1.14.0_migraphx3.0.0-dtk22.10.1 docker pull image.sourcefind.cn:5000/dcu/admin/base/custom:ort1.14.0_migraphx3.0.0-dtk22.10.1
``` ```
### 推理示例
1.参考《MIGraphX教程》设置好PYTHONPATH
2.安装依赖:
```Python
# 进入migraphx samples工程根目录
cd <path_to_migraphx_samples>
# 进入示例程序目录
cd ./Python/
# 安装依赖
pip install -r requirements.txt
```
3.在Python目录下执行如下命令运行该示例程序:
```python
python Unet.py
```
会在当前目录中生成分割图像
<img src="./Doc/Images/Unet_03.jpg" style="zoom:100%;" align=middle>
## C++版本推理
下面介绍如何运行C++代码示例,具体推理代码解析,在Doc/Tutorial_Cpp.md目录中有详细说明。
参考Python版本推理中的构建安装,在光源中拉取推理的docker镜像。
### 安装Opencv依赖 ### 安装Opencv依赖
```python ```python
...@@ -57,50 +94,19 @@ export LD_LIBRARY_PATH=<path_to_migraphx_samples>/depend/lib/:$LD_LIBRARY_PATH ...@@ -57,50 +94,19 @@ export LD_LIBRARY_PATH=<path_to_migraphx_samples>/depend/lib/:$LD_LIBRARY_PATH
source ~/.bashrc source ~/.bashrc
``` ```
## 推理 ### 推理示例
下面介绍如何运行python代码和C++代码示例,具体推理代码解析,在Doc目录中有详细说明。
### python版本推理 运行Unet示例程序,具体执行如下命令:
1.参考《MIGraphX教程》中的安装方法安装MIGraphX并设置好PYTHONPATH ```python
2.安装依赖:
```Python
# 进入migraphx samples工程根目录 # 进入migraphx samples工程根目录
cd <path_to_migraphx_samples> cd <path_to_migraphx_samples>
# 进入示例程序目录 # 进入build目录
cd Python/Segmentation
# 安装依赖
pip install -r requirements.txt
```
3.在Python/Segmentation目录下执行如下命令运行该示例程序:
```python
python Unet.py
```
会在当前目录中生成分割图像
<img src="./Doc/Images/Unet_03.jpg" style="zoom:100%;" align=middle>
### C++版本推理
切换到build目录中,执行如下命令:
```python
cd ./build/ cd ./build/
./MIGraphX_Samples
```
根据提示选择运行U-net模型的示例程序
```c++ # 执行示例程序
./MIGraphX_Samples 0 ./Unet
``` ```
会在当前目录中生成分割图像 会在当前目录中生成分割图像
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<!--Unet--> <!--Unet-->
<Unet> <Unet>
<ModelPath>"../Resource/Models/Segmentation/unet_13_256.onnx"</ModelPath> <ModelPath>"../Resource/Models/unet_13_256.onnx"</ModelPath>
</Unet> </Unet>
</opencv_storage> </opencv_storage>
#include <Sample.h>
#include <opencv2/dnn.hpp>
#include <SimpleLog.h>
#include <Filesystem.h>
#include <Unet.h>
using namespace std;
using namespace cv;
using namespace cv::dnn;
using namespace migraphx;
using namespace migraphxSamples;
void Sample_Unet()
{
// 加载Unet模型
Unet unet;
InitializationParameterOfSegmentation initParamOfSegmentationUnet;
initParamOfSegmentationUnet.parentPath = "";
initParamOfSegmentationUnet.configFilePath = CONFIG_FILE;
initParamOfSegmentationUnet.logName = "";
ErrorCode errorCode=unet.Initialize(initParamOfSegmentationUnet);
if(errorCode!=SUCCESS)
{
LOG_ERROR(stdout, "fail to initialize Unet!\n");
exit(-1);
}
LOG_INFO(stdout, "succeed to initialize Unet\n");
// 读取图像
cv::Mat srcImage =cv::imread("../Resource/Images/car1.jpeg", 1);
// 推理
cv::Mat maskImage;
double time1 = getTickCount();
unet.Segmentation(srcImage, maskImage);
double time2 = getTickCount();
double elapsedTime = (time2 - time1) * 1000 / getTickFrequency();
LOG_INFO(stdout, "inference time:%f ms\n", elapsedTime);
LOG_INFO(stdout,"========== Segmentation Results ==========\n");
LOG_INFO(stdout,"Segmentation results have been saved to ./Result.jpg\n");
cv::imwrite("./Result.jpg", maskImage);
}
\ No newline at end of file
// 示例程序
#ifndef __SAMPLE_H__
#define __SAMPLE_H__
// Unet sample
void Sample_Unet();
#endif
\ No newline at end of file
#include <Unet.h> #include <Unet.h>
#include <migraphx/onnx.hpp> #include <migraphx/onnx.hpp>
#include <migraphx/gpu/target.hpp> #include <migraphx/gpu/target.hpp>
#include <migraphx/gpu/hip.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/quantization.hpp>
#include <opencv2/dnn.hpp>
#include <CommonUtility.h>
#include <Filesystem.h> #include <Filesystem.h>
#include <SimpleLog.h> #include <SimpleLog.h>
...@@ -14,7 +11,12 @@ using namespace cv::dnn; ...@@ -14,7 +11,12 @@ using namespace cv::dnn;
namespace migraphxSamples namespace migraphxSamples
{ {
Unet::Unet():logFile(NULL) static float Sigmoid(float x)
{
return (1 / (1 + exp(-x)));
}
Unet::Unet()
{ {
} }
...@@ -26,33 +28,42 @@ Unet::~Unet() ...@@ -26,33 +28,42 @@ Unet::~Unet()
ErrorCode Unet::Initialize(InitializationParameterOfSegmentation initParamOfSegmentationUnet) ErrorCode Unet::Initialize(InitializationParameterOfSegmentation initParamOfSegmentationUnet)
{ {
// 初始化(获取日志文件,加载配置文件等) // 读取配置文件
ErrorCode errorCode=DoCommonInitialization(initParamOfSegmentationUnet); std::string configFilePath=initParamOfSegmentationUnet.configFilePath;
if(errorCode!=SUCCESS) if(Exists(configFilePath)==false)
{ {
LOG_ERROR(logFile,"fail to DoCommonInitialization\n"); LOG_ERROR(stdout, "no configuration file!\n");
return errorCode; return CONFIG_FILE_NOT_EXIST;
} }
LOG_INFO(logFile,"succeed to DoCommonInitialization\n"); 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");
// 获取配置文件参数 // 获取配置文件参数
FileNode netNode = configurationFile["Unet"]; cv::FileNode netNode = configurationFile["Unet"];
std::string modelPath=initializationParameter.parentPath+(std::string)netNode["ModelPath"]; std::string modelPath=(std::string)netNode["ModelPath"];
// 加载模型 // 加载模型
if(Exists(modelPath)==false) if(Exists(modelPath)==false)
{ {
LOG_ERROR(logFile,"%s not exist!\n",modelPath.c_str()); LOG_ERROR(stdout,"%s not exist!\n",modelPath.c_str());
return MODEL_NOT_EXIST; return MODEL_NOT_EXIST;
} }
net = migraphx::parse_onnx(modelPath); net = migraphx::parse_onnx(modelPath);
LOG_INFO(logFile,"succeed to load model: %s\n",GetFileName(modelPath).c_str()); LOG_INFO(stdout,"succeed to load model: %s\n",GetFileName(modelPath).c_str());
// 获取模型输入属性 // 获取模型输入属性
std::pair<std::string, migraphx::shape> inputAttribute=*(net.get_parameter_shapes().begin()); std::unordered_map<std::string, migraphx::shape> inputMap=net.get_parameter_shapes();
inputName=inputAttribute.first; inputName=inputMap.begin()->first;
inputShape=inputAttribute.second; inputShape=inputMap.begin()->second;
inputSize=cv::Size(inputShape.lens()[3],inputShape.lens()[2]); 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);
// 设置模型为GPU模式 // 设置模型为GPU模式
migraphx::target gpuTarget = migraphx::gpu::target{}; migraphx::target gpuTarget = migraphx::gpu::target{};
...@@ -60,53 +71,19 @@ ErrorCode Unet::Initialize(InitializationParameterOfSegmentation initParamOfSegm ...@@ -60,53 +71,19 @@ ErrorCode Unet::Initialize(InitializationParameterOfSegmentation initParamOfSegm
// 编译模型 // 编译模型
migraphx::compile_options options; migraphx::compile_options options;
options.device_id=0; // 设置GPU设备,默认为0号设备 options.device_id=0; // 设置GPU设备,默认为0号设备
options.offload_copy=true; // 设置offload_copy options.offload_copy=true;
net.compile(gpuTarget,options); net.compile(gpuTarget,options);
LOG_INFO(logFile,"succeed to compile model: %s\n",GetFileName(modelPath).c_str()); LOG_INFO(stdout,"succeed to compile model: %s\n",GetFileName(modelPath).c_str());
// Run once by itself // warm up
migraphx::parameter_map inputData; std::unordered_map<std::string, migraphx::argument> inputData;
inputData[inputName]=migraphx::generate_argument(inputShape); inputData[inputName]=migraphx::argument{inputShape};
net.eval(inputData); net.eval(inputData);
// log输出日志信息 // log输出日志信息
LOG_INFO(logFile,"InputSize:%dx%d\n",inputSize.width,inputSize.height); LOG_INFO(stdout,"InputSize:%dx%d\n",inputSize.width,inputSize.height);
LOG_INFO(logFile,"InputName:%s\n",inputName.c_str()); LOG_INFO(stdout,"InputName:%s\n",inputName.c_str());
return SUCCESS;
}
ErrorCode Unet::DoCommonInitialization(InitializationParameterOfSegmentation initParamOfSegmentationUnet)
{
initializationParameter = initParamOfSegmentationUnet;
// 获取日志文件
logFile=LogManager::GetInstance()->GetLogFile(initializationParameter.logName);
// 加载配置文件
std::string configFilePath=initializationParameter.configFilePath;
if(!Exists(configFilePath))
{
LOG_ERROR(logFile, "no configuration file!\n");
return CONFIG_FILE_NOT_EXIST;
}
if(!configurationFile.open(configFilePath, FileStorage::READ))
{
LOG_ERROR(logFile, "fail to open configuration file\n");
return FAIL_TO_OPEN_CONFIG_FILE;
}
LOG_INFO(logFile, "succeed to open configuration file\n");
// 修改父路径
std::string &parentPath = initializationParameter.parentPath;
if (!parentPath.empty())
{
if(!IsPathSeparator(parentPath[parentPath.size() - 1]))
{
parentPath+=PATH_SEPARATOR;
}
}
return SUCCESS; return SUCCESS;
} }
...@@ -114,22 +91,22 @@ ErrorCode Unet::Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage) ...@@ -114,22 +91,22 @@ ErrorCode Unet::Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage)
{ {
if(srcImage.empty()||srcImage.type()!=CV_8UC3) if(srcImage.empty()||srcImage.type()!=CV_8UC3)
{ {
LOG_ERROR(logFile, "image error!\n"); LOG_ERROR(stdout, "image error!\n");
return IMAGE_ERROR; return IMAGE_ERROR;
} }
// 图像预处理并转换为NCHW // 数据预处理并转换为NCHW格式
cv::Mat inputBlob; cv::Mat inputBlob;
cv::dnn::blobFromImage(srcImage, cv::dnn::blobFromImage(srcImage,
inputBlob, inputBlob,
1 / 255.0, 1 / 255.0,
inputSize, inputSize,
Scalar(0, 0, 0), cv::Scalar(0, 0, 0),
true, true,
false); false);
// 输入数据 // 创建输入数据
migraphx::parameter_map inputData; std::unordered_map<std::string, migraphx::argument> inputData;
inputData[inputName]= migraphx::argument{inputShape, (float*)inputBlob.data}; inputData[inputName]= migraphx::argument{inputShape, (float*)inputBlob.data};
// 推理 // 推理
...@@ -142,7 +119,7 @@ ErrorCode Unet::Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage) ...@@ -142,7 +119,7 @@ ErrorCode Unet::Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage)
int numberOfOutput=outputShape.elements(); // 输出节点元素的个数 int numberOfOutput=outputShape.elements(); // 输出节点元素的个数
float *data = (float *)result.data(); // 输出节点数据指针 float *data = (float *)result.data(); // 输出节点数据指针
// 计算sigmoid值,并且当大于0.996时,值为1,当小于0.996时,值为0,存储在value_mask[]数组中 // 计算sigmoid值
int value_mask[numberOfOutput]; int value_mask[numberOfOutput];
for(int i=0; i<numberOfOutput; ++i) for(int i=0; i<numberOfOutput; ++i)
{ {
...@@ -158,12 +135,12 @@ ErrorCode Unet::Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage) ...@@ -158,12 +135,12 @@ ErrorCode Unet::Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage)
} }
// 将对应的value_mask[]数组中的值按行依次赋值到outputImage对应位置处 // 将对应的value_mask[]数组中的值按行依次赋值到outputImage对应位置处
cv::Mat outputImage = cv::Mat_<int>(Size(outputShape.lens()[3], outputShape.lens()[2]), CV_32S); cv::Mat outputImage = cv::Mat_<int>(cv::Size(outputShape.lens()[3], outputShape.lens()[2]), CV_32S);
for(int i=0;i<outputShape.lens()[2];++i) for(int i=0;i<outputShape.lens()[2];++i)
{ {
for(int j=0;j<outputShape.lens()[3];++j) for(int j=0;j<outputShape.lens()[3];++j)
{ {
outputImage.at<int>(i,j)=value_mask[256*i+j]; //其中,256代表了outputShape.lens()[3]的值 outputImage.at<int>(i,j)=value_mask[256*i+j];
} }
} }
outputImage.convertTo(maskImage, CV_8U, 255.0); outputImage.convertTo(maskImage, CV_8U, 255.0);
...@@ -172,9 +149,6 @@ ErrorCode Unet::Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage) ...@@ -172,9 +149,6 @@ ErrorCode Unet::Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage)
} }
float Unet::Sigmoid(float x)
{
return (1 / (1 + exp(-x)));
}
} }
#ifndef __UNET_H__ #ifndef __UNET_H__
#define __UNET_H__ #define __UNET_H__
#include <string>
#include <migraphx/program.hpp> #include <migraphx/program.hpp>
#include <opencv2/opencv.hpp>
#include <CommonDefinition.h>
using namespace std; #include <CommonDefinition.h>
using namespace cv;
using namespace migraphx;
namespace migraphxSamples namespace migraphxSamples
{ {
...@@ -25,14 +20,7 @@ public: ...@@ -25,14 +20,7 @@ public:
ErrorCode Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage); ErrorCode Segmentation(const cv::Mat &srcImage, cv::Mat &maskImage);
private: private:
ErrorCode DoCommonInitialization(InitializationParameterOfSegmentation initParamOfSegmentationUnet);
float Sigmoid(float x);
private:
FILE *logFile;
cv::FileStorage configurationFile; cv::FileStorage configurationFile;
InitializationParameterOfSegmentation initializationParameter;
migraphx::program net; migraphx::program net;
cv::Size inputSize; cv::Size inputSize;
......
// 常用数据类型和宏定义 // 常用定义
#ifndef __COMMON_DEFINITION_H__ #ifndef __COMMON_DEFINITION_H__
#define __COMMON_DEFINITION_H__ #define __COMMON_DEFINITION_H__
#include <string>
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
namespace migraphxSamples namespace migraphxSamples
{ {
...@@ -21,20 +17,7 @@ namespace migraphxSamples ...@@ -21,20 +17,7 @@ namespace migraphxSamples
#define CONFIG_FILE "../Resource/Configuration.xml" #define CONFIG_FILE "../Resource/Configuration.xml"
typedef struct __Time typedef enum _ErrorCode
{
string year;
string month;
string day;
string hour;
string minute;
string second;
string millisecond; // ms
string microsecond; // us
string weekDay;
}_Time;
typedef enum _ErrorCode
{ {
SUCCESS=0, // 0 SUCCESS=0, // 0
MODEL_NOT_EXIST, // 模型不存在 MODEL_NOT_EXIST, // 模型不存在
...@@ -44,7 +27,7 @@ typedef enum _ErrorCode ...@@ -44,7 +27,7 @@ typedef enum _ErrorCode
IMAGE_ERROR, // 图像错误 IMAGE_ERROR, // 图像错误
}ErrorCode; }ErrorCode;
typedef struct _ResultOfPrediction typedef struct _ResultOfPrediction
{ {
float confidence; float confidence;
int label; int label;
...@@ -52,24 +35,22 @@ typedef struct _ResultOfPrediction ...@@ -52,24 +35,22 @@ typedef struct _ResultOfPrediction
}ResultOfPrediction; }ResultOfPrediction;
typedef struct _ResultOfDetection typedef struct _ResultOfDetection
{ {
Rect boundingBox; cv::Rect boundingBox;
float confidence; float confidence;
int classID; int classID;
string className; std::string className;
bool exist; bool exist;
_ResultOfDetection():confidence(0.0f),classID(0),exist(true){} _ResultOfDetection():confidence(0.0f),classID(0),exist(true){}
}ResultOfDetection; }ResultOfDetection;
typedef struct _InitializationParameterOfSegmentation typedef struct _InitializationParameterOfSegmentation
{ {
std::string parentPath; std::string parentPath;
std::string configFilePath; std::string configFilePath;
cv::Size inputSize;
std::string logName;
}InitializationParameterOfSegmentation; }InitializationParameterOfSegmentation;
} }
......
#include <CommonUtility.h> #include <CommonUtility.h>
#include <assert.h>
#include <ctype.h>
#include <time.h>
#include <stdlib.h>
#include <algorithm>
#include <sstream>
#include <vector>
#ifdef _WIN32
#include <io.h>
#include <direct.h>
#include <Windows.h>
#else
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/time.h>
#endif
#include <SimpleLog.h>
namespace migraphxSamples namespace migraphxSamples
{ {
_Time GetCurrentTime3()
{
_Time 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",tv.tv_usec/1000);
currentTime.millisecond = string(temp);
sprintf(temp, "%03d", tv.tv_usec % 1000);
currentTime.microsecond = string(temp);
sprintf(temp, "%d", p->tm_wday);
currentTime.weekDay = string(temp);
#endif
return currentTime;
}
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;
}
bool CompareConfidence(const ResultOfDetection &L,const ResultOfDetection &R) bool CompareConfidence(const ResultOfDetection &L,const ResultOfDetection &R)
{ {
return L.confidence > R.confidence; return L.confidence > R.confidence;
...@@ -109,7 +13,7 @@ bool CompareArea(const ResultOfDetection &L,const ResultOfDetection &R) ...@@ -109,7 +13,7 @@ bool CompareArea(const ResultOfDetection &L,const ResultOfDetection &R)
return L.boundingBox.area() > R.boundingBox.area(); return L.boundingBox.area() > R.boundingBox.area();
} }
void NMS(vector<ResultOfDetection> &detections, float IOUThreshold) void NMS(std::vector<ResultOfDetection> &detections, float IOUThreshold)
{ {
// sort // sort
std::sort(detections.begin(), detections.end(), CompareConfidence); std::sort(detections.begin(), detections.end(), CompareConfidence);
......
...@@ -3,23 +3,16 @@ ...@@ -3,23 +3,16 @@
#ifndef __COMMON_UTILITY_H__ #ifndef __COMMON_UTILITY_H__
#define __COMMON_UTILITY_H__ #define __COMMON_UTILITY_H__
#include <mutex>
#include <string>
#include <vector>
#include <CommonDefinition.h> #include <CommonDefinition.h>
using namespace std;
namespace migraphxSamples namespace migraphxSamples
{ {
// 分割字符串
std::vector<std::string> SplitString(std::string str,std::string separator);
// 排序规则: 按照置信度或者按照面积排序 // 排序规则: 按照置信度或者按照面积排序
bool CompareConfidence(const ResultOfDetection &L,const ResultOfDetection &R); bool CompareConfidence(const ResultOfDetection &L,const ResultOfDetection &R);
bool CompareArea(const ResultOfDetection &L,const ResultOfDetection &R); bool CompareArea(const ResultOfDetection &L,const ResultOfDetection &R);
// 非极大抑制
void NMS(std::vector<ResultOfDetection> &detections, float IOUThreshold); void NMS(std::vector<ResultOfDetection> &detections, float IOUThreshold);
} }
......
...@@ -11,12 +11,7 @@ ...@@ -11,12 +11,7 @@
#include <unistd.h> #include <unistd.h>
#include <dirent.h> #include <dirent.h>
#endif #endif
#include <CommonUtility.h>
#include <opencv2/opencv.hpp>
#include <SimpleLog.h>
using namespace cv;
// 路径分隔符(Linux:‘/’,Windows:’\\’) // 路径分隔符(Linux:‘/’,Windows:’\\’)
#ifdef _WIN32 #ifdef _WIN32
#define PATH_SEPARATOR '\\' #define PATH_SEPARATOR '\\'
...@@ -24,9 +19,31 @@ using namespace cv; ...@@ -24,9 +19,31 @@ using namespace cv;
#define PATH_SEPARATOR '/' #define PATH_SEPARATOR '/'
#endif #endif
using namespace std;
namespace migraphxSamples 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 #if defined _WIN32 || defined WINCE
const char dir_separators[] = "/\\"; const char dir_separators[] = "/\\";
...@@ -293,7 +310,7 @@ namespace migraphxSamples ...@@ -293,7 +310,7 @@ namespace migraphxSamples
} }
else else
{ {
LOG_INFO(stdout, "could not open directory: %s", directory.c_str()); printf("could not open directory: %s", directory.c_str());
} }
} }
...@@ -390,7 +407,7 @@ namespace migraphxSamples ...@@ -390,7 +407,7 @@ namespace migraphxSamples
#endif #endif
if (!result) if (!result)
{ {
LOG_INFO(stdout, "can't remove directory: %s\n", path.c_str()); printf("can't remove directory: %s\n", path.c_str());
} }
} }
else else
...@@ -402,7 +419,7 @@ namespace migraphxSamples ...@@ -402,7 +419,7 @@ namespace migraphxSamples
#endif #endif
if (!result) if (!result)
{ {
LOG_INFO(stdout, "can't remove file: %s\n", path.c_str()); printf("can't remove file: %s\n", path.c_str());
} }
} }
} }
...@@ -438,7 +455,7 @@ namespace migraphxSamples ...@@ -438,7 +455,7 @@ namespace migraphxSamples
{ {
RemoveAll(path); RemoveAll(path);
++numberOfFiles; ++numberOfFiles;
LOG_INFO(stdout, "%s deleted! number of deleted files:%d\n", path.c_str(), numberOfFiles); printf("%s deleted! number of deleted files:%d\n", path.c_str(), numberOfFiles);
} }
} }
...@@ -452,7 +469,7 @@ namespace migraphxSamples ...@@ -452,7 +469,7 @@ namespace migraphxSamples
} }
else else
{ {
LOG_INFO(stdout, "could not open directory: %s", directory.c_str()); printf("could not open directory: %s", directory.c_str());
} }
// ����RemoveAllɾ��Ŀ¼ // ����RemoveAllɾ��Ŀ¼
...@@ -592,17 +609,17 @@ namespace migraphxSamples ...@@ -592,17 +609,17 @@ namespace migraphxSamples
if(!srcFile.is_open()) if(!srcFile.is_open())
{ {
LOG_ERROR(stdout,"can not open %s\n",srcPath.c_str()); printf("can not open %s\n",srcPath.c_str());
return false; return false;
} }
if(!dstFile.is_open()) if(!dstFile.is_open())
{ {
LOG_ERROR(stdout, "can not open %s\n", dstPath.c_str()); printf("can not open %s\n", dstPath.c_str());
return false; return false;
} }
if(srcPath==dstPath) if(srcPath==dstPath)
{ {
LOG_ERROR(stdout, "src can not be same with dst\n"); printf("src can not be same with dst\n");
return false; return false;
} }
char buffer[2048]; char buffer[2048];
...@@ -622,7 +639,7 @@ namespace migraphxSamples ...@@ -622,7 +639,7 @@ namespace migraphxSamples
{ {
if(srcPath==dstPath) if(srcPath==dstPath)
{ {
LOG_ERROR(stdout, "src can not be same with dst\n"); printf("src can not be same with dst\n");
return false; return false;
} }
...@@ -662,9 +679,9 @@ namespace migraphxSamples ...@@ -662,9 +679,9 @@ namespace migraphxSamples
// process // process
double process = (1.0*(i + 1) / fileNameList.size()) * 100; double process = (1.0*(i + 1) / fileNameList.size()) * 100;
LOG_INFO(stdout, "%s done! %f% \n", GetFileName(fileNameList[i]).c_str(), process); printf("%s done! %f% \n", GetFileName(fileNameList[i]).c_str(), process);
} }
LOG_INFO(stdout, "all done!(the number of files:%d)\n", fileNameList.size()); printf("all done!(the number of files:%d)\n", fileNameList.size());
return true; return true;
......
...@@ -3,10 +3,8 @@ ...@@ -3,10 +3,8 @@
#ifndef __FILE_SYSTEM_H__ #ifndef __FILE_SYSTEM_H__
#define __FILE_SYSTEM_H__ #define __FILE_SYSTEM_H__
#include <vector>
#include <string> #include <string>
#include <vector>
using namespace std;
namespace migraphxSamples namespace migraphxSamples
{ {
...@@ -21,7 +19,7 @@ bool IsDirectory(const std::string &path); ...@@ -21,7 +19,7 @@ bool IsDirectory(const std::string &path);
bool IsPathSeparator(char c); bool IsPathSeparator(char c);
// 路径拼接 // 路径拼接
string JoinPath(const std::string &base, const std::string &path); std::string JoinPath(const std::string &base, const std::string &path);
// 创建多级目录,注意:创建多级目录的时候,目标目录是不能有文件存在的 // 创建多级目录,注意:创建多级目录的时候,目标目录是不能有文件存在的
bool CreateDirectories(const std::string &directoryPath); bool CreateDirectories(const std::string &directoryPath);
...@@ -49,14 +47,13 @@ void Remove(const std::string &directory, const std::string &extension=""); ...@@ -49,14 +47,13 @@ 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/ * 示例:path为D:/1/1.txt,则GetFileName()为1.txt,GetFileName_NoExtension()为1,GetExtension()为.txt,GetParentPath()为D:/1/
*/ */
string GetFileName(const std::string &path); // 1.txt std::string GetFileName(const std::string &path);
string GetFileName_NoExtension(const std::string &path); // 1 std::string GetFileName_NoExtension(const std::string &path);
string GetExtension(const std::string &path);// .txt std::string GetExtension(const std::string &path);
string GetParentPath(const std::string &path);// D:/1/ std::string GetParentPath(const std::string &path);
// 拷贝文件:CopyFile("D:/1.txt","D:/2.txt");将1.txt拷贝为2.txt // 拷贝文件
bool CopyFile(const std::string srcPath,const std::string dstPath); bool CopyFile(const std::string srcPath,const std::string dstPath);
/** 拷贝目录 /** 拷贝目录
......
...@@ -19,7 +19,7 @@ using namespace std; ...@@ -19,7 +19,7 @@ using namespace std;
/** 简易日志 /** 简易日志
* *
* 轻量级日志系统,不依赖于其他第三方库,只需要包含一个头文件就可以使用。提供了4种日志级别,包括INFO,DEBUG,WARN和ERROR。 * 不依赖于其他第三方库,只需要包含一个头文件就可以使用。提供了4种日志级别,包括INFO,DEBUG,WARN和ERROR。
* *
* 示例1: * 示例1:
// 初始化日志,在./Log/目录下创建两个日志文件log1.log和log2.log(注意:目录./Log/需要存在,否则日志创建失败) // 初始化日志,在./Log/目录下创建两个日志文件log1.log和log2.log(注意:目录./Log/需要存在,否则日志创建失败)
......
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <Sample.h> #include <Unet.h>
#include <SimpleLog.h>
#include <Filesystem.h>
void MIGraphXSamplesUsage(char* programName) int main()
{ {
printf("Usage : %s <index> \n", programName); // 加载Unet模型
printf("index:\n"); migraphxSamples::Unet unet;
printf("\t 0) Unet sample.\n"); migraphxSamples::InitializationParameterOfSegmentation initParamOfSegmentationUnet;
} initParamOfSegmentationUnet.configFilePath = CONFIG_FILE;
migraphxSamples::ErrorCode errorCode=unet.Initialize(initParamOfSegmentationUnet);
int main(int argc, char *argv[]) if(errorCode!=migraphxSamples::SUCCESS)
{
if (argc < 2 || argc > 2)
{
MIGraphXSamplesUsage(argv[0]);
return -1;
}
if (!strncmp(argv[1], "-h", 2))
{ {
MIGraphXSamplesUsage(argv[0]); LOG_ERROR(stdout, "fail to initialize Unet!\n");
return 0; exit(-1);
}
switch (*argv[1])
{
case '0':
{
Sample_Unet();
break;
}
default :
{
MIGraphXSamplesUsage(argv[0]);
break;
}
} }
LOG_INFO(stdout, "succeed to initialize Unet\n");
// 读取图像
cv::Mat srcImage =cv::imread("../Resource/Images/car1.jpeg", 1);
// 推理
cv::Mat maskImage;
double time1 = cv::getTickCount();
unet.Segmentation(srcImage, maskImage);
double time2 = cv::getTickCount();
double elapsedTime = (time2 - time1) * 1000 / cv::getTickFrequency();
LOG_INFO(stdout, "inference time:%f ms\n", elapsedTime);
LOG_INFO(stdout,"========== Segmentation Results ==========\n");
LOG_INFO(stdout,"Segmentation results have been saved to ./Result.jpg\n");
cv::imwrite("./Result.jpg", maskImage);
return 0; return 0;
} }
\ No newline at end of file
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