部署系列六基于nndeploy的深度学习 图像降噪unet部署

文章目录

    • 1.直接在源代码demo中修改
    • 2. 如何修改呢?
      • 3. 修改 graph
      • 4. 总结

https://github.com/DeployAI/nndeploy
https://nndeploy-zh.readthedocs.io/zh/latest/introduction/index.html

通过以上2个官方链接对nndeploy基本的使用方法应该有所了解了。
下面就是利用nndeploy跑一个图像降噪的unet类型网络。

为了方便,直接修改源码然后重新编译了一个demo。大家理解就好,可以自己整理完善,创建新的demo, 因为我这里没有创建新的deno,而是直接修改 yolov5的相关代码。

1.直接在源代码demo中修改

源代码如果你想运行yolo5是一个目标检测模型,可以通过下面的命令:
onnxruntime:115ms
./install/lib/demo_nndeploy_detect --name NNDEPLOY_YOLOV5 --inference_type kInferenceTypeOnnxRuntime --device_type kDeviceTypeCodeX86:0 --model_type kModelTypeOnnx --is_path --model_value …/…/yolov5s.onnx --input_type kInputTypeImage --input_path …/…/sample.jpg --output_path …/…/sample_output.jpg

openvino:57ms
./install/lib/demo_nndeploy_detect --name NNDEPLOY_YOLOV5 --inference_type kInferenceTypeOpenVino --device_type kDeviceTypeCodeX86:0 --model_type kModelTypeOnnx --is_path --model_value …/…/yolov5s.onnx --input_type kInputTypeImage --input_path …/…/sample.jpg --output_path …/…/sample_output.jpg

mnn:78ms
./install/lib/demo_nndeploy_detect --name NNDEPLOY_YOLOV5 --inference_type kInferenceTypeMnn --device_type kDeviceTypeCodeX86:0 --model_type kModelTypeMnn --is_path --model_value …/…/yolov5s.mnn --input_type kInputTypeImage --input_path …/…/sample.jpg --output_path …/…/sample_output.jpg

tensorrt: 17ms
./install/lib/demo_nndeploy_detect --name NNDEPLOY_YOLOV5 --inference_type kInferenceTypeTensorRt --device_type kDeviceTypeCodeCuda:0 --model_type kModelTypeOnnx --is_path --model_value …/…/yolov5s.onnx --input_type kInputTypeImage --input_path …/…/sample.jpg --output_path …/…/sample_output.jpg

然后我直接修改源码然后编译后通过下面的命令 可以运行 unet denoise model

tensorrt
./install/lib/demo_nndeploy_detect --name NNDEPLOY_YOLOV5 --inference_type kInferenceTypeTensorRt --device_type kDeviceTypeCodeCuda:0 --model_type kModelTypeOnnx --is_path --model_value /home/tony/nndeploy/mymodel/scripts/unet8.opt.onnx --input_type kInputTypeImage --input_path …/…/1007_01_06_40_000101.png --output_path …/…/sample_output.jpg

onnxruntime
./install/lib/demo_nndeploy_detect --name NNDEPLOY_YOLOV5 --inference_type kInferenceTypeOnnxRuntime --device_type kDeviceTypeCodeX86:0 --model_type kModelTypeOnnx --is_path --model_value /home/tony/nndeploy/mymodel/scripts/unet8.opt.onnx --input_type kInputTypeImage --input_path …/…/1007_01_06_40_000101.png --output_path …/…/sample_output.jpg

openvino:
./install/lib/demo_nndeploy_detect --name NNDEPLOY_YOLOV5 --inference_type kInferenceTypeOpenVino --device_type kDeviceTypeCodeX86:0 --model_type kModelTypeOnnx --is_path --model_value /home/tony/nndeploy/mymodel/scripts/unet8.opt.onnx --input_type kInputTypeImage --input_path …/…/1007_01_06_40_000101.png --output_path …/…/sample_output.jpg

MNN:
./install/lib/demo_nndeploy_detect --name NNDEPLOY_YOLOV5 --inference_type kInferenceTypeMnn --device_type kDeviceTypeCodeX86:0 --model_type kModelTypeMnn --is_path --model_value /home/tony/nndeploy/mymodel/scripts/unet8.opt.mnn --input_type kInputTypeImage --input_path …/…/1007_01_06_40_000101.png --output_path …/…/sample_output.jpg

