深度学习(十一)---zed 调用yolov5 进行识别目标并实时测距

1. 前言

zed 相机测距有2种方式:一种是根据点云数据进行测试,二是根据zed获取深度值进行测距。上篇文章 调用yolov5模型进行实时图像推理及网页端部署 我们讲述了zed调用yolov5进行目标识别,我们在此基础上进一步实现目标测距功能。

2.深度图和点云图的区别:

(1)深度图像也叫距离影像,是指将从图像采集器到场景中各点的距离(深度)值作为像素值的图像。深度D等于像素在该视图相机坐标系下Z坐标。获取方法有:激光雷达深度成像法、计算机立体视觉成像、坐标测量机法、莫尔条纹法、结构光法。

(2)点云:当一束激光照射到物体表面时,所反射的激光会携带方位、距离等信息。通过深度相机得到的物体外观表面的点数据集合是点云。使用深度相机得到的点云信息为三维坐标(X,Y,Z)。点云格式有*.las ;*.pcd; *.txt等。

(3)深度数据流所提供的图像帧中,每一个像素点代表的是在深度感应器的视野中,该特定的(x, y)坐标处物体到离摄像头平面最近的物体到该平面的距离(以毫米为单位)。

(4)深度图像经过坐标转换可以计算为点云数据;有规则及必要信息的点云数据可以反算为深度图像。

(5)视差图是立体匹配算法的产出,而深度图则是立体匹配到点云生成的中间桥梁。

简而言之,点云可以看作是三维的深度图。深度图只包含每个像素的距离或Z信息,而点云包含物体表面的3D点(X,Y, Z)的集合,可以包含颜色信息。

3.测距原理

(1)基于点云三维测距

基于点云的三维测距,首先获取目标物体(x,y)的点云值,然后利用欧几里得公式进行求解

point_cloud = sl.Mat()
zed.retrieve_measure(point_cloud, sl.MEASURE.XYZRGBA, sl.MEM.CPU)
s, point_cloud_value = point_cloud.get_value((x2+x1)/2, (y2+y1)/2)
或者: 
point_cloud_value = point_cloud.get_value((x2+x1)/2, (y2+y1)/2)[1]
# print("point_cloud_value",point_cloud_value) -->输出:-->(SUCCESS, array([....]))
distance = math.sqrt(point_cloud_value[0] * point_cloud_value[0] + point_cloud_value[1] * point_cloud_value[1] + point_cloud_value[2] * point_cloud_value[2])

(2)基于深度值测距

使用深度值进行测距,可以直接得出距离值

depth = sl.Mat()
zed.retrieve_measure(depth, sl.MEASURE.DEPTH, sl.MEM.CPU)
s,depth_value = depth.get_value((x2+x1)/2, (y2+y1)/2)  -->输出:(SUCCESS, ...)
或者:
depth_value = depth.get_value((x2+x1)/2, (y2+y1)/2)[1]

4.完整代码实现

