单目深度估计模型 lite-mono 测试

lite-mono 使用工业数据集kitti 进行训练,目的使用单目摄像头实现物体深度预测,关于kitti数据集的介绍和下载参考


(二)一文带你了解KITTI数据集-CSDN博客文章浏览阅读2.7w次,点赞64次,收藏294次。文章介绍了KITTI数据集的起源、组成、传感器配置和数据结构,包括图像、点云、相机校准和物体标签的详细信息。此外,还阐述了数据预处理步骤、数据集的组织结构和文件解析,以及用于3D目标检测的评价指标。该数据集对于开发和评估自动驾驶场景中的计算机视觉算法至关重要。https://blog.csdn.net/m0_46556474/article/details/130944612

另一篇介绍lite-mono的帖子可以提前看看

CVPR‘2023 | Lite-Mono: 一种新的轻量级自监督单目深度估计方法_litemono内容-CSDN博客文章浏览阅读842次。本文提出了一种新的轻量级单目自监督单目深度估计方法。设计了一种混合的CNN和Transformer架构来建模多尺度增强的局部特征和全局上下文信息。在8个KITTI数据集上的实验结果证明了该方法的优越性。通过在提出的CDC块中设置优化的扩张率,并插入LGFI模块来获得局部-全局特征相关性,Lite-Mono可以感知不同尺度的物体,甚至是对靠近摄像机的移动物体。论文还验证了该模型在Make3D数据集上的泛化能力。此外,Lite-Mono在模型复杂性和推理速度之间实现了良好的权衡。_litemono内容https://blog.csdn.net/CVHub/article/details/130236211

本文主要尝试把模型转化为onnx,  再利用这个单眼深度估计模型Lite-Mono进行推理

权重的下载

wget -O weights/lite-mono_640x192.zip 'https://surfdrive.surf.nl/files/index.php/s/CUjiK221EFLyXDY/download'wget -O weights/lite-mono-small_640x192.zip 'https://surfdrive.surf.nl/files/index.php/s/8cuZNH1CkNtQwxQ/download'wget -O weights/lite-mono-tiny_640x192.zip 'https://surfdrive.surf.nl/files/index.php/s/TFDlF3wYQy0Nhmg/download'wget -O weights/lite-mono-8m_640x192.zip 'https://surfdrive.surf.nl/files/index.php/s/UlkVBi1p99NFWWI/download'wget -O weights/lite-mono_1024x320.zip 'https://surfdrive.surf.nl/files/index.php/s/IK3VtPj6b5FkVnl/download'wget -O weights/lite-mono-small_1024x320.zip 'https://surfdrive.surf.nl/files/index.php/s/w8mvJMkB1dP15pu/download'wget -O weights/lite-mono-tiny_1024x320.zip 'https://surfdrive.surf.nl/files/index.php/s/myxcplTciOkgu5w/download'wget -O weights/lite-mono-8m_1024x320.zip 'https://surfdrive.surf.nl/files/index.php/s/mgonNFAvoEJmMas/download'

解压

unzip weights/lite-mono_640x192.zip -d weights
unzip weights/lite-mono-small_640x192.zip -d weights
unzip weights/lite-mono-tiny_640x192.zip -d weights
unzip weights/lite-mono-8m_640x192.zip -d weightsunzip weights/lite-mono_1024x320.zip -d weights
unzip weights/lite-mono-small_1024x320.zip -d weights
unzip weights/lite-mono-tiny_1024x320.zip -d weights
unzip weights/lite-mono-8m_1024x320.zip -d weights

Lite-Mono 模型加载

import osimport torch
from torchvision import transforms, datasetsimport networksdef load_network(model='lite-mono', load_weights_folder=None, device='cuda'):device = torch.device('cuda')encoder_path = os.path.join(load_weights_folder, 'encoder.pth')decoder_path = os.path.join(load_weights_folder, 'depth.pth')encoder_dict = torch.load(encoder_path)decoder_dict = torch.load(decoder_path)feed_height = encoder_dict['height']feed_width = encoder_dict['width']encoder = networks.LiteMono(model=model,height=feed_height,width=feed_width,)model_dict = encoder.state_dict()encoder.load_state_dict({k: vfor k, v in encoder_dict.items() if k in model_dict})encoder.to(device)encoder.eval()depth_decoder = networks.DepthDecoder(encoder.num_ch_enc, scales=range(3))depth_model_dict = depth_decoder.state_dict()depth_decoder.load_state_dict({k: vfor k, v in decoder_dict.items() if k in depth_model_dict})depth_decoder.to(device)depth_decoder.eval()return encoder, depth_decoder