TNN:
./install/lib/demo_nndeploy_detect --name NNDEPLOY_YOLOV5 --inference_type kInferenceTypeTnn --device_type kDeviceTypeCodeX86:0 --model_type kModelTypeTnn --is_path --model_value /home/tony/nndeploy/mymodel/scripts/unet8.sim.tnnproto,/home/tony/nndeploy/mymodel/scripts/unet8.sim.tnnmodel --input_type kInputTypeImage --input_path …/…/1007_01_06_40_000101.png --output_path …/…/sample_output.jpg

2. 如何修改呢?

首先明白我的模型,输入输出都是 c,h,w, 0-1, float32
首先修改demo.cc:
设置了graph的 input和output :都是 h, w, c , 0-1, float32
输入是 h,w,c float32
输出也是h,w,c float32

一个完整的graph包括:

  1. 前处理需要完成 从 h,w,c foat32 -> c, h, w float32
    2.然后infer跑model;:输入输出都是 c,h,w, 0-1, float32
    3.那么后处理需要完成 从 c, h, w,float32 -> h, w, c, float32

其实使用一个框架,要获取到 模型输入和输出的指针,然后可以用opencv进行前后预处理,很多框架都有自己的前后处理(我不太喜欢用,感觉不清晰有学习成本)
在这里插入图片描述
完整代码:

#include "flag.h"
#include "nndeploy/base/glic_stl_include.h"
#include "nndeploy/base/time_profiler.h"
#include "nndeploy/dag/node.h"
#include "nndeploy/device/device.h"
#include "nndeploy/model/detect/yolo/yolo.h"using namespace nndeploy;cv::Mat drawBox(cv::Mat &cv_mat, model::DetectResult &result) {// float w_ratio = float(cv_mat.cols) / float(640);// float h_ratio = float(cv_mat.rows) / float(640);float w_ratio = float(cv_mat.cols);float h_ratio = float(cv_mat.rows);const int CNUM = 80;cv::RNG rng(0xFFFFFFFF);cv::Scalar_<int> randColor[CNUM];for (int i = 0; i < CNUM; i++)rng.fill(randColor[i], cv::RNG::UNIFORM, 0, 256);int i = -1;for (auto bbox : result.bboxs_) {std::array<float, 4> box;box[0] = bbox.bbox_[0];  // 640.0;box[2] = bbox.bbox_[2];  // 640.0;box[1] = bbox.bbox_[1];  // 640.0;box[3] = bbox.bbox_[3];  // 640.0;box[0] *= w_ratio;box[2] *= w_ratio;box[1] *= h_ratio;box[3] *= h_ratio;int width = box[2] - box[0];int height = box[3] - box[1];int id = bbox.label_id_;NNDEPLOY_LOGE("box[0]:%f, box[1]:%f, width :%d, height :%d\n", box[0],box[1], width, height);cv::Point p = cv::Point(box[0], box[1]);cv::Rect rect = cv::Rect(box[0], box[1], width, height);cv::rectangle(cv_mat, rect, randColor[id]);std::string text = " ID:" + std::to_string(id);cv::putText(cv_mat, text, p, cv::FONT_HERSHEY_PLAIN, 1, randColor[id]);}return cv_mat;
}//
int main(int argc, char *argv[]) {gflags::ParseCommandLineNonHelpFlags(&argc, &argv, true);if (demo::FLAGS_usage) {demo::showUsage();return -1;}// 检测模型的有向无环图graph名称,例如:// NNDEPLOY_YOLOV5/NNDEPLOY_YOLOV6/NNDEPLOY_YOLOV8std::string name = demo::getName();// 推理后端类型,例如:// kInferenceTypeOpenVino / kInferenceTypeTensorRt / kInferenceTypeOnnxRuntimebase::InferenceType inference_type = demo::getInferenceType();// 推理设备类型,例如:// kDeviceTypeCodeX86:0/kDeviceTypeCodeCuda:0/...base::DeviceType device_type = demo::getDeviceType();// 模型类型,例如:// kModelTypeOnnx/kModelTypeMnn/...base::ModelType model_type = demo::getModelType();// 模型是否是路径bool is_path = demo::isPath();// 模型路径或者模型字符串std::vector<std::string> model_value = demo::getModelValue();// 有向无环图graph的输入边packertdag::Edge input("detect_in");// 有向无环图graph的输出边packertdag::Edge output("detect_out");// 创建检测模型有向无环图graphdag::Graph *graph =dag::createGraph(name, inference_type, device_type, &input, &output,model_type, is_path, model_value);if (graph == nullptr) {NNDEPLOY_LOGE("graph is nullptr");return -1;}// 初始化有向无环图graphNNDEPLOY_TIME_POINT_START("graph->init()");base::Status status = graph->init();if (status != base::kStatusCodeOk) {NNDEPLOY_LOGE("graph init failed");return -1;}NNDEPLOY_TIME_POINT_END("graph->init()");// 有向无环图graph的输入图片路径std::string input_path = demo::getInputPath();// opencv读图cv::Mat input_mat = cv::imread(input_path);int img_h = input_mat.rows;int img_w = input_mat.cols;input_mat.convertTo(input_mat, CV_32FC3, 1.0/255);// 将图片写入有向无环图graph输入边input.set(input_mat);// 定义有向无环图graph的输出结果cv::Mat result(img_h, img_w, CV_32FC3);//model::DetectResult result;// 将输出结果写入有向无环图graph输出边output.set(result);// 有向无环图Graphz运行NNDEPLOY_TIME_POINT_START("graph->run()");status = graph->run();if (status != base::kStatusCodeOk) {NNDEPLOY_LOGE("graph run failed");return -1;}NNDEPLOY_TIME_POINT_END("graph->run()");//drawBox(input_mat, result);std::string ouput_path = demo::getOutputPath();result.convertTo(result, CV_8UC3, 255);//cv::imwrite("ret.png", output);cv::imwrite(ouput_path, result);// 有向无环图graphz反初始化NNDEPLOY_TIME_POINT_START("graph->deinit()");status = graph->deinit();if (status != base::kStatusCodeOk) {NNDEPLOY_LOGE("graph deinit failed");return -1;}NNDEPLOY_TIME_POINT_END("graph->deinit()");NNDEPLOY_TIME_PROFILER_PRINT("detetct time profiler");// 有向无环图graphz销毁delete graph;NNDEPLOY_LOGE("hello world!\n");return 0;
}

