yolov8+zed 实现三维测距(版本一)

相关链接
此项目直接调用zed相机实现三维测距,无需标定,相关内容如下:
1. yolov4直接调用zed相机实现三维测距
2.yolov5直接调用zed相机实现三维测距(python)
3. yolov7直接调用zed相机实现三维测距(python)
4. yolov9直接调用zed相机实现三维测距(python)
5. Windows+YOLOV8环境配置
6.具体实现效果已在哔哩哔哩发布,点击此链接跳转

本篇博文工程源码下载见文章末尾(麻烦github给个星星)

1. 相关配置

python==3.7
Windows-pycharm
zed api 具体配置见 (zed api 配置步骤)

由于我电脑之前python版本为3.7,yolov8要求python最低为3.8,所以本次实验直接在虚拟环境里进行,未配置gpu,可能看着卡卡的,有需要的可以配置一下,原理是一样的

2. 版本一

2.1 相关代码

主代码 zed-yolo.py,具体放置在yolov8主目录下,盒子形式展现,可实现测距+跟踪

#!/usr/bin/env python3

import sys
import numpy as np

import argparse
import torch
import cv2
import pyzed.sl as sl
from ultralytics import YOLO

from threading import Lock, Thread
from time import sleep

import ogl_viewer.viewer as gl
import cv_viewer.tracking_viewer as cv_viewer

lock = Lock()
run_signal = False
exit_signal = False


def xywh2abcd(xywh, im_shape):
    output = np.zeros((4, 2))

    # Center / Width / Height -> BBox corners coordinates
    x_min = (xywh[0] - 0.5*xywh[2]) #* im_shape[1]
    x_max = (xywh[0] + 0.5*xywh[2]) #* im_shape[1]
    y_min = (xywh[1] - 0.5*xywh[3]) #* im_shape[0]
    y_max = (xywh[1] + 0.5*xywh[3]) #* im_shape[0]

    # A ------ B
    # | Object |
    # D ------ C

    output[0][0] = x_min
    output[0][1] = y_min

    output[1][0] = x_max
    output[1][1] = y_min

    output[2][0] = x_max
    output[2][1] = y_max

    output[3][0] = x_min
    output[3][1] = y_max
    return output

def detections_to_custom_box(detections, im0):
    output = []
    for i, det in enumerate(detections):
        xywh = det.xywh[0]

        # Creating ingestable objects for the ZED SDK
        obj = sl.CustomBoxObjectData()
        obj.bounding_box_2d = xywh2abcd(xywh, im0.shape)
        obj.label = det.cls
        obj.probability = det.conf
        obj.is_grounded = False
        output.append(obj)
    return output


def torch_thread(weights, img_size, conf_thres=0.2, iou_thres=0.45):
    global image_net, exit_signal, run_signal, detections

    print("Intializing Network...")

    model = YOLO(weights)

    while not exit_signal:
        if run_signal:
            lock.acquire()

            img = cv2.cvtColor(image_net, cv2.COLOR_BGRA2RGB)
            # https://docs.ultralytics.com/modes/predict/#video-suffixes
            det = model.predict(img, save=False, imgsz=img_size, conf=conf_thres, iou=iou_thres)[0].cpu().numpy().boxes

            # ZED CustomBox format (with inverse letterboxing tf applied)
            detections = detections_to_custom_box(det, image_net)
            lock.release()
            run_signal = False
        sleep(0.01)


def main():
    global image_net, exit_signal, run_signal, detections

    capture_thread = Thread(target=torch_thread, kwargs={'weights': opt.weights, 'img_size': opt.img_size, "conf_thres": opt.conf_thres})
    capture_thread.start()

    print("Initializing Camera...")

    zed = sl.Camera()

    input_type = sl.InputType()
    if opt.svo is not None:
        input_type.set_from_svo_file(opt.svo)

    # Create a InitParameters object and set configuration parameters
    init_params = sl.InitParameters(input_t=input_type, svo_real_time_mode=True)
    init_params.coordinate_units = sl.UNIT.METER
    init_params.depth_mode = sl.DEPTH_MODE.ULTRA  # QUALITY
    init_params.coordinate_system = sl.COORDINATE_SYSTEM.RIGHT_HANDED_Y_UP
    init_params.depth_maximum_distance = 50

    runtime_params = sl.RuntimeParameters()
    status = zed.open(init_params)

    if status != sl.ERROR_CODE.SUCCESS:
        print(repr(status))
        exit()

    image_left_tmp = sl.Mat()

    print("Initialized Camera")

    positional_tracking_parameters = sl.PositionalTrackingParameters()
    # If the camera is static, uncomment the following line to have better performances and boxes sticked to the ground.
    # positional_tracking_parameters.set_as_static = True
    zed.enable_positional_tracking(positional_tracking_parameters)

    obj_param = sl.ObjectDetectionParameters()
