LYT-Net——轻量级网络低光照条件图像修复模型推理部署(C++/Python)

news2024/11/25 22:42:00

1.环境安装

conda create -n LYT_Torch python=3.9 -y
conda activate LYT_Torch
conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia

pip install matplotlib scikit-learn scikit-image opencv-python yacs joblib natsort h5py tqdm tensorboard

pip install einops gdown addict future lmdb numpy pyyaml requests scipy yapf lpips thop timm

2. Onnx模型推理

2.1 Onnxruntime

ONNX Runtime(Open Neural Network Exchange Runtime)是一个用于推理(inference)的高性能、跨平台的开源引擎,它由微软公司发起并维护。ONNX Runtime 支持多种机器学习模型,包括但不限于 PyTorch、TensorFlow、SciKit-Learn 等,允许开发者在不同框架之间无缝迁移模型,并在生产环境中高效运行。

  • 跨平台:支持 Windows、Linux 和 macOS 等多种操作系统。
  • 高性能:优化了模型的推理速度,特别是在使用 GPU 加速时。
  • 多框架支持:原生支持 ONNX 格式的模型,同时也支持从其他框架转换来的模型。
  • 实时性:适用于需要实时或近实时推理的应用场景。
  • 易于集成:提供了 C++ 和 Python API,方便集成到不同语言的应用程序中。
  • 自动混合精度:支持自动混合精度(AMP),可以在不损失模型精度的情况下提高推理速度。
  • 量化支持:支持模型量化,可以进一步减小模型大小并提高推理速度。
  • 微服务:支持作为微服务部署,易于在云环境或边缘设备上使用。

使用 ONNX Runtime 进行模型推理的基本步骤如下:

  • 转换模型:如果模型不是 ONNX 格式,需要使用相应的转换工具将其转换为 ONNX 格式。
  • 加载模型:使用 ONNX Runtime 的 API 加载转换后的模型。
  • 准备输入:准备模型推理所需的输入数据,并确保其符合模型的输入要求。
  • 运行推理:调用 ONNX Runtime 的推理 API 运行模型并获取输出。
  • 处理输出:根据应用需求处理模型的推理输出。

2.2 C++推理

#include "LYTNet.h"

LYTNet::LYTNet(std::string model_path)
{
	OrtStatus* status = OrtSessionOptionsAppendExecutionProvider_CUDA(sessionOptions, 0);   ///cuda

	sessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);
	std::wstring widestr = std::wstring(model_path.begin(), model_path.end()); windows
	ort_session = new Ort::Session(env, widestr.c_str(), sessionOptions); windows*/
	//ort_session = new Session(env, model_path.c_str(), sessionOptions); linux

	size_t numInputNodes = ort_session->GetInputCount();
	size_t numOutputNodes = ort_session->GetOutputCount();
	Ort::AllocatorWithDefaultOptions allocator;
	for (int i = 0; i < numInputNodes; i++)
	{
		input_names.push_back(ort_session->GetInputName(i, allocator));
		Ort::TypeInfo input_type_info = ort_session->GetInputTypeInfo(i);
		auto input_tensor_info = input_type_info.GetTensorTypeAndShapeInfo();
		auto input_dims = input_tensor_info.GetShape();
		input_node_dims.push_back(input_dims);
	}
	for (int i = 0; i < numOutputNodes; i++)
	{
		output_names.push_back(ort_session->GetOutputName(i, allocator));
		Ort::TypeInfo output_type_info = ort_session->GetOutputTypeInfo(i);
		auto output_tensor_info = output_type_info.GetTensorTypeAndShapeInfo();
		auto output_dims = output_tensor_info.GetShape();
		output_node_dims.push_back(output_dims);
	}
	this->inpHeight = input_node_dims[0][1];
	this->inpWidth = input_node_dims[0][2];
	this->outHeight = output_node_dims[0][1];
	this->outWidth = output_node_dims[0][2];
}