ONNX 模型变换方法

def convert_to_onnx(input_shape=(640, 192), output_dir='',encoder=None, decoder=None, device='cpu',
):os.makedirs(output_dir, exist_ok=True)# encoderinput_image = torch.randn(1, 3, input_shape[1], input_shape[0]).to(device)input_layer_names = ['input_image']output_layer_names = ['features']torch.onnx.export(encoder, input_image,file_name + '/encoder.onnx', verbose=True,input_names=input_layer_names,output_names=output_layer_names,do_constant_folding=False,opset_version=13,)# decoderencoder_results = encoder(input_image)features = []features.append(torch.randn(*list(encoder_results[0].shape)).to(device))features.append(torch.randn(*list(encoder_results[1].shape)).to(device))features.append(torch.randn(*list(encoder_results[2].shape)).to(device))input_layer_names = ['features_1', 'features_2', 'features_3']output_layer_names = ['depth']torch.onnx.export(decoder, features,file_name + '/decoder.onnx', verbose=True,input_names=input_layer_names,output_names=output_layer_names,do_constant_folding=False,opset_version=13,)

onnx格式变换

file_name = 'lite-mono_640x192'
input_shape = (640, 192)
model='lite-mono'load_weights_folder = 'weights/' + file_name
encoder, decoder = load_network(model, load_weights_folder)convert_to_onnx(input_shape=input_shape, output_dir=file_name, encoder=encoder, decoder=decoder, device='cuda:0',
)file_name = 'lite-mono-small_640x192'
input_shape = (640, 192)
model='lite-mono-small'load_weights_folder = 'weights/' + file_name
encoder, decoder = load_network(model, load_weights_folder)convert_to_onnx(input_shape=input_shape, output_dir=file_name, encoder=encoder, decoder=decoder, device='cuda:0',
)file_name = 'lite-mono-tiny_640x192'
input_shape = (640, 192)
model='lite-mono-tiny'load_weights_folder = 'weights/' + file_name
encoder, decoder = load_network(model, load_weights_folder)convert_to_onnx(input_shape=input_shape, output_dir=file_name, encoder=encoder, decoder=decoder, device='cuda:0',
)file_name = 'lite-mono-8m_640x192'
input_shape = (640, 192)
model='lite-mono-8m'load_weights_folder = 'weights/' + file_name
encoder, decoder = load_network(model, load_weights_folder)convert_to_onnx(input_shape=input_shape, output_dir=file_name, encoder=encoder, decoder=decoder, device='cuda:0',
)file_name = 'lite-mono_1024x320'
input_shape = (1024, 320)
model='lite-mono'load_weights_folder = 'weights/' + file_name
encoder, decoder = load_network(model, load_weights_folder)convert_to_onnx(input_shape=input_shape, output_dir=file_name, encoder=encoder, decoder=decoder, device='cuda:0',
)file_name = 'lite-mono-small_1024x320'
input_shape = (1024, 320)
model='lite-mono-small'load_weights_folder = 'weights/' + file_name
encoder, decoder = load_network(model, load_weights_folder)convert_to_onnx(input_shape=input_shape, output_dir=file_name, encoder=encoder, decoder=decoder, device='cuda:0',
)file_name = 'lite-mono-tiny_1024x320'
input_shape = (1024, 320)
model='lite-mono-tiny'load_weights_folder = 'weights/' + file_name
encoder, decoder = load_network(model, load_weights_folder)convert_to_onnx(input_shape=input_shape, output_dir=file_name, encoder=encoder, decoder=decoder, device='cuda:0',
)file_name = 'lite-mono-8m_1024x320'
input_shape = (1024, 320)
model='lite-mono-8m'load_weights_folder = 'weights/' + file_name
encoder, decoder = load_network(model, load_weights_folder)convert_to_onnx(input_shape=input_shape, output_dir=file_name, encoder=encoder, decoder=decoder, device='cuda:0',
)

