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

news2024/12/26 20:48:44

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 NMS
           augment=False,       
           half=False,         
           hide_labels=False,   
           hide_conf=False,     
           line_thickness=3    
           ):
    ######## zed 初始化 #########
    zed = sl.Camera()
    # 设置相机的分辨率1080和采集帧率30fps
    init_params = sl.InitParameters()
    init_params.camera_resolution = sl.RESOLUTION.HD1080  # Use HD1080 video mode
    init_params.camera_fps = 30  # fps可选:15、30、60、100

    err = 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.names
    colors = [[random.randint(0, 255) for _ in range(3)] for _ in range(len(names))]  
    #toFP16
    if 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=3

            img = img[:, :, ::-1].transpose(2, 0, 1)  #BGR to RGB, to 3x416x416
            img = np.ascontiguousarray(img)  #channel = imgsz

            img = torch.from_numpy(img).to(device)
            #uint8 to fp16/32
            img = img.half() if half else img.float()  

            #0 - 255 to 0.0 - 1.0
            img /= 255.0   #512
            if img.ndimension() == 3:
                img = img.unsqueeze(0)
                # print("shape2",img.shape[2])   #320

            t1 = 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):   #检测框坐标,置信度,类别id
                        xywh = (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 math
            x1, 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:
            break
      
    cv2.destroyAllWindows()

if __name__ == "__main__":

    detect()

5.可视化展示

在这里插入图片描述

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

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

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

相关文章

Apache httpd漏洞复现

文章目录 未知后缀名解析漏洞多后缀名解析漏洞启动环境漏洞复现 换行解析漏洞启动环境漏洞复现 未知后缀名解析漏洞 该漏洞与Apache、php版本无关,属于用户配置不当造成的解析漏洞。在有多个后缀的情况下,只要一个文件含有.php后缀的文件即将被识别成PHP…

微信多开bat代码

目录标题 创建txt文件右键 点击新建文本文档 复制如下代码进去,将里面的微信地址改成自己的微信地址(查看地址方法:右击微信图标->属性->目标)复制如下代码 创建txt文件 右键 点击新建文本文档 复制如下代码进去&#xff0…

Linux系统——MySQL安装(CentOS7 超详细演示)

Linux系统安装MySQL MySQL8.0.26-Linux版安装1. 准备一台Linux服务器2. 下载Linux版MySQL安装包3. 上传MySQL安装包4. 创建目录,并解压5. 安装mysql的安装包6. 启动MySQL服务7. 查询自动生成的root用户密码8. 修改root用户密码9. 创建用户10. 并给root用户分配权限11. 通过Data…

2023高教社杯 国赛数学建模E题思路 - 黄河水沙监测数据分析

1 赛题 E 题 黄河水沙监测数据分析 黄河是中华民族的母亲河。研究黄河水沙通量的变化规律对沿黄流域的环境治理、气候变 化和人民生活的影响, 以及对优化黄河流域水资源分配、协调人地关系、调水调沙、防洪减灾 等方面都具有重要的理论指导意义。 附件 1 给出了位…

willchange 优化性能的原理是什么

写在前面 今天说一下性能优化部分的其中一个点,这个点叫做 willchange,说他的原因主要有以下几个:第一很多人知道用这个可以提高性能但是不知道原因是什么,第二,我们用的时候他虽然可以提高性能,但是不代表…

Revit SDK 介绍:GenericModelCreation常规模型的创建

前言 这个例子介绍了如何创建拉伸、放样、扫掠、融合、放样融合,涵盖了一个建模软件需要的基本建模方法。 内容 CreateExtrusion 生成的放样融合接口: m_creationFamily.NewExtrusion(true, curve, sketchPlane, bottomProfile, topProfile)核心逻辑&…

msvcr100.dll丢失应该怎么解决,比较靠谱的五种解决方法分享

首先,我们需要了解什么是msvcr100.dll。msvcr100.dll是Microsoft Visual C 2010 Redistributable Package的一部分,它包含了一些运行时库,用于支持某些程序的运行。简单来说,msvcr100.dll就是一个“桥梁”,连接了我们的…

组织架构图怎么做?手把手教你绘制完美的组织架构图

组织架构图是企业和组织中不可或缺的工具,它以图形化的方式展示了各级层次的关系,帮助人们更好地理解和管理整体结构。本文将为你详细介绍绘制组织架构图的要素、步骤和技巧,并推荐四款强大的绘图软件,让你轻松绘制完美的组织架构…

无涯教程-JavaScript - DELTA函数

描述 DELTA函数测试两个值是否相等。如果number1 number2,则返回1;否则返回1。否则返回0。 您可以使用此功能来过滤一组值。如,通过合计几个DELTA函数,您可以计算相等对的计数。此功能也称为Kronecker Delta功能。 语法 DELTA (number1, [number2])争论 Argum…

RK3588算法盒子maskrom模式下系统烧录

先在firefly官网下载bulidroot文件,然后进行烧录相关文件。 点击upgrade,进行烧录升级; 等待烧录完成后, 重新开机进入loader模式下, 进行烧录Untunt20.04系统的操作就行。

企业电脑文件加密系统 / 防泄密软件——「天锐绿盾」

「天锐绿盾」是一种公司文件加密系统,旨在保护公司内网数据安全,防止信息泄露。该系统由硬件和软件组成,其中包括服务端程序、控制台程序和终端程序。 PC访问地址: isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c…

python趣味编程-太空入侵者游戏

在 Python 中使用 Turtle 的简单太空入侵者游戏免费源代码 使用 Turtle 的简单太空入侵者游戏是一个用Python编程语言编码的桌面游戏应用程序。该项目包含克隆实际太空入侵者游戏的多种功能。该项目可以使正在学习计算机相关课程的学生受益。该应用程序易于学习,可以帮助您发现…

软件设计师(八)算法设计与分析

算法被公认为是计算机科学的基石,算法理论研究的是算法的设计技术和分析技术。 一、算法设计和分析的基本概念 1、算法 (Algorithm) 算法:是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条…

element树形筛选

<el-inputv-model"projectName"placeholder"请输入名称"clearablemaxlength"10"clear"clearTree" /> <el-divider /> <el-treeref"tree"class"filter-tree":data"treeList":props"…

技术面试与HR面:两者之间的关联与区别

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

华为OD机试 - 二维伞的雨滴效应(Java JS Python)

题目描述 普通的伞在二维平面世界中,左右两侧均有一条边,而两侧伞边最下面各有一个伞坠子,雨滴落到伞面,逐步流到伞坠处,会将伞坠的信息携带并落到地面,随着日积月累,地面会呈现伞坠的信息。 1、为了模拟伞状雨滴效应,用二叉树来模拟二维平面伞(如下图所示),现在输…

波奇学C++:多态

组合和继承 继承是白箱复用(whiter-box-reuse),获得继承类的内部细节 组合是黑盒测试(black-box-reuse),无法得走类的内部实现 class C {// }; //组合 class E { private:C _cc; }; is-a 关系用继承&#xff0c;人-学生&#xff1b;has-a 关系用组合 车-轮胎。 多态&#…

制作精美房地产电子传单的秘诀与技巧揭秘

如果您是一个房地产从业者或者是想要自己制作一个房地产电子传单的小白&#xff0c;那么本文将为您提供一个简单易懂的制作教程。我们将使用乔拓云网在线制作平台来制作这个电子传单。 第一步&#xff0c;登录乔拓云网在线制作平台。在浏览器中输入并打开乔拓云网的官方网站&am…

Cortex-M3如何跳出BusFault,跳过出错代码,程序往下执行

为了方便演示如何实现该方法&#xff0c;采用构造触发BusFault&#xff0c;方便分析 首先需要对系统Handler控制及状态寄存器SHCSR.MEMFAULTENA使能 往SRAM reserved写入数据&#xff0c;触发BusFault 如上图所示&#xff0c;可以看到触发BusFault前BFSR寄存器第7为高&#…

你参与的APP开发项目安全吗?

Android将安全设计贯穿系统架构的各个层面&#xff0c;覆盖系统内核、虚拟机、应用程序框架层以及应用层各个环节&#xff0c;力求在开放的同时&#xff0c;也恰当保护用户的数据、应用程序和设备的安全。Android安全模型主要提供以下几种安全机制&#xff1a; 进程沙箱隔离机…