import time
import cv2
import numpy as np
import torch
from models.experimental import attempt_load
from utils.datasets import letterbox
from utils.general import check_img_size, non_max_suppression,scale_coords, xyxy2xywh,set_logging,plot_one_box
# from utils.plots import colors, plot_one_box
from utils.torch_utils import select_device,time_synchronized
from numpy import random
import pyzed.sl as sl@torch.no_grad()
def detect(weights='weights/yolov5s.pt', imgsz=512,           cap = 0,             conf_thres=0.25,    iou_thres=0.45,      max_det=1000,        device='',           crop=True,           classes=None,        agnostic_nms=False,  #class-agnostic NMSaugment=False,       half=False,         hide_labels=False,   hide_conf=False,     line_thickness=3    ):######## zed 初始化 #########zed = sl.Camera()# 设置相机的分辨率1080和采集帧率30fpsinit_params = sl.InitParameters()init_params.camera_resolution = sl.RESOLUTION.HD1080  # Use HD1080 video modeinit_params.camera_fps = 30  # fps可选:15、30、60、100err = zed.open(init_params)  # 根据自定义参数打开相机if err != sl.ERROR_CODE.SUCCESS:exit(1)runtime_parameters = sl.RuntimeParameters()  # 设置相机获取参数runtime_parameters.sensing_mode = sl.SENSING_MODE.STANDARD  # 创建sl.Mat对象来存储图像(容器),Mat类可以处理1到4个通道的多种矩阵格式(定义储存图象的类型)image = sl.Mat()  # 图像point_cloud = sl.Mat() #点云depth = sl.Mat()  #深度# # 获取分辨率# resolution = zed.get_camera_information().camera_resolution# w, h = resolution.width , resolution.height# x,y = int(w/2),int(h/2)  # 中心点########### 图像预处理 ##########device = select_device(device)print("device", device)half &= device.type != 'cpu'  model = attempt_load(weights, map_location=device)  stride = int(model.stride.max())  imgsz = check_img_size(imgsz, s=stride)  names = model.module.names if hasattr(model, 'module') else model.namescolors = [[random.randint(0, 255) for _ in range(3)] for _ in range(len(names))]  #toFP16if half:model.half()  if device.type != 'cpu':model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters()))) while True:### zed捕获图像 #####if zed.grab(runtime_parameters) == sl.ERROR_CODE.SUCCESS:  #相机成功获取图象# 获取图像timestamp = zed.get_timestamp(sl.TIME_REFERENCE.CURRENT)  #获取图像被捕获时的时间戳(ms)zed.retrieve_image(image, sl.VIEW.LEFT)  # image:容器,sl.VIEW.LEFT:内容 ,左镜头view = image.get_data()  # 转换成图像数组,便于后续的显示或者储存# 显示彩色图# img0 = cv2.resize(view,(384,384))im = view[:, :, 0:3]#### 图像推理,目标识别 ############labels = []t0 = time.time()img = letterbox(im, imgsz)[0]  #channel=3img = img[:, :, ::-1].transpose(2, 0, 1)  #BGR to RGB, to 3x416x416img = np.ascontiguousarray(img)  #channel = imgszimg = torch.from_numpy(img).to(device)#uint8 to fp16/32img = img.half() if half else img.float()  #0 - 255 to 0.0 - 1.0img /= 255.0   #512if img.ndimension() == 3:img = img.unsqueeze(0)# print("shape2",img.shape[2])   #320t1 = time_synchronized()pred = model(img, augment=False)[0]pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms)t2 = time_synchronized()for i, det in enumerate(pred):  #s, im0 = '', im.copy()s += '%gx%g ' % img.shape[2:]  gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  if det is not None and len(det):det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()for c in det[:, -1].unique():n = (det[:, -1] == c).sum()s += f"{n} {names[int(c)]}{'s' * (n > 1)}, "  for *xyxy, conf, cls in reversed(det):   #检测框坐标,置信度,类别idxywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()  line = (cls, *xywh, conf)  c = int(cls)  #names[c] 获取类别名称label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')if crop:    plot_one_box(xyxy, im0, label=label, color=colors[int(c)], line_thickness=line_thickness)labels.append([names[c],conf,xyxy])###### 点云测距 #########import mathx1, y1 = int(xyxy[0]), int(xyxy[1])x2, y2 = int(xyxy[2]), int(xyxy[3])zed.retrieve_measure(point_cloud, sl.MEASURE.XYZRGBA, sl.MEM.CPU)s, point_cloud_value = point_cloud.get_value((x2+x1)/2, (y2+y1)/2)# print("point_cloud_value",point_cloud_value)distance = math.sqrt(point_cloud_value[0] * point_cloud_value[0] + point_cloud_value[1] * point_cloud_value[1] +point_cloud_value[2] * point_cloud_value[2])cv2.circle(im0, (int((x2+x1)/2), int((y2+y1)/2)), 5, [0, 0, 255], 5) #画出目标中心点               cv2.putText(im0, "Distance: " + str(round(distance / 1000, 2)) + 'm', (int(xyxy[0]), int(xyxy[3] + 25)),cv2.FONT_HERSHEY_COMPLEX, 1, colors[int(c)], 2) #标出点云距离mm-->m##### 求解深度距离 ##########zed.retrieve_measure(depth, sl.MEASURE.DEPTH, sl.MEM.CPU)s1,depth_value = depth.get_value((x2+x1)/2, (y2+y1)/2)cv2.putText(im0, "depth_value: " + str(round(depth_value /1000, 2)) + 'm', (int(xyxy[0]), int(xyxy[3] + 75)),cv2.FONT_HERSHEY_COMPLEX, 1, colors[int(c)], 2)  #标出深度值# print("depth_value",depth_value)print(f'time: ({time.time() - t0:.3f}s)')cv2.namedWindow('666',cv2.WINDOW_NORMAL)cv2.resizeWindow('666',800,600)cv2.imshow("666",im0)key = cv2.waitKey(20)  if key == 27:breakcv2.destroyAllWindows()if __name__ == "__main__":detect()

5.可视化展示

在这里插入图片描述

由此可以看出深度测距和点云测距存在一定误差,一般使用点云测距会更精准些。

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

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

相关文章

数据分析因子评分学习

当多个因素影响一个结果时,我们需要综合考虑这些因素分别对结果德影响。因子评分就是用于比较其对结果德影响程度。 文章目录 前言一、案例背景二、解决方案(一)分析思路(二)剔除无关数据(三)求…

ac7260网卡不能连5g

之前路由器是双频,最近为了连物联网一堆,把双频拆成两个wifi 结果电脑上装的pdd网卡就罢工了,连4g可以,但是连5g网络就不行,连上却没网,导致网盘下东西慢。刚开始以为是tplink的易展问题,结果看…

CSS中如何实现元素的旋转和缩放效果?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 元素的旋转和缩放效果⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、刚刚踏…

element ui 表格组件与分页组件的二次封装

目录 效果图 组件封装 parseTime函数 debounce 函数 页面使用 【扩展】vue 函数式组件 函数式组件特点: 函数式组件的优点: 【扩展】vue中的render函数 一、初步认识render函数 二、为什么使用render函数 三、render函数的解析 【扩展】添加…

HDFS文件删除后,HIVE元数据还存在的问题

一.背景 手动在hdfs上删除了一个表的分区数据(inc_day2023-08-30),当查询这个表这个分区的数据时报错文件不存在 二.原因 即HDFS数据删除了,但是hive metastore元数据却没有更新,使用show partitions tablename 发现该分区还存在 三.解决办法…

【 Tkinter界面-练习04】 画板作画详细揭示

一、说明 对画布的掌握分三个部分,将图形paint到画布、动画move、鼠标画;本篇将侧重于鼠标画的功能,提起鼠标画实现,将涉及一系列组合操作才能完成,这里将一一加以介绍。 Canvas 小部件具有大量功能,我们不…

C++提高篇:深入理解纯虚函数和抽象类

在C中,纯虚函数和抽象类是面向对象编程中重要的概念。本文将会深入探讨这两个概念的含义、如何定义和使用它们,以及它们在实际开发中的应用。 一、什么是纯虚函数? 在C中,纯虚函数是指在基类中声明但没有实现的虚函数。纯虚函数的…

2023全国大学生数学建模ABCDE选题建议,思路模型,小白要怎么选?难度怎么样

首先最重要的&#xff0c;难度C<B<A&#xff0c;D、E题推荐选E题 大家可以查看我们的视频讲解&#xff0c;在这里&#xff1a;【2023全国大学生数学建模竞赛选题建议&#xff0c;难度分析&#xff0c;小白应该怎么选】 https://b23.tv/S6O26uc 选题建议视频播放​b23.t…

设备管理系统有什么功能?它有什么用?

设备管理系统已成为现代化大规模研究所&#xff0c;信息化管理体系建设中最为关键的要素。随着工业设备的机械化、自动化、大型化、高速化以及复杂化等因素不断叠加&#xff0c;设备设施对于工业生产的作用和影响越来越大&#xff0c;其各项制度和流程也涉及面广、内容繁杂。  …

私有化部署即时通讯平台,完美替代飞书和钉钉的SaaS系统

在当今快速发展的数字化时代&#xff0c;企业对于安全、灵活、可定制的即时通讯平台需求不断增长。作为一家领先的品牌&#xff0c;WorkPlus专注于提供私有化部署的即时通讯平台&#xff0c;完美替代飞书和钉钉的SaaS系统。本文将重点介绍WorkPlus如何通过创新的解决方案&#…

系统学习Linux-PXE无人值守装机(附改密)

目录 pxe实现系统自动安装pxe工作原理 大致的工作过程如下&#xff1a; PXE的组件&#xff1a; 一、配置vsftpd 二、配置tftp 三、准备pxelinx.0文件、引导文件、内核文件 四、配置dhcp 配置ip 配置dhcp 五、创建default文件 六、新建测试主机用来测试装机效果 七、…

2023 年高教社杯全国大学生数学建模竞赛-E 题 黄河水沙监测数据分析详解+思路+Python代码

2023 年高教社杯全国大学生数学建模竞赛-E 题 黄河水沙监测数据分析 十分激动啊啊啊题目终于出来了&#xff01;&#xff01;官网6点就进去了结果直接卡死现在才拿到题目&#xff0c;我是打算A-E题全部做一遍。简单介绍一下我自己&#xff1a;博主专注建模四年&#xff0c;参与…

STC单片机+EC11编码器实现调节PWM输出占空比

STC单片机+EC11编码器实现调节PWM输出占空比 📌相关篇《stc单片机外部中断+EC11编码器实现计数功能》 📍《STC15单片机特有的PWM寄存器和普通定时器实现PWM输出》 🎬效果演示: 🌼 通过逻辑分析仪获取P11引脚上的信号波形,查看其对应输出的占空比。 ✨本例程基于上面两…

复制粘贴是怎么实现的

在上面的代码中&#xff0c;command 和 select 是自定义的函数。它们的作用如下&#xff1a; 实现复制粘贴的思路&#xff1a; 创建一个 textarea 标签将 textarea 移出可视区域给这个 textarea 赋值将这个 textarea 标签添加到页面中调用 textarea 的 select 方法调用 docum…

(c++)类和对象 上篇

目录 1.面向过程和面向对象初步认识 2.类的引入 3.类的定义 4.类的访问限定符及封装 5.类的作用域 6.类的实例化 7.类的对象大小的计算 8.类成员函数的this指针 1.面向过程和面向对象初步认识 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步…

外滩大会今日开幕 近20位“两院”院士、诺贝尔奖和图灵奖得主齐聚

2023 Inclusion外滩大会9月7日在上海黄浦世博园正式开幕。这场以“科技创造可持续未来”为主题的大会为期三天&#xff0c;近20位“两院”院士、诺贝尔奖和图灵奖得主&#xff0c;全球超500位有影响力的科技领军企业和专家学者&#xff0c;将在此带来一场科技、人文和产业的思想…

Linux下go环境安装、环境配置并执行第一个go程序

一、安装 1.Golang对Linux的内核版本要求 GO对Linux内核版本最低要求是 2.6.23&#xff0c;对应要求操作系统版本是&#xff1a; RHEL 6.0CentOS 6.0即&#xff0c;不支持 (RHEL 和 CentOS) 的 (4.x or 5.x)。2.下载golang的代码版本 Golang的官网下载地址&#xff1a;https:…

Vue2+Vue3基础入门到实战项目(七)——智慧商城项目

Vue 核心技术与实战 智慧商城 接口文档&#xff1a;https://apifox.com/apidoc/shared-12ab6b18-adc2-444c-ad11-0e60f5693f66/doc-2221080 演示地址&#xff1a;http://cba.itlike.com/public/mweb/#/ 01. 项目功能演示 1.明确功能模块 启动准备好的代码&#xff0c;演示…

Unity 之 利用数组来管理资源

文章目录 在Unity中&#xff0c;资源数组&#xff08;Resource Arrays&#xff09;不是Unity的标准概念。然而&#xff0c;您可能在特定上下文中使用数组来管理资源或游戏对象。我将解释如何在Unity中使用数组来管理资源。 资源管理&#xff1a; 在Unity中&#xff0c;资源通常…

React Hook之useContext

1. 什么是useContext React官方解释&#xff1a;useContext 是一个 React Hook&#xff0c;可以让你读取和订阅组件中的 context&#xff08;React官方文档地址&#xff09;。 通俗的讲&#xff0c;useContext的作用就是&#xff1a;实现组件间的状态共享&#xff0c;主要应用场…