/***************** Mat转vector **********************/
template<typename _Tp>
std::vector<_Tp> convertMat2Vector(const cv::Mat& mat)
{
	return (std::vector<_Tp>)(mat.reshape(1, 1));//通道数不变,按行转为一行
}

/****************** vector转Mat *********************/
template<typename _Tp>
cv::Mat convertVector2Mat(std::vector<_Tp> v, int channels, int rows)
{
	cv::Mat mat = cv::Mat(v).clone();//将vector变成单列的mat,这里需要clone(),因为这里的赋值操作是浅拷贝
	cv::Mat dest = mat.reshape(channels, rows);
	return dest;
}


cv::Mat LYTNet::detect(cv::Mat srcimg)
{
	cv::Mat dstimg;
	resize(srcimg, dstimg, cv::Size(this->inpWidth, this->inpHeight));
	dstimg.convertTo(dstimg, CV_32FC3, 1 / 127.5, -1.0);
	this->input_image_ = (std::vector<float>)(dstimg.reshape(1, 1));

	// const size_t area = this->inpWidth * this->inpHeight * 3;
	// this->input_image_.resize(area);
	// memcpy(this->input_image_.data(), (float*)dstimg.data, area*sizeof(float));

	std::array<int64_t, 4> input_shape_{ 1, this->inpHeight, this->inpWidth, 3 };

	auto allocator_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
	Ort::Value input_tensor_ = Ort::Value::CreateTensor<float>(allocator_info, input_image_.data(),
		input_image_.size(), input_shape_.data(), input_shape_.size());

	std::vector<Ort::Value> ort_outputs = ort_session->Run(Ort::RunOptions{ nullptr }, &input_names[0],
		&input_tensor_, 1, output_names.data(), output_names.size());  

	float* pred = ort_outputs[0].GetTensorMutableData<float>();
	cv::Mat output_image(outHeight, outWidth, CV_32FC3, pred);
	output_image = (output_image + 1.0) * 127.5;
	output_image.convertTo(output_image, CV_8UC3);
	resize(output_image, output_image, cv::Size(srcimg.cols, srcimg.rows));
	return output_image;
}

2.3 Python推理部署

import argparse
import cv2
import numpy as np
import onnxruntime

class LYTNet:
    def __init__(self, modelpath):
        # Initialize model
        # self.net = cv2.dnn.readNet(modelpath) ####opencv-dnn读取失败
        so = onnxruntime.SessionOptions()
        so.log_severity_level = 3
        self.net = onnxruntime.InferenceSession(modelpath, so)
        self.input_height = self.net.get_inputs()[0].shape[1]   ####(1,h,w,3)
        self.input_width = self.net.get_inputs()[0].shape[2]
        self.input_name = self.net.get_inputs()[0].name

    def detect(self, srcimg): 
        input_image = cv2.resize(srcimg, (self.input_width, self.input_height))
        input_image = input_image.astype(np.float32) / 127.5 - 1.0
        blob = np.expand_dims(input_image, axis=0).astype(np.float32)

        result = self.net.run(None, {self.input_name: blob})

        # Post process:squeeze, RGB->BGR, Transpose, uint8 cast
        output_image = np.squeeze(result[0])
        output_image = (output_image + 1.0 ) * 127.5
        output_image = output_image.astype(np.uint8)
        output_image = cv2.resize(output_image, (srcimg.shape[1], srcimg.shape[0]))
        return output_image


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--imgpath', type=str,
                        default='testimgs/4_1.JPG', help="image path")
    parser.add_argument('--modelpath', type=str,
                        default='weights/lyt_net_lolv2_real_320x240.onnx', help="model path")
    args = parser.parse_args()

    mynet = LYTNet(args.modelpath)
    srcimg = cv2.imread(args.imgpath)

    dstimg = mynet.detect(srcimg)

    if srcimg.shape[0] >= srcimg.shape[1]:
        boundimg = np.zeros((srcimg.shape[0], 10, 3), dtype=srcimg.dtype)+255
        combined_img = np.hstack([srcimg, boundimg, dstimg])
    else:
        boundimg = np.zeros((10, srcimg.shape[1], 3), dtype=srcimg.dtype)+255
        combined_img = np.vstack([srcimg, boundimg, dstimg])
    
    winName = 'Deep Learning use OpenCV-dnn'
    cv2.namedWindow(winName, 0)
    cv2.imshow(winName, combined_img)  ###原图和结果图也可以分开窗口显示
    cv2.waitKey(0)
    cv2.destroyAllWindows()

