OnnxRuntime----Lite-Mono单目深度估计ONNX推理

news2024/11/29 0:45:44

题目要求:学习了解单目深度估计模型Lite-Mono,根据上篇VSCode配置之OnnxRuntime(CPU) && YOLOv7验证,实现深度估计模型Lite-Mono推理,并集成到现有ONNX系列模型中。
Lite-Mono论文:Lite-Mono:A Lightweight CNN and Transformer Architecture for Self-Supervised Monocular Depth Estimation
Lite-Mono 源码:Lite-Mono GitHub

分析:
1)了解Lite-Mono的基本原理和代码理解
2)将模型转化为更加方便高效的ONNX模型并在OnnxRuntime中完成推理过程(并验证)

  • 结果展示(已对Pymodel和Cmodel输出disparity验证):
    在这里插入图片描述
  • Pytorch转ONNX模型
    参看OpenCV----MonoDepthv2单目深度估计ONNX推理
  • OnnxRuntime Cmodel:
#include <assert.h>
#include <vector>
#include <ctime>
#include <iostream>
#include <onnxruntime_cxx_api.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>

using std::cout;
using std::endl;

class litemono
{
public:
    litemono(const wchar_t* onnx_model_path);
    std::vector<float> predict(std::vector<float>& input_data, int batch_size = 1, int index = 0);
    cv::Mat predict(cv::Mat& input_tensor, int batch_size = 1, int index = 0);
private:
    Ort::Env env;
    Ort::Session session;
    Ort::AllocatorWithDefaultOptions allocator;
    std::vector<const char*>input_node_names = {"input"};
    std::vector<const char*>output_node_names = {"output"};
    std::vector<int64_t> input_node_dims;
    std::vector<int64_t> output_node_dims;
};
litemono::litemono(const wchar_t* onnx_model_path) :session(nullptr), env(nullptr)
{
    // init env
    this->env = Ort::Env(ORT_LOGGING_LEVEL_WARNING, "lite_mono");
    // init session options
    Ort::SessionOptions session_options;
    // session_options.SetInterOpNumThreads(1);
    // session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL);
    // create session and load to memory
    this->session = Ort::Session(env, onnx_model_path, session_options);
    //输入输出节点数量和名称
    size_t num_input_nodes = session.GetInputCount();
    size_t num_output_nodes = session.GetOutputCount();
    for (int i = 0; i < num_input_nodes; i++)
    {
        Ort::TypeInfo type_info = session.GetInputTypeInfo(i);
		auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
		ONNXTensorElementDataType type = tensor_info.GetElementType();
        this->input_node_dims = tensor_info.GetShape();
    }
    for (int i = 0; i < num_output_nodes; i++)
    {
        Ort::TypeInfo type_info = session.GetOutputTypeInfo(i);
		auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
		ONNXTensorElementDataType type = tensor_info.GetElementType();
        this->output_node_dims = tensor_info.GetShape();
    }
}

std::vector<float> litemono::predict(std::vector<float>& input_tensor_values, int batch_size, int index)
{
    this->input_node_dims[0] = batch_size;
    this->output_node_dims[0] = batch_size;
    float* floatarr = nullptr;
    try
    {
        std::vector<const char*>output_node_names;
        if (index != -1)
        {
            output_node_names = { this->output_node_names[index] };
        }
        else
        {
            output_node_names = this->output_node_names;
        }
        this->input_node_dims[0] = batch_size;
        auto input_tensor_size = input_tensor_values.size();
        auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
        Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, input_tensor_values.data(), input_tensor_size, input_node_dims.data(), 4);
        auto output_tensors = session.Run(Ort::RunOptions{ nullptr }, input_node_names.data(), &input_tensor, 1, output_node_names.data(), 1);
        assert(output_tensors.size() == 1 && output_tensors.front().IsTensor());
        floatarr = output_tensors[0].GetTensorMutableData<float>();
    }
    catch (Ort::Exception& e)
    {
        throw e;
    }
    int64_t output_tensor_size = 1;
    for (auto& it : this->output_node_dims)
    {
        output_tensor_size *= it;
    }
    std::vector<float>results(output_tensor_size);
    for (unsigned i = 0; i < output_tensor_size; i++)
    {
        results[i] = floatarr[i];
    }
    return results;
}
cv::Mat litemono::predict(cv::Mat& input_tensor, int batch_size, int index)
{
    int input_tensor_size = input_tensor.cols * input_tensor.rows * 3;
    std::size_t counter = 0;
    std::vector<float>input_data(input_tensor_size);
    std::vector<float>output_data;
    try
    {
        for (unsigned k = 0; k < 3; k++)
        {
            for (unsigned i = 0; i < input_tensor.rows; i++)
            {
                for (unsigned j = 0; j < input_tensor.cols; j++)
                {
                    input_data[counter++] = static_cast<float>(input_tensor.at<cv::Vec3b>(i, j)[k]) / 255.0;
                }
            }
        }
    }
    catch (cv::Exception& e)
    {
        printf(e.what());
    }
    try
    {
        output_data = this->predict(input_data);
    }
    catch (Ort::Exception& e)
    {
        throw e;
    }
    cv::Mat output_tensor(output_data);
    output_tensor =output_tensor.reshape(1, {192, 640}) * 255.0;
    output_tensor.convertTo(output_tensor, CV_8UC1);
    cv::applyColorMap(output_tensor, output_tensor, cv::COLORMAP_JET);
    return output_tensor;
}
  • 测试代码 (框架整体代码见之前博客 OpenCV 检测/分割 兼容框架)
