Commit b51b1aac authored by shangxl's avatar shangxl
Browse files

增加offloadcopy、批量处理图片等功能

parent be0d1a01
...@@ -2,15 +2,13 @@ ...@@ -2,15 +2,13 @@
#include <migraphx/onnx.hpp> #include <migraphx/onnx.hpp>
#include <migraphx/gpu/target.hpp> #include <migraphx/gpu/target.hpp>
#include <migraphx/quantization.hpp>
#include <hip/hip_runtime_api.h>
#include <Filesystem.h> #include <Filesystem.h>
#include <SimpleLog.h> #include <SimpleLog.h>
#include <algorithm> #include <algorithm>
namespace migraphxSamples namespace migraphxSamples{
{
static float Sigmoid(float x) { return (1 / (1 + exp(-x))); }
static std::vector<float> softmax(vector<float> v){ static std::vector<float> softmax(vector<float> v){
...@@ -62,8 +60,8 @@ DeepLabV3::DeepLabV3() {} ...@@ -62,8 +60,8 @@ DeepLabV3::DeepLabV3() {}
DeepLabV3::~DeepLabV3() { configurationFile.release(); } DeepLabV3::~DeepLabV3() { configurationFile.release(); }
ErrorCode DeepLabV3::Initialize(InitializationParameterOfSegmentation initParamOfSegmentationUnet) ErrorCode DeepLabV3::Initialize(InitializationParameterOfSegmentation initParamOfSegmentationUnet){
{
// 读取配置文件 // 读取配置文件
std::string configFilePath = initParamOfSegmentationUnet.configFilePath; std::string configFilePath = initParamOfSegmentationUnet.configFilePath;
if(!Exists(configFilePath)) if(!Exists(configFilePath))
...@@ -81,10 +79,9 @@ ErrorCode DeepLabV3::Initialize(InitializationParameterOfSegmentation initParamO ...@@ -81,10 +79,9 @@ ErrorCode DeepLabV3::Initialize(InitializationParameterOfSegmentation initParamO
// 获取配置文件参数 // 获取配置文件参数
cv::FileNode netNode = configurationFile["DeepLabV3"]; cv::FileNode netNode = configurationFile["DeepLabV3"];
std::string modelPath = (std::string)netNode["ModelPath"]; std::string modelPath = (std::string)netNode["ModelPath"];
useInt8 = (bool)(int)netNode["UseInt8"];
// 设置最大输入shape useFP16 = (bool)(int)netNode["UseFP16"];
migraphx::onnx_options onnx_options; useOffloadCopy = (bool)(int)netNode["UseOffloadCopy"];
onnx_options.map_input_dims["inputs"] = {1, 3, 256, 256};
// 加载模型 // 加载模型
if(!Exists(modelPath)) if(!Exists(modelPath))
...@@ -92,7 +89,14 @@ ErrorCode DeepLabV3::Initialize(InitializationParameterOfSegmentation initParamO ...@@ -92,7 +89,14 @@ ErrorCode DeepLabV3::Initialize(InitializationParameterOfSegmentation initParamO
LOG_ERROR(stdout, "%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, onnx_options);
migraphx::onnx_options onnx_options;
if(initParamOfSegmentationUnet.loadMode){
onnx_options.map_input_dims["input"] = {1, 3, 513, 513};
}else{
onnx_options.map_input_dims["input"] = {3, 3, 513, 513};
}
net = migraphx::parse_onnx(modelPath,onnx_options);
LOG_INFO(stdout, "succeed to load model: %s\n", GetFileName(modelPath).c_str()); LOG_INFO(stdout, "succeed to load model: %s\n", GetFileName(modelPath).c_str());
// 获取模型输入/输出节点信息 // 获取模型输入/输出节点信息
...@@ -100,92 +104,205 @@ ErrorCode DeepLabV3::Initialize(InitializationParameterOfSegmentation initParamO ...@@ -100,92 +104,205 @@ ErrorCode DeepLabV3::Initialize(InitializationParameterOfSegmentation initParamO
std::unordered_map<std::string, migraphx::shape> outputs = net.get_outputs(); std::unordered_map<std::string, migraphx::shape> outputs = net.get_outputs();
inputName = inputs.begin()->first; inputName = inputs.begin()->first;
inputShape = inputs.begin()->second; inputShape = inputs.begin()->second;
outputName = outputs.begin()->first;
outputShape = outputs.begin()->second;
auto it = outputs.begin();
++it;
outputName2 = it->first;
outputShape2 = it->second;
int N = inputShape.lens()[0]; int N = inputShape.lens()[0];
int C = inputShape.lens()[1]; int C = inputShape.lens()[1];
int H = inputShape.lens()[2]; int H = inputShape.lens()[2];
int W = inputShape.lens()[3]; int W = inputShape.lens()[3];
inputSize = cv::Size(W, H); inputSize = cv::Size(W, H);
// 设置模型为GPU模式 // 设置模型为GPU模式
migraphx::target gpuTarget = migraphx::gpu::target{}; migraphx::target gpuTarget = migraphx::gpu::target{};
if(useInt8){
std::vector<cv::Mat> calibrateImages;
std::string folderPath = "../Resource/Images/calibrateImages/";
std::string calibrateImageExt = "*.jpg";
std::vector<cv::String> calibrateImagePaths;
cv::glob(folderPath + calibrateImageExt, calibrateImagePaths, false);
for(const auto& path : calibrateImagePaths){
calibrateImages.push_back(cv::imread(path, 1));
}
cv::Mat inputcalibrateBlob;
cv::dnn::blobFromImages(calibrateImages, inputcalibrateBlob, 1 / 255.0, inputSize, cv::Scalar(0, 0, 0), true, false);
std::unordered_map<std::string, migraphx::argument> inputData;
inputData[inputName] = migraphx::argument{inputShape, (float *)inputcalibrateBlob.data};
std::vector<std::unordered_map<std::string, migraphx::argument>> calibrationData = {inputData};
// INT8量化
migraphx::quantize_int8(net, gpuTarget, calibrationData);
}else{
migraphx::quantize_fp16(net);
}
// 编译模型 // 编译模型
migraphx::compile_options options; migraphx::compile_options options;
options.device_id = 0; // 设置GPU设备,默认为0号设备 options.device_id = 0; // 设置GPU设备,默认为0号设备
options.offload_copy = true; if(useOffloadCopy){
options.offload_copy = true;
}else{
options.offload_copy = false;
}
net.compile(gpuTarget, options); net.compile(gpuTarget, options);
LOG_INFO(stdout, "succeed to compile model: %s\n", GetFileName(modelPath).c_str()); LOG_INFO(stdout, "succeed to compile model: %s\n", GetFileName(modelPath).c_str());
if(!useOffloadCopy){
inputBufferDevice = nullptr;
hipMalloc(&inputBufferDevice, inputShape.bytes());
modalDataMap[inputName] = migraphx::argument{inputShape, inputBufferDevice};
outputBufferDevice = nullptr;
hipMalloc(&outputBufferDevice, outputShape.bytes());
outputBufferDevice2 = nullptr;
hipMalloc(&outputBufferDevice2, outputShape2.bytes());
modalDataMap[outputName] = migraphx::argument{outputShape, outputBufferDevice};
modalDataMap[outputName2] = migraphx::argument{outputShape2, outputBufferDevice2};
outputBufferHost = nullptr; // host内存
outputBufferHost = malloc(outputShape.bytes());
outputBufferHost2 = nullptr; // host内存
outputBufferHost2 = malloc(outputShape2.bytes());
}
// warm up // warm up
std::unordered_map<std::string, migraphx::argument> inputData; if(useOffloadCopy){
inputData[inputName] = migraphx::argument{inputShape}; std::unordered_map<std::string, migraphx::argument> inputData;
net.eval(inputData); inputData[inputName] = migraphx::argument{inputShape};
net.eval(inputData);
}else{
migraphx::argument inputData = migraphx::argument{inputShape}; //创建数据
hipMemcpy(inputBufferDevice, inputData.data(), inputShape.bytes(), hipMemcpyHostToDevice); //将数据复制到device上
net.eval(modalDataMap);
}
// log输出日志信息 // log输出日志信息
LOG_INFO(stdout, "InputSize:%dx%d\n", inputSize.width, inputSize.height); LOG_INFO(stdout, "InputSize:%dx%d\n", inputSize.width, inputSize.height);
LOG_INFO(stdout, "InputName:%s\n", inputName.c_str()); LOG_INFO(stdout, "InputName:%s\n", inputName.c_str());
LOG_INFO(stdout, "UseInt8:%d\n", (int)useInt8);
LOG_INFO(stdout, "UseFP16:%d\n", (int)useFP16);
LOG_INFO(stdout, "useOffloadCopy:%d\n", (int)useOffloadCopy);
return SUCCESS; return SUCCESS;
} }
ErrorCode DeepLabV3::Segmentation(const cv::Mat& srcImage, cv::Mat& maskImage) ErrorCode DeepLabV3::Segmentation(std::vector<cv::Mat> srcImages, std::vector<cv::Mat> & maskImages){
{
if(srcImage.empty() || srcImage.type() != CV_8UC3) if(srcImages.size()==0 || srcImages[0].empty() || srcImages[0].type() != CV_8UC3)
{ {
LOG_ERROR(stdout, "image error!\n"); LOG_ERROR(stdout, "image error!\n");
return IMAGE_ERROR; return IMAGE_ERROR;
} }
// 数据预处理并转换为NCHW格式 // 数据预处理并转换为NCHW格式
cv::Mat inputBlob; cv::Mat inputBatchBlob;
cv::dnn::blobFromImage( cv::dnn::blobFromImages(srcImages, inputBatchBlob, 1 / 255.0, inputSize, cv::Scalar(0, 0, 0), true, false);
srcImage, inputBlob, 1 / 255.0, inputSize, cv::Scalar(0, 0, 0), true, false);
// 创建输入数据 // 创建颜色映射表
std::unordered_map<std::string, migraphx::argument> inputData; std::vector<cv::Scalar> color_map = create_color_map();
inputData[inputName] = migraphx::argument{inputShape, (float*)inputBlob.data};
// 推理
std::vector<migraphx::argument> results = net.eval(inputData);
// 获取输出节点的属性
migraphx::argument result = results[0]; // 获取第一个输出节点的数据
migraphx::shape outputShape = result.get_shape(); // 输出节点的shape
std::vector<std::size_t> outputSize = outputShape.lens(); // 每一维大小,维度顺序为(N,C,H,W)
int numberOfOutput = outputShape.elements(); // 输出节点元素的个数
float* data = (float*)result.data(); // 输出节点数据指针
int N = outputShape.lens()[0]; if(useOffloadCopy){
int C = outputShape.lens()[1]; // 创建输入数据
int H = outputShape.lens()[2]; std::unordered_map<std::string, migraphx::argument> inputData;
int W = outputShape.lens()[3]; inputData[inputName] = migraphx::argument{inputShape, (float*)inputBatchBlob.data};
// 推理
std::vector<migraphx::argument> results = net.eval(inputData);
// 获取输出节点的属性
migraphx::argument result = results[0]; // 获取第一个输出节点的数据
migraphx::shape outputShape = result.get_shape(); // 输出节点的shape
std::vector<std::size_t> outputSize = outputShape.lens(); // 每一维大小,维度顺序为(N,C,H,W)
int numberOfOutput = outputShape.elements(); // 输出节点元素的个数
float* data = (float*)result.data(); // 输出节点数据指针
int N = outputShape.lens()[0];
int C = outputShape.lens()[1];
int H = outputShape.lens()[2];
int W = outputShape.lens()[3];
for(int m = 0;m < N;m++){
cv::Mat outputImage(cv::Size(W, H), CV_8UC3);
for(int i = 0;i < H; i++){
for(int j = 0;j < W;j++){
std::vector<float> channel_value;
for(int k = 0;k < C;k++){
channel_value.push_back(data[m*C*H*W+k*(H*W)+i*W+j]);
}
std::vector<float> probs = softmax(channel_value);
// 找到概率最高的类别索引
int max_index = std::max_element(probs.begin(),probs.end())-probs.begin();
cv::Scalar sc = color_map[max_index];
outputImage.at<cv::Vec3b>(i, j)[0]= sc.val[0];
outputImage.at<cv::Vec3b>(i, j)[1]= sc.val[1];
outputImage.at<cv::Vec3b>(i, j)[2]= sc.val[2];
}
}
maskImages.push_back(outputImage);
}
cv::Mat outputImage(cv::Size(W, H), CV_8UC3); }else{
// 创建颜色映射表
std::vector<cv::Scalar> color_map = create_color_map(); migraphx::argument inputData = migraphx::argument{inputShape, (float*)inputBatchBlob.data};
// 拷贝到device输入内存
for(int i = 0;i < H; i++){ hipMemcpy(inputBufferDevice, inputData.data(), inputShape.bytes(), hipMemcpyHostToDevice);
for(int j = 0;j < W;j++){ // 推理
std::vector<float> channel_value; std::vector<migraphx::argument> results = net.eval(modalDataMap);
for(int k = 0;k < C;k++){
channel_value.push_back(data[k*(H*W)+i*W+j]); // 获取输出节点的属性
migraphx::argument result = results[0]; // 获取第一个输出节点的数据
migraphx::shape outputShapes = result.get_shape(); // 输出节点的shape
std::vector<std::size_t> outputSize = outputShapes.lens(); // 每一维大小,维度顺序为(N,C,H,W)
int numberOfOutput = outputShapes.elements(); // 输出节点元素的个数
// 将device输出数据拷贝到分配好的host输出内存
hipMemcpy(outputBufferHost,outputBufferDevice, outputShapes.bytes(),hipMemcpyDeviceToHost); // 直接使用事先分配好的输出内存拷贝
int N = outputSize[0];
int C = outputSize[1];
int H = outputSize[2];
int W = outputSize[3];
// 获取输出节点的属性
migraphx::argument result2 = results[1]; // 获取第2个输出节点的数据
migraphx::shape outputShapes2 = result2.get_shape(); // 输出节点的shape
std::vector<std::size_t> outputSize2 = outputShapes2.lens(); // 每一维大小,维度顺序为(N,C,H,W)
// 将device输出数据拷贝到分配好的host输出内存
hipMemcpy(outputBufferHost2,outputBufferDevice2, outputShapes2.bytes(),hipMemcpyDeviceToHost); // 直接使用事先分配好的输出内存拷贝
for(int m = 0;m < N;m++){
cv::Mat outputImage(cv::Size(W, H), CV_8UC3);
for(int i = 0;i < H; i++){
for(int j = 0;j < W;j++){
std::vector<float> channel_value;
for(int k = 0;k < C;k++){
channel_value.push_back(((float *)outputBufferDevice2)[m*C*H*W+k*(H*W)+i*W+j]);
}
std::vector<float> probs = softmax(channel_value);
// 找到概率最高的类别索引
int max_index = std::max_element(probs.begin(),probs.end())-probs.begin();
cv::Scalar sc = color_map[max_index];
outputImage.at<cv::Vec3b>(i, j)[0]= sc.val[0];
outputImage.at<cv::Vec3b>(i, j)[1]= sc.val[1];
outputImage.at<cv::Vec3b>(i, j)[2]= sc.val[2];
}
} }
std::vector<float> probs = softmax(channel_value); maskImages.push_back(outputImage);
// 找到概率最高的类别索引
int max_index = std::max_element(probs.begin(),probs.end())-probs.begin();
cv::Scalar sc = color_map[max_index];
outputImage.at<cv::Vec3b>(i, j)[0]= sc.val[0];
outputImage.at<cv::Vec3b>(i, j)[1]= sc.val[1];
outputImage.at<cv::Vec3b>(i, j)[2]= sc.val[2];
} }
} // 释放
hipFree(inputBufferDevice);
hipFree(outputBufferDevice);
hipFree(outputBufferDevice2);
free(outputBufferHost);
free(outputBufferHost2);
}
maskImage = outputImage.clone();
return SUCCESS; return SUCCESS;
} }
......
...@@ -6,8 +6,7 @@ ...@@ -6,8 +6,7 @@
namespace migraphxSamples namespace migraphxSamples{
{
class DeepLabV3{ class DeepLabV3{
public: public:
...@@ -17,7 +16,7 @@ namespace migraphxSamples ...@@ -17,7 +16,7 @@ namespace migraphxSamples
ErrorCode Initialize(InitializationParameterOfSegmentation initParamOfSegmentationUnet); ErrorCode Initialize(InitializationParameterOfSegmentation initParamOfSegmentationUnet);
ErrorCode Segmentation(const cv::Mat& srcImage, cv::Mat& maskImage); ErrorCode Segmentation(std::vector<cv::Mat> srcImages, std::vector<cv::Mat> & maskImages);
private: private:
cv::FileStorage configurationFile; cv::FileStorage configurationFile;
...@@ -26,7 +25,22 @@ namespace migraphxSamples ...@@ -26,7 +25,22 @@ namespace migraphxSamples
cv::Size inputSize; cv::Size inputSize;
std::string inputName; std::string inputName;
migraphx::shape inputShape; migraphx::shape inputShape;
float scale; std::string outputName;
migraphx::shape outputShape;
std::string outputName2;
migraphx::shape outputShape2;
std::unordered_map<std::string, migraphx::argument> modalDataMap;
void* inputBufferDevice;
void* outputBufferDevice;
void* outputBufferDevice2;
void* outputBufferHost;
void* outputBufferHost2;
bool useInt8;
bool useFP16;
bool useOffloadCopy;
}; };
} // namespace migraphxSamples } // namespace migraphxSamples
......
...@@ -51,6 +51,7 @@ typedef struct _InitializationParameterOfSegmentation ...@@ -51,6 +51,7 @@ typedef struct _InitializationParameterOfSegmentation
{ {
std::string parentPath; std::string parentPath;
std::string configFilePath; std::string configFilePath;
int loadMode;
} InitializationParameterOfSegmentation; } InitializationParameterOfSegmentation;
} // namespace migraphxSamples } // namespace migraphxSamples
......
...@@ -5,10 +5,49 @@ ...@@ -5,10 +5,49 @@
#include <SimpleLog.h> #include <SimpleLog.h>
#include <Filesystem.h> #include <Filesystem.h>
int main(){
migraphxSamples::DeepLabV3 deeplabv3; void MIGraphXSamplesUsage(char *programName)
{
printf("Usage : %s <index> \n", programName);
printf("index:\n");
printf("\t 0) DeepLabV3 Single Image Sample.\n");
printf("\t 1) DeepLabV3 Multiple Image Sample.\n");
}
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;
}
migraphxSamples::InitializationParameterOfSegmentation initParamOfSegmentationUnet; migraphxSamples::InitializationParameterOfSegmentation initParamOfSegmentationUnet;
std::vector<cv::Mat> srcImages;
switch(*argv[1]){
case '0':
srcImages.push_back(cv::imread("../Resource/Images/000001.jpg", 1));
initParamOfSegmentationUnet.loadMode = 1; //加载单个图片
break;
case '1':
std::string folderPath = "../Resource/Images/";
std::string imageExt = "*.jpg";
std::vector<cv::String> imagePaths;
cv::glob(folderPath + imageExt, imagePaths, false);
for(const auto& path : imagePaths){
srcImages.push_back(cv::imread(path, 1));
}
initParamOfSegmentationUnet.loadMode = 0; //加载多个图片
break;
}
migraphxSamples::DeepLabV3 deeplabv3;
initParamOfSegmentationUnet.configFilePath = CONFIG_FILE; initParamOfSegmentationUnet.configFilePath = CONFIG_FILE;
migraphxSamples::ErrorCode errorCode = deeplabv3.Initialize(initParamOfSegmentationUnet); migraphxSamples::ErrorCode errorCode = deeplabv3.Initialize(initParamOfSegmentationUnet);
if(errorCode != migraphxSamples::SUCCESS) if(errorCode != migraphxSamples::SUCCESS)
...@@ -18,15 +57,17 @@ int main(){ ...@@ -18,15 +57,17 @@ int main(){
} }
LOG_INFO(stdout, "succeed to initialize DeepLabV3\n"); LOG_INFO(stdout, "succeed to initialize DeepLabV3\n");
// 读取图像
cv::Mat srcImage = cv::imread("../Resource/Images/000001.jpg", 1);
// 推理 // 推理
cv::Mat maskImage; std::vector<cv::Mat> maskImages;
deeplabv3.Segmentation(srcImage, maskImage); deeplabv3.Segmentation(srcImages, maskImages);
LOG_INFO(stdout, "========== Segmentation Results ==========\n"); LOG_INFO(stdout, "========== Segmentation Results ==========\n");
LOG_INFO(stdout, "Segmentation results have been saved to ./Result.jpg\n"); LOG_INFO(stdout, "Segmentation results have been saved to build directory\n");
cv::imwrite("./Result.jpg", maskImage); for(int i = 0;i<maskImages.size();i++){
std::string fileName ="Result_"+std::to_string(i+1)+".jpg";
cv::imwrite(fileName, maskImages[i]);
}
return 0; return 0;
......
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