#    obj_param.detection_model = sl.OBJECT_DETECTION_MODEL.CUSTOM_BOX_OBJECTS
    obj_param.enable_tracking = True
    zed.enable_object_detection(obj_param)

    objects = sl.Objects()
    obj_runtime_param = sl.ObjectDetectionRuntimeParameters()

    # Display
    camera_infos = zed.get_camera_information()
    camera_res = camera_infos.camera_resolution
    # Create OpenGL viewer
    viewer = gl.GLViewer()
    point_cloud_res = sl.Resolution(min(camera_res.width, 720), min(camera_res.height, 404))
    point_cloud_render = sl.Mat()
    viewer.init(camera_infos.camera_model, point_cloud_res, obj_param.enable_tracking)
    point_cloud = sl.Mat(point_cloud_res.width, point_cloud_res.height, sl.MAT_TYPE.F32_C4, sl.MEM.CPU)
    image_left = sl.Mat()
    # Utilities for 2D display
    display_resolution = sl.Resolution(min(camera_res.width, 1280), min(camera_res.height, 720))
    image_scale = [display_resolution.width / camera_res.width, display_resolution.height / camera_res.height]
    image_left_ocv = np.full((display_resolution.height, display_resolution.width, 4), [245, 239, 239, 255], np.uint8)

    # # Utilities for tracks view
    # camera_config = camera_infos.camera_configuration
    # tracks_resolution = sl.Resolution(400, display_resolution.height)
    # track_view_generator = cv_viewer.TrackingViewer(tracks_resolution, camera_config.fps, init_params.depth_maximum_distance)
    # track_view_generator.set_camera_calibration(camera_config.calibration_parameters)
    # image_track_ocv = np.zeros((tracks_resolution.height, tracks_resolution.width, 4), np.uint8)
    # Camera pose
    cam_w_pose = sl.Pose()

    while viewer.is_available() and not exit_signal:
        if zed.grab(runtime_params) == sl.ERROR_CODE.SUCCESS:
            # -- Get the image
            lock.acquire()
            zed.retrieve_image(image_left_tmp, sl.VIEW.LEFT)
            image_net = image_left_tmp.get_data()
            lock.release()
            run_signal = True

            # -- Detection running on the other thread
            while run_signal:
                sleep(0.001)

            # Wait for detections
            lock.acquire()
            # -- Ingest detections
            zed.ingest_custom_box_objects(detections)
            lock.release()
            zed.retrieve_objects(objects, obj_runtime_param)

            # -- Display
            # Retrieve display data
            zed.retrieve_measure(point_cloud, sl.MEASURE.XYZRGBA, sl.MEM.CPU, point_cloud_res)
            point_cloud.copy_to(point_cloud_render)
            zed.retrieve_image(image_left, sl.VIEW.LEFT, sl.MEM.CPU, display_resolution)
            zed.get_position(cam_w_pose, sl.REFERENCE_FRAME.WORLD)

            # 3D rendering
            viewer.updateData(point_cloud_render, objects)
            # 2D rendering
            np.copyto(image_left_ocv, image_left.get_data())
            cv_viewer.render_2D(image_left_ocv, image_scale, objects, obj_param.enable_tracking)
            global_image = image_left_ocv
            # global_image = cv2.hconcat([image_left_ocv, image_track_ocv])
            # # Tracking view
            # track_view_generator.generate_view(objects, cam_w_pose, image_track_ocv, objects.is_tracked)

            cv2.imshow("ZED | 2D View and Birds View", global_image)
            key = cv2.waitKey(10)
            if key == 27:
                exit_signal = True
        else:
            exit_signal = True

    viewer.exit()
    exit_signal = True
    zed.close()


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', type=str, default='yolov8n.pt', help='model.pt path(s)')
    parser.add_argument('--svo', type=str, default=None, help='optional svo file')
    parser.add_argument('--img_size', type=int, default=416, help='inference size (pixels)')
    parser.add_argument('--conf_thres', type=float, default=0.4, help='object confidence threshold')
    opt = parser.parse_args()

    with torch.no_grad():
        main()