使用onnx进行推理

  • 视频捕获:首先初始化视频捕获设备。
  • 模型加载:加载编码器和解码器的 ONNX 模型。
  • 主循环:在无限循环中读取视频帧,进行推理,处理输出图像,直到按下 ESC 键。
  • 资源释放:在结束时释放视频捕获资源并关闭所有窗口。

需要以下库

os:用于文件和路径操作。
copy:用于深拷贝对象。
time:用于时间测量。
argparse:用于处理命令行参数。
cv2:OpenCV库,用于图像处理。
numpy:用于处理数组和矩阵。
onnxruntime:用于运行 ONNX 模型。

def run_inference(encoder, decoder, image):

  • 输入:编码器和解码器模型,以及输入图像。
  • 处理
    • 预处理:调整图像大小、颜色空间转换、转置和归一化。
    • 推理:将处理后的图像输入编码器和解码器,生成深度图。
    • 后处理:归一化深度图并转换为 uint8 格式。

def main():

  • 解析命令行参数:包括设备编号、视频文件路径和模型路径。
  • 视频捕获:使用 OpenCV 从指定设备或视频文件读取帧。
  • 加载模型:使用 ONNX Runtime 加载编码器和解码器模型。
  • 循环处理
    • 捕获视频帧,进行深度推理,并绘制调试信息。
    • 显示输入和输出图像。

def draw_debug(image, elapsed_time, depth_map):

  • 输入:原始图像、推理耗时和深度图。
  • 处理
    • 使用 cv.applyColorMap 为深度图应用色彩映射。
    • 在调试图像上显示推理耗时。

完整代码如下

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import copy
import time
import argparseimport cv2 as cv
import numpy as np
import onnxruntimedef run_inference(encoder, decoder, image):# ONNX Input Sizeinput_size = encoder.get_inputs()[0].shapeinput_width = input_size[3]input_height = input_size[2]# Pre process:Resize, BGR->RGB, Transpose, float32 castinput_image = cv.resize(image, dsize=(input_width, input_height))input_image = cv.cvtColor(input_image, cv.COLOR_BGR2RGB)input_image = input_image.transpose(2, 0, 1)input_image = np.expand_dims(input_image, axis=0)input_image = input_image.astype('float32')input_image = input_image / 255.0# Inferenceinput_name = encoder.get_inputs()[0].namefeatures = encoder.run(None, {input_name: input_image})input_name_01 = decoder.get_inputs()[0].nameinput_name_02 = decoder.get_inputs()[1].nameinput_name_03 = decoder.get_inputs()[2].namedepth_map = decoder.run(None,{input_name_01: features[0],input_name_02: features[1],input_name_03: features[2]},)# Post processdepth_map = np.squeeze(depth_map[0])d_min = np.min(depth_map)d_max = np.max(depth_map)depth_map = (depth_map - d_min) / (d_max - d_min)depth_map = depth_map * 255.0depth_map = np.asarray(depth_map, dtype="uint8")return depth_mapdef main():parser = argparse.ArgumentParser()parser.add_argument("--device", type=int, default=0)parser.add_argument("--movie", type=str, default=None)parser.add_argument("--model",type=str,default='model/lite-mono-tiny_640x192',)args = parser.parse_args()model_dir = args.modelencoder_path = os.path.join(model_dir, 'encoder.onnx')decoder_path = os.path.join(model_dir, 'decoder.onnx')# Initialize video capturecap_device = args.deviceif args.movie is not None:cap_device = args.moviecap = cv.VideoCapture(cap_device)# Load modelencoder = onnxruntime.InferenceSession(encoder_path,providers=['CUDAExecutionProvider','CPUExecutionProvider',],)decoder = onnxruntime.InferenceSession(decoder_path,providers=['CUDAExecutionProvider','CPUExecutionProvider',],)while True:start_time = time.time()# Capture readret, frame = cap.read()if not ret:breakdebug_image = copy.deepcopy(frame)# Inference executiondepth_map = run_inference(encoder,decoder,frame,)elapsed_time = time.time() - start_time# Drawdebug_image, depth_image = draw_debug(debug_image,elapsed_time,depth_map,)key = cv.waitKey(1)if key == 27:  # ESCbreakcv.imshow('Input', debug_image)cv.imshow('Output', depth_image)cap.release()cv.destroyAllWindows()def draw_debug(image, elapsed_time, depth_map):image_width, image_height = image.shape[1], image.shape[0]debug_image = copy.deepcopy(image)# Apply ColorMapdepth_image = cv.applyColorMap(depth_map, cv.COLORMAP_JET)depth_image = cv.resize(depth_image, dsize=(image_width, image_height))# Inference elapsed timecv.putText(debug_image,"Elapsed Time : " + '{:.1f}'.format(elapsed_time * 1000) + "ms",(10, 40), cv.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2,cv.LINE_AA)return debug_image, depth_image