3. 修改 graph

一个完整的graph包括:

  1. 前处理需要完成 从 h,w,c foat32 -> c, h, w float32
    2.然后infer跑model;:输入输出都是 c,h,w, 0-1, float32
    3.那么后处理需要完成 从 c, h, w,float32 -> h, w, c, float32

dag::Graph* createYoloV5Graph(const std::string& name,
base::InferenceType inference_type,
base::DeviceType device_type, dag::Edge* input,
dag::Edge* output, base::ModelType model_type,
bool is_path,
std::vectorstd::string model_value)
中修改前后处理函数即可。

前处理,infer , 后处理是一个 graph , 也就是demo中完整的图。
demo中的input和output是 完整的图的输入输出。

然后前处理,infer, 后处理 内部也有自己的input和output,不要搞混淆了。

比如模型infer输入,输出都是c,h,w, float32的结果,
后处理 input是 c,h,w float32 的数据,output转换为 h,w,c float32的数据(对应上面的cv::Mat result(img_h, img_w, CV_32FC3);)

那么我们修改 后处理函数为

base::Status YoloPostProcess::runV5V6() {// data, img_data 就是输入和输出的指针,将图像从c,h,w转为h,w,c device::Tensor* tensor = inputs_[0]->getTensor();float* data = (float*)tensor->getPtr();int batch = tensor->getBatch();int channel = tensor->getChannel();int height = tensor->getHeight();int width = tensor->getWidth();
NNDEPLOY_LOGE("batch:%d, channel:%d, height:%d, width:%d. (%f,%f,%f))\n", batch,  channel, height, width, data[0], data[1], data[2]);
cv::Mat* dst = outputs_[0]->getCvMat();
NNDEPLOY_LOGE("mat  channel:%d, height:%d, width:%d.\n", dst->channels(),   dst->rows, dst->cols);auto* img_data = (float*)dst->data;for (int h = 0; h < height; h++){for (int w = 0; w < width; w++){for (int c = 0; c < 3; c++){int in_index = h * width * 3 + w * 3 + c;int out_index = c * width * height + h * width + w;// if (w < 10)//   if(h < 10)//     printf("%.2f,", data[out_index]);img_data[in_index] = data[out_index];}}// if(h < 10)//   printf("\n");}return base::kStatusCodeOk;
}

前处理也是同样的道理。

4. 总结

前后处理都完成后,进重新编译,得到的./install/lib/demo_nndeploy_detect 就是处理 UNET类型的输入输出了, 不能处理目标检测网络了,目标检测的输入是 uint8 image, 输出的是一系列目标框,对应的前后处理都是不同的。
1080P的图像, 在我训练的降噪model(未量化)上 基于openvino在 amd的Ryzen Embedded上可以跑到30-60ms。
降噪前后对比:降噪最重要是不损失细节且可以提升清晰度。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/168803.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动语音识别 支持86种语言 Dragon Professional 16 Crack

从个体从业者到全球组织&#xff0c;文档密集型行业的专业人士长期以来一直依靠 Dragon 语音识别来更快、更高效地创建高质量文档&#xff0c;减少管理开销&#xff0c;以便他们能够专注于客户。了解 Dragon Professional v16 如何通过单一解决方案提高标准&#xff0c;为各个业…

ArcGis如何用点连线?

这里指的是根据已有坐标点手动连线&#xff0c;类似于mapgis中的“用点连线”&#xff0c;线的每个拐点是可以自动捕捉到坐标点的&#xff0c;比直接画精确。 我也相信这么强大的软件一定可以实现类似于比我的软件上坐标时自动生成的线&#xff0c;但是目前我还没接触到那里&a…

基于IDEA+SpringBoot+微服务开发的P2P平台项目

基于springboot的社区养老医疗综合服务平台 项目介绍&#x1f481;&#x1f3fb; 项目名称&#xff1a;基于P2P的金融项目 一个基于P2P&#xff08;点对点&#xff09;模式的金融服务平台&#xff0c;致力于提供透明、高效、安全的金融服务。我们的目标是连接借款人与投资者&am…

Clion在Windows下build时出现undefined reference,即使cmake已经正确链接第三方库(如protobuf)?

你是否正在使用clion自带的vcpkg来安装了protobuf&#xff1f; 或者你是否自己使用visual studio自己编译了libprotobuf.lib&#xff1f; 你是否已经正确在CmakeLists.txt中添加了以下命令&#xff1a; find_package(Protobuf CONFIG REQUIRED) include_directories(${Protobu…

inBuilder低代码平台新特性推荐-第十期

各位知乎的友友们&#xff0c;大家好~ 今天来给大家带来的是inBuilder低代码平台特性推荐系列第十期——查看变更日志 场景介绍 【销售订单列表】中添加查看变更日志按钮&#xff0c;可以查看列表当前行数据的历史变更记录。 运行时效果 概念 系统中有些关键业务关键数据&am…

【极客技术】真假GPT-4?微调 Llama 2 以替代 GPT-3.5/4 已然可行!

近日小编在使用最新版GPT-4-Turbo模型&#xff08;主要特点是支持128k输入和知识库截止日期是2023年4月&#xff09;时&#xff0c;发现不同商家提供的模型回复出现不一致的情况&#xff0c;尤其是模型均承认自己知识库达到2023年4月&#xff0c;但当我们细问时&#xff0c;Fak…

如何开发有趣而富有创意的营销小游戏

在数字化时代&#xff0c;企业通过创意而独特的方式与目标受众互动&#xff0c;已成为提高品牌知名度和用户参与度的重要手段之一。其中&#xff0c;设计一款引人入胜的营销小游戏&#xff0c;不仅能吸引用户的眼球&#xff0c;还能有效传达品牌信息。以下是一些建议&#xff0…

AI赋能数据表设计

数据表设计软件用过多种&#xff0c;用Ai 设计表几年Ai大模型爆发之后提升了新的高度 用navicat 设计表就是在跟团队的人介绍这次功能的表结构时&#xff0c;没办法看备注&#xff0c;只能看英文字段&#xff0c;导致在比较复杂的表中&#xff0c;总是在表结构和图形结构中来回…

转录组学习第5弹-比对参考基因组

比对参考基因组 在构建文库的过程中需要将DNA片段化&#xff0c;因此测序得到的序列只是基因组的部分序列。为了确定测序reads在基因组上的位置&#xff0c;需要将reads比对回参考基因组上&#xff0c;这个步骤叫做比对&#xff0c;即文献中所提到的alignment或mapping。包括基…

2023.11.23使用flask实现在指定路径生成文件夹操作

2023.11.23使用flask实现在指定路径生成文件夹操作 程序比较简单&#xff0c;实现功能&#xff1a; 1、前端输入文件夹 2、后端在指定路径生成文件夹 3、前端反馈文件夹生成状态 main.py from flask import Flask, request, render_template import osapp Flask(__name__)a…

SAP从放弃到入门系列之-制造商零件编号-MPN 物料

文章目录 一、概念二、 配置点配置点1&#xff1a;启用MPN配置点2&#xff1a;MPN配置参数文件配置点3&#xff1a;激活库存管理的MPN所有功能变化1&#xff1a;MM01界面有库存管理制造商零部件号的字段&#xff1a;变化2&#xff1a;MM60界面的查询条件多了MPN物料号变化3&…

Mac开发环境——MacOSX安装与配置Anaconda与PyCharm详细流程

一、安装与使用Anaconda 1.简介 Anaconda 是一个用于数据科学、机器学习和科学计算的开源发行版和包管理器。有许多可用于数据处理、分析和建模的工具和库&#xff0c;并提供了一个方便的环境管理系统。Anaconda 包含了 Python 解释器和许多常用的 Python 包&#xff0c;以及…

【Unity入门】碰撞检测

碰撞器由来 1.系统默认会给每个对象(GameObject)添加一个碰撞组件(ColliderComponent)&#xff0c;一些背景对象则可以取消该组件。 2.在unity3d中&#xff0c;能检测碰撞发生的方式有两种&#xff0c;一种是利用碰撞器&#xff0c;另一种则是利用触发器。这两种方式的应用非…

Android Studio 显示build variants工具栏

工具栏&#xff1a; 如下图所示 依次点击View-->ToolWindows-->Build Variants。 在此记个笔记

Spring原理——基于xml配置文件创建IOC容器的过程

Spring框架的核心之一是IOC&#xff0c;那么我们是怎么创建出来的Bean呢&#xff1f; 作者进行了简单的总结&#xff0c;希望能对你有所帮助。 IOC的创建并不是通过new而是利用了java的反射机制&#xff0c;利用了newInstance方法进行的创建对象。 首先&#xff0c;我们先定义…

数据结构 | 堆【图解】

数据结构 | 堆【图解】 文章目录 数据结构 | 堆【图解】堆的概念及结构堆的实现堆的初始化堆的插入【重点】堆的删除【重点】取堆顶的数据堆的数据个数堆的判空堆的销毁 全部代码 堆的概念及结构 堆&#xff08;heap&#xff09;&#xff1a; 一种有特殊用途的数据结构——用来…

详解:什么是“智能合同管理”

未来已来&#xff0c;行业数字化进行的如火如荼&#xff0c;并逐步驶入深水区。合同是企业开展经营活动的重要文件&#xff0c;也是风险管控的核心地带&#xff0c;做好合同管理对企业运营效率的提升至关重要。近年来&#xff0c;合同管理已经跟随企业数字化的浪潮进入转型时期…

Leetcode—2824.统计和小于目标的下标对数目【简单】

2023每日刷题&#xff08;三十九&#xff09; Leetcode—2824.统计和小于目标的下标对数目 实现代码 class Solution { public:int countPairs(vector<int>& nums, int target) {int n nums.size();sort(nums.begin(), nums.end());int left 0, right left 1;i…

迈巴赫S480升级电动后门 手势控制开关 更加方便

安装了电动后门的迈巴赫S480&#xff0c;从原来的触摸门把手和门内拉手开关门&#xff0c;增加了钥匙控制、前排显示屏控制、后门按键开关控制、后排娱乐屏控制等多种开关门方式&#xff0c;将一个待客之礼体现出多种不一样的尊贵感受。 中控显示屏由驾驶者控制&#xff0c;可以…

UML建模图文详解教程07——活动图

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl本文参考资料&#xff1a;《UML面向对象分析、建模与设计&#xff08;第2版&#xff09;》吕云翔&#xff0c;赵天宇 著 活动图概述 活动图(activity diagram)是 UML中一种重…