2.4 实现效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码与模型下载地址:https://download.csdn.net/download/matt45m/89600913

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

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

相关文章

Conformal low power-7.运行Conformal Low Power 1801流程

要获取有关原生1801流程的最新信息&#xff08;例如功能、指南、常见问题解答和dofile脚本&#xff09;&#xff0c;请使用SET WEB_INTERFACE ON命令启动Web界面。 左手边列出了所有的Conformal产品。还有一个名为“Sample Dofiles”的部分&#xff0c;提供了在不同场景下运行C…

第一个Python Web程序

1、离线安装Django 由于Python是3.7版本,Django选择2.2.4版本,并且中间需要安装依赖包。全部安装包如下: 打开Anaconda Prompt,先进入Python3.7环境,然后依次安装各个包: 至此,Django离线安装成功。 2、编写第一个Django程序 2.1 创建Django项目 创建项目welcome时…

C#初级——继承

继承 继承是面向对象程序设计中最重要的概念之一。继承允许我们根据一个类来定义另一个类&#xff0c;不需要完全重新编写新的数据成员和成员函数&#xff0c;只需要设计一个新的类&#xff0c;继承了已有的类的成员即可。这个已有的类被称为的基类&#xff08;父类&#xff0…

(自适应手机端)行业协会机构网站模板

(自适应手机端)行业协会机构网站模板PbootCMS内核开发的网站模板&#xff0c;该模板适用于行业协会网站等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b;自适应手机端&#xff0c;同一个后台&#xff0c;数据即时同步&#…

git的配置使用

第三周 Tursday 早 git日志的安装使用 [rootweb ~]# yum -y install git.x86_64 //安装软件包 [rootweb ~]# rpm -ql git //查看git的包 ​ [rootweb ~]# mkdir /yy000 //创建新目录 [rootweb ~]# cd /yy000/ [rootweb yy000]# git init //将当前目录做为仓库…

基于SpringBoot+Vue的娱乐代理售票系统(带1w+文档)

基于SpringBootVue的娱乐代理售票系统(带1w文档) 基于SpringBootVue的娱乐代理售票系统(带1w文档) 休闲娱乐代理售票系统的开发运用java技术&#xff0c;MIS的总体思想&#xff0c;以及MYSQL等技术的支持下共同完成了该系统的开发&#xff0c;实现了休闲娱乐代理售票管理的信息…

Why decoder-only? LLM架构的演化之路

如何根据大模型架构进行选型 ©作者|Zhongmei 来源|神州问学 引言 本文想为大型语言模型&#xff08;LLMs&#xff09;及其下游自然语言处理&#xff08;NLP&#xff09;任务的实践者和用户提供一份全面且实用的指南。将从模型架构的角度出发&#xff0c;对比不同架构的…

多线程上下文切换:详解与优化

多线程上下文切换&#xff1a;详解与优化 一、什么是多线程上下文切换&#xff1f;二、对性能的影响2.1 优点2.2 缺点 三、优化策略 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 一、什么是多线程上下文切换&#xff1f; 多线程上下文切…

在 Vim 编辑器中,如果某个单词被意外地高亮显示,使用:noh可以取消高亮显示

文章目录 1、问题出现的背景2、解决办法 1、问题出现的背景 配置镜像加速器&#xff0c;修改 /etc/docker/daemon.json 目录下的文件&#xff0c;不小心高亮显示https&#xff0c;产生问题的步骤是&#xff0c;我先是按esc键退出vim的编辑模式&#xff0c;然后在https的前面按…