...
int main(int argc, char* argv[])
{
    const wchar_t* model_path = L"model/lite_mono.onnx";
    litemono model(model_path);
    cv::Mat image = cv::imread("inference/car.jpg");
    auto ori_h = image.cols;
    auto ori_w = image.rows;
    cv::imshow("image", image);
    cv::resize(image, image, {640, 192}, 0.0, 0.0, cv::INTER_CUBIC);
    cv::cvtColor(image, image, cv::COLOR_BGR2RGB);
    auto result = model.predict(image);
    cv::resize(result, result, {ori_h, ori_w}, 0.0, 0.0, cv::INTER_CUBIC);
    cv::imshow("result", result);
    cv::waitKey(0);
    cv::destroyAllWindows();
}
  • 小结
    模型整合和框架迁移:
    1)Lite-Mono的模型结构和MonoDepthv2比较接近,均包含编码器(encoder)和深度解码器(depth-encoder),在推理时只需要最浅层输出结果即可;
    2)在上一篇YOLOv7 OnnxRuntime推理配置基础上做深度估计,了解该框架的基本推理流程,实践起来更加方便快捷,对系统框架有了进一步的了解和深入;
    3)接下来可能会考虑尝试在手机端部署AI demo,实测真实场景下的推理精度和速度;

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

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

相关文章

运算放大器的内部结构-运放

运算放大器的内部结构 算放大器的内部电路&#xff0c;对于使用者在遭遇应用上的极限而导致无法达成系统设计规格时&#xff0c;非常有帮助。而虽然各家厂商推出的运算放大器性能与规格互有差异&#xff0c;但是一般而言标准的运算放大器都包含下列三个部分&#xff1a; 差动…

走进小程序【一】什么是小程序?

文章目录&#x1f31f;前言&#x1f31f;发展史&#x1f31f;什么是[微信小程序](https://developers.weixin.qq.com/miniprogram/dev/framework/)&#xff1f;&#x1f31f;微信小程序能做什么&#xff1f;&#x1f31f;小程序发展前景和优势&#x1f31f;写在最后&#x1f31…

ROS1学习笔记:launch启动文件的使用方法

参考B站古月居ROS入门21讲&#xff1a;launch启动文件的使用方法 基于VMware Ubuntu 20.04 Noetic版本的环境 文章目录一、launch的文件结构二、launch的文件语法2.1 根元素2.2 参数设置2.3 重映射和嵌套三、相关示例simple.launchturtlesim_parameter_config.launchstart_tf_d…

SpringBoot 整合 JSP和MyBatis

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

【满血Buff】ChatGPT科普篇,三段式介绍,内含各种高效率插件

【满血Buff】ChatGPT科普篇&#xff0c;三段式介绍&#xff0c;内含各种高效率插件1、ChatGPT是什么2、为什么要掌握ChatGPT效能工具3、ChatGPT能做什么4、和ChatGPT相关的谷歌插件4.1 WebChatGPT4.2 OpenAI Ttanslator 翻译4.3 ChatGPT for Google本篇博客采用三段论的叙事方式…

Redis Cluster详解

文章目录集群设计目标Redis 集群协议中的客户端和服务器角色写入安全可用性(Availability)性能(Performance)避免合并(merge)操作主要模块介绍哈希槽(Hash Slot)Keys hash tagsCluster nodes属性Cluster总线集群拓扑节点握手请求重定向Moved 重定向ASK 重定向smart客户端状态检…

基于Tensorflow搭建卷积神经网络CNN(新冠肺炎医学图像识别)保姆及级教程

项目介绍 TensorFlow2.X 搭建卷积神经网络&#xff08;CNN&#xff09;&#xff0c;实现人脸识别&#xff08;可以识别自己的人脸哦&#xff01;&#xff09;。搭建的卷积神经网络是类似VGG的结构(卷积层与池化层反复堆叠&#xff0c;然后经过全连接层&#xff0c;最后用softm…

物理世界的互动之旅:Matter.js入门指南

theme: smartblue 本文简介 戴尬猴&#xff0c;我是德育处主任 欢迎来到《物理世界的互动之旅&#xff1a;Matter.js入门指南》。 本文将带您探索 Matter.js&#xff0c;一个强大而易于使用的 JavaScript 物理引擎库。 我将介绍 Matter.js 的基本概念&#xff0c;包括引擎、世界…