window下启动测试main会有报错

cv2.error: OpenCV(4.10.0) D:\a\opencv-python\opencv-python\opencv\modules\highgui\src\window.cpp:1301: error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Cocoa support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function 'cvShowImage'

解决方法参考

https://stackoverflow.com/questions/67120450/error-2unspecified-error-the-function-is-not-implemented-rebuild-the-libraicon-default.png?t=O83Ahttps://stackoverflow.com/questions/67120450/error-2unspecified-error-the-function-is-not-implemented-rebuild-the-libra

安装下面模块

pip install opencv-contrib-python 

使用一个行车记录仪视频进行测试

2905c3d871374931af52209aecc7b83d.gif

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

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

相关文章

.Net 多线程、异步、性能优化应用与心得

文章目录 概要多线程Thread方式创建线程:Task方式创建线程[C#5.0引入]&#xff08;推荐使用&#xff09;:线程池方式创建线程&#xff1a; 异步异步方法异步IO操作异步数据库操作异步Web请求取消异步ValueTask[C# 7.0引入]ValueTask<TResult> 和 Task 性能优化懒加载对象…

qt-C++语法笔记之mapToGlobal将组件(控件)中的本地坐标系(局部坐标)映射到全局坐标系

qt-C语法笔记之mapToGlobal将组件&#xff08;控件&#xff09;中的本地坐标系&#xff08;局部坐标&#xff09;映射到全局坐标系 code review! 文章目录 qt-C语法笔记之mapToGlobal将组件&#xff08;控件&#xff09;中的本地坐标系&#xff08;局部坐标&#xff09;映射到…

python爬虫--小白篇【爬取B站视频】

目录 一、任务分析 二、网页分析 三、任务实现 一、任务分析 将B站视频爬取并保存到本地&#xff0c;经过分析可知可以分为四个步骤&#xff0c;分别是&#xff1a; 爬取视频页的网页源代码&#xff1b;提取视频和音频的播放地址&#xff1b;下载并保存视频和音频&#x…

UniScene:Video、LiDAR 和Occupancy全面SOTA

论文: https://arxiv.org/pdf/2412.05435 项目页面&#xff1a;https://arlo0o.github.io/uniscene/ 0. 摘要 生成高保真度、可控制且带有标注的训练数据对于自动驾驶至关重要。现有方法通常直接从粗糙的场景布局生成单一形式的数据&#xff0c;这不仅无法输出多样化下游任务…

Ubuntu22.04搭建FTP服务器保姆级教程

在网络环境中&#xff0c;文件传输是一项至关重要的任务。FTP&#xff08;文件传输协议&#xff09;是一种基于客户端/服务器模式的协议&#xff0c;广泛用于在互联网上传输文件。Ubuntu作为一款流行的Linux发行版&#xff0c;因其稳定性和易用性而广受开发者和系统管理员的喜爱…

【银河麒麟高级服务器操作系统】修改容器中journal服务日志存储位置无效—分析及解决方案

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 服务器环境以及配置 【机型】 整机类型/架构&am…

React 第十六节 useCallback 使用详解注意事项

useCallback 概述 1、useCallback 是在React 中多次渲染缓存函数的 Hook&#xff0c;返回一个函数的 memoized的值&#xff1b; 2、如果多次传入的依赖项不变&#xff0c;那么多次定义的时候&#xff0c;返回的值是相同的,防止频繁触发更新&#xff1b; 3、多应用在 父组件为函…

二十七、Tomcat专题总结与拓展

文章目录 一、Tomcat设计思路总结1、Tomcat整体架构2、Tomcat设计思路 二、Tomcat源码设计精髓三、拓展&#xff1a;SpringBoot整合Tomcat源码分析四、拓展&#xff1a;SpringBoot整合Undertow实战1、Undertow概述2、SpringBoot集成Undertow2.1、引入依赖2.2、application.prop…

[游戏开发] Unity中使用FlatBuffer

什么是FlatBuffer 官网&#xff1a; GitHub - google/flatbuffers: FlatBuffers: Memory Efficient Serialization LibraryFlatBuffers: Memory Efficient Serialization Library - google/flatbuffershttps://github.com/google/flatbuffers 为什么用FloatBuffer&#xff0c…

【JAVA】旅游行业中大数据的使用

一、应用场景 数据采集与整合&#xff1a;全面收集旅游数据&#xff0c;如客流量、游客满意度等&#xff0c;整合形成统一数据集&#xff0c;为后续分析提供便利。 舆情监测与分析&#xff1a;实时监测旅游目的地的舆情信息&#xff0c;运用NLP算法进行智能处理&#xff0c;及…

android studio创建虚拟机注意事项

emulator 启动模拟器的时候&#xff0c;可以用 AVD 界面&#xff0c;也可以用命令行启动&#xff0c;但命令行启 动的时候要注意&#xff0c;系统有两个 emulator.exe &#xff0c;建议使用 emulator 目录下的那个&#xff01;&#xff01; 创建类型为google APIs的虚拟机可从…

全面解析租赁小程序的功能与优势

内容概要 租赁小程序正在逐渐改变人与物之间的互动方式。通过这些小程序&#xff0c;用户不仅可以轻松找到所需的租赁商品&#xff0c;还能够享受无缝的操作体验。为了给大家一个清晰的了解&#xff0c;下面我们将重点介绍几个核心功能。 建议&#xff1a;在选择租赁小程序时&…

JCR一区牛顿-拉夫逊优化算法+分解对比!VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测

JCR一区牛顿-拉夫逊优化算法分解对比&#xff01;VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测 目录 JCR一区牛顿-拉夫逊优化算法分解对比&#xff01;VMD-NRBO-Transformer-BiLSTM多变量时序光伏功率预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.中科院…

用二维图像渲染3D场景视频

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

每日一练:链表-重排链表

LCR 026. 重排链表 - 力扣&#xff08;LeetCode&#xff09; 题目要求&#xff1a; 给定一个单链表 L 的头节点 head &#xff0c;单链表 L 表示为&#xff1a; L0 → L1 → … → Ln-1 → Ln 请将其重新排列后变为&#xff1a; L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → ……

国产物联网平台(IotSharp+IoTGateway+Influxdb)快速上手

环境说明&#xff1a; Visual Studio 2022 CommunityIotSharp代码&#xff1a;https://github.com/IoTSharp/IoTSharp.gitIoTGateway版本&#xff1a;v2.1.1Node版本&#xff1a;v20.18.1Influxdb版本&#xff1a;v2.7.11 安装Node Node.js官网 官网下载并安装&#xff0c;…

每日一刷——二叉树的构建——12.12

第一题&#xff1a;最大二叉树 题目描述&#xff1a;654. 最大二叉树 - 力扣&#xff08;LeetCode&#xff09; 我的想法&#xff1a; 我感觉这个题目最开始大家都能想到的暴力做法就是遍历找到数组中的最大值&#xff0c;然后再遍历一遍&#xff0c;把在它左边的依次找到最大…

Redis篇-6--原理篇5--单线程模型

1、概述 Redis 采用单线程模型来处理客户端请求&#xff0c;这意味着在任意时刻只有一个命令被执行。这种设计简化了 Redis 的实现&#xff0c;并确保了高并发环境下的数据一致性。尽管 Redis 是单线程的&#xff0c;但它通过高效的内存管理和网络 I/O 操作&#xff0c;仍然能…

【问题记录】07 MAC电脑,使用FileZilla(SFTP)连接堡垒机不成功

项目场景&#xff1a; 使用MAC电脑&#xff0c;以子账号&#xff08;非root&#xff09;的形式登录&#xff0c;连接堡垒机CLB&#xff08;传统型负载均衡&#xff09;&#xff0c;使用FileZilla&#xff08;SFTP&#xff09;进行FTP文件传输。 问题描述&#xff1a; MAC电脑…

Linux下进程替换exec系列接口

文章目录 Linux下进程替换1. c库exec函数族一、exec函数族简介二、exec函数族函数原型及参数说明三、exec函数族的工作机制四、注意事项五、示例代码 2. 系统调用execve接口一、execve接口与C库exec函数族的关系二、函数原型三、参数说明四、工作原理五、返回值六、注意事项七、…