Android经典面试题之Kotlin中 if 和 let的区别

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 在Kotlin中&#xff0c;if和let虽然有时候用来处理相似的情景&#xff0c;但它们实际上是用于不同的场景并具有不同的性质。下面我们来详细对比…

K-近邻和神经网络

K-近邻&#xff08;K-NN, K-Nearest Neighbors&#xff09; 原理 K-近邻&#xff08;K-NN&#xff09;是一种非参数分类和回归算法。K-NN 的主要思想是根据距离度量&#xff08;如欧氏距离&#xff09;找到训练数据集中与待预测样本最近的 K 个样本&#xff0c;并根据这 K 个…

安科瑞ASJ系列智能剩余电流继电器介绍

产品概述&#xff1a; 安科瑞ASJ系列智能剩余电流继电器是一种重要的电气安全保护设备&#xff0c;‌主要用于交流50Hz、‌额定电压400V及以下的TT和TN系统配电线路中。‌该系列继电器的主要功能包括对电气线路进行接地故障保护&#xff0c;‌以防止接地故障电流引起的设备损坏…

C语言家教记录(一)

C语言家教记录&#xff08;一&#xff09; 导语C语言简介特点优点缺点 Codeblocks安装和使用简单程序结构变量&#xff08;常量&#xff09;和赋值类型声明常量赋值标识符 基本运算输入输出printf基本格式转义序列 scanf转换说明 示例程序总结和复习 导语 本次授课内容如下&am…

一句JS代码,实现随机颜色的生成

今天我们只用 一句JS代码&#xff0c;实现随机颜色的生成&#xff0c;首先看一下效果&#xff1a; 每次刷新浏览器背景颜色都不一样 实现此效果的JS函数 &#xff1a; let randomColor () > ...: 定义一个箭头函数randomColor&#xff0c;用于生成一个随机颜色。 Math.ra…

苹果发布iPhone AI,Apple Intelligence初版落地!未融入ChatGPT,仅面向付费开发者

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 苹果公司Apple Intelligence初版落地&#xff1a;iPhone AI引领智能化新篇章 在全球科技领域&#xff0c;苹果公司一直以其创新精神和前沿技术…

java算法day27

java算法day27 动态规划初步总结509 斐波那契数杨辉三角打家劫舍完全平方数 动态规划初步总结 如果你感觉某个问题有很多重叠子问题&#xff0c;使用动态规划是最有效的。 动态规划的过程就是每一个状态一定是由上一个状态推导出来的&#xff0c;这一点就区分于贪心了。贪心是…

热力图大揭秘!Matplotlib教你如何画出让数据‘火辣辣‘的激情图!

1. 引言 嘿&#xff0c;小伙伴们&#xff01;今天咱们来点不一样的&#xff0c;走进Matplotlib的神奇世界&#xff0c;一起绘制那让人热血沸腾的热力图&#xff01;别误会&#xff0c;这可不是什么天气预报图&#xff0c;而是让数据“火辣辣”展现自我的秘密武器。想象一下&am…

PHP进阶-CentOS7部署LNMP服务架构的项目

在开发和部署Web应用时&#xff0c;LNMP&#xff08;Linux、Nginx、MySQL、PHP&#xff09;的组合是非常常见的。这篇博客将介绍如何通过一个简单的脚本&#xff0c;在CentOS 7上部署LNMP&#xff0c;并将PHP项目自动部署到服务器上。这不仅可以节省大量的时间&#xff0c;还能…

《系统架构设计师教程(第2版)》第13章-层次式架构设计理论与实践-03-中间层(业务层|逻辑层)架构设计

文章目录 1. 业务逻辑层组件设计1.1 业务逻辑组件的实现类1.2 业务逻辑组件的配置 2. 业务逻辑层工作流设计2.1 工作流2.2 工作流参考模型2.2.1 概述2.2.1 工作流参考模型 3. 业务逻辑层实体设计3.1 业务逻辑层实体概述3.2 逻辑层实体的表示方法3.2.1 XML表示业务层实体3.2.2 通…