【Jetpack】DataBinding 架构组件 ③ ( 使用 include 导入二级界面布局 | 二级页面绑定数据模型 )

文章目录一、使用 include 导入二级界面布局二、二级页面绑定数据模型1、将二级界面布局转为 DataBinding 布局2、在主布局中为二级界面布局传递数据模型三、核心代码示例1、主布局2、子布局3、Java 代码4、执行结果一、使用 include 导入二级界面布局 如果在 DataBinding 布局…

C++之深入解析虚函数表的实现及其内存布局

一、虚函数表概述 C 中的虚函数的作用主要是实现了多态的机制&#xff0c;关于多态&#xff0c;简而言之就是用父类型别的指针指向其子类的实例&#xff0c;然后通过父类的指针调用实际子类的成员函数&#xff1a; Derive d; Base1 *b1 &d; Base2 *b2 &d; Base3 *b…

使用自己修改的特制舵机,支持关节角度回传的桌面级小机器工具人

有人说:一个人从1岁活到80岁很平凡,但如果从80岁倒着活,那么一半以上的人都可能不凡。 生活没有捷径,我们踩过的坑都成为了生活的经验,这些经验越早知道,你要走的弯路就会越少。

c++小知识

1、一般头文件&#xff1a; #include<iostream> using namespace std; 2、ios::sync_with_stdio(false); 其含义是取消cin与stdin的同步&#xff0c;cout和stdout的同步 cin.tie(0); tie是将两个stream绑定的函数&#xff0c;空参数的话返回当前的输出流指针。 3、…

从零开始搭建性能完备的网站-思路过程(1)

之前前端的一揽子技术基本都学完了&#xff0c;除了react和uniapp这些想做大前端需要学的东西&#xff0c;基本vue相关的东西都学过了&#xff0c;本来想做尚硅谷的后台项目&#xff0c;可是它使用的工具库实在是太老了&#xff0c;所以直接跳到自己搭建网站这一步来&#xff0…

尚硅谷大数据技术Zookeeper教程-笔记04【源码解析-源码详解】

视频地址&#xff1a;【尚硅谷】大数据技术之Zookeeper 3.5.7版本教程_哔哩哔哩_bilibili 尚硅谷大数据技术Zookeeper教程-笔记01【Zookeeper(入门、本地安装、集群操作)】尚硅谷大数据技术Zookeeper教程-笔记02【服务器动态上下线监听案例、ZooKeeper分布式锁案例、企业面试真…

C语言标准CRC-32校验函数

C语言标准CRC-32校验函数 CRC-32校验产生4个字节长度的数据校验码&#xff0c;通过计算得到的校验码和获得的校验码比较&#xff0c;用于验证获得的数据的正确性。获得的校验码是随数据绑定获得。 CRC校验原理及标准CRC-8校验函数可参考&#xff1a;C语言标准CRC-8校验函数。…

HTML5 <ol> 标签、HTML5 <object> 标签

HTML5 <ol> 标签 实例 HTML5 <ol>标签用于定义文档中的有序列表。请参考下述示例&#xff1a; 2 个不同的有序列表实例&#xff1a; <ol><li>Coffee</li><li>Tea</li><li>Milk</li> </ol><ol start"50…

低代码平台是否会取代程序员?答案在这里

上图是一张机器人或者自动化系统取代人工的图片&#xff0c;您看了有哪些感想呢&#xff1f; 故事 程序员小张&#xff1a; 刚毕业&#xff0c;参加工作1年左右&#xff0c;日常工作是CRUD 架构师老李&#xff1a; 多个大型项目经验&#xff0c;精通各种屠龙宝术&#xff1b; …

Java 在线编程编译工具上线,直接运行Java代码

前言 大家好&#xff0c;我是小哈~ 周末没出去浪&#xff0c;花了点时间&#xff0c;在我的个人网站上线了一款小工具。啥工具呢&#xff1f;一款可以在线编译 Java 代码并运行输出结果的小工具。 大家都知道&#xff0c;甲骨文刷 Java 版本号非常积极&#xff0c;这不上个月…

【大唐杯学习超快速入门】5G技术原理仿真教学——通信网络认知

这里写目录标题智能通信业务对讲机固定电话电视机wifiPAD扫地机器人手机电信业务号码办理基础业务办理业务选择通信流程模拟增值业务办理工程实践信号塔基站机房传输&核心机房智能通信业务 按照顺序来进行&#xff0c;对讲机&#xff0c;固定电话&#xff0c;电视机&#…

HTTP协议 | 一文详解HTTP报文结构

目录 &#x1f333; HTTP/HTTPS简介 &#x1f333; HTTP工作原理 HTTP三点注意事项 1. HTTP是无连接的 2. HTTP是媒体独立的 3. HTTP是无状态的 HTTPS 作用 &#x1f333; HTTP消息结构 HTTP请求消息 1. 请求行 2. 请求头 3. 空行 4. 请求数据 HTTP请求实例 HTT…