2.2 实验结果

测距图(感觉挺精准的)
在这里插入图片描述
视频展示:

Zed相机+YOLOv8目标检测跟踪

3. 版本二

3.1 简介

版本一是调用了zed开发的库实现的检测,直接以盒子的形式去展示的结果,可开发性不强,且功能较弱

版本二的跟踪和分割均是在yolov8的基础上去实现的相关功能,而非调用官方封装好的库,帧率和开发性均强于版本一,如需要可跳转下方链接订阅https://blog.csdn.net/qq_45077760/article/details/137029320

3.2 功能展示

测距功能

在这里插入图片描述
跟踪功能
在这里插入图片描述

分割功能

在这里插入图片描述
视频展示

4. 源码下载

4.1 版本一

下载链接:https://download.csdn.net/download/qq_45077760/89146305

4.2 版本二

下载链接:https://blog.csdn.net/qq_45077760/article/details/137029320

### YOLOv8ZED相机集成实现测距 为了在Ubuntu上使用YOLOv8ZED相机构建个有效的物体检测并测量距离的应用程序,需考虑几个方面: #### ZED SDK安装 确保已按照官方指南完成ZED SDK的安装[^3]。这步骤对于获取来自ZED相机的数据至关重要。 #### Python环境设置 创建个新的虚拟环境来管理依赖项,并激活此环境。之后安装必要的Python包,包括`ultralytics`(用于YOLOv8)、`pyzed`以及其他可能需要的支持库如NumPy等。 ```bash python3 -m venv myenv source myenv/bin/activate pip install ultralytics pyzed numpy opencv-python ``` #### 加载预训练模型 下载或转换适用于YOLOv8的目标识别权重文件。可以从Ultralytics官网或其他可信资源处获得这些预训练好的模型参数。 #### 编写代码逻辑 下面是个简单的例子展示如何结合两者工作: ```python from pyzed import sl import cv2 from ultralytics import YOLO # 初始化ZED相机 init_params = sl.InitParameters() cam = sl.Camera() status = cam.open(init_params) if status != sl.ERROR_CODE.SUCCESS: print("Camera Open", status, "Exit!") exit(-1) runtime_parameters = sl.RuntimeParameters() image_zed = sl.Mat() # 左图像 depth_image_zed = sl.Mat() # 深度图 point_cloud = sl.Mat() # 点云数据 model = YOLO('path_to_yolov8_weights') # 替换为实际路径 while True: err = cam.grab(runtime_parameters) if err == sl.ERROR_CODE.SUCCESS: cam.retrieve_image(image_zed, sl.VIEW.LEFT) # 获取左摄像头图片 cam.retrieve_measure(depth_image_zed, sl.MEASURE.DEPTH) # 获取深度信息 image_cv = image_zed.get_data()[:, :, :3] results = model.predict(image=image_cv, conf=0.5)[0].boxes.data.cpu().numpy() for result in results: x_min, y_min, x_max, y_max, score, class_id = map(int, result[:6]) center_x = (x_min + x_max) / 2 center_y = (y_min + y_max) / 2 depth_value = depth_image_zed.get_value(center_x, center_y).get_depth()[1] distance = round(depth_value * 0.001, 2) # 转换成米单位 label = f'{score:.2f} {distance} m' cv2.rectangle(image_cv, (x_min, y_min), (x_max, y_max), color=(0, 255, 0)) cv2.putText(image_cv, label, org=(x_min, y_min - 10), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=0.5, thickness=2, color=(0, 255, 0)) cv2.imshow("Image", image_cv) key = cv2.waitKey(1) if key & 0xFF == ord('q'): break cv2.destroyAllWindows() cam.close() ``` 这段脚本展示了基本的工作流程:打开ZED相机连接;读取每帧视频流中的彩色图像以及对应的深度信息;利用加载后的YOLOv8模型执行目标检测任务;最后计算每个被标记对象中心位置的距离值,并将其显示出来。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

积极向上的mr.d

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值