zed2相机使用技巧(基于官方教程)

考虑到生成深度信息网上都是直接用的相机生成的,我的zed2相机也具有传感器,且内部也可以生成深度图,接下来我将从两方面出发,一方面去学习zed-sdk的使用(之前学过一段时间),另一方面去看他的源码学习,他的原理。

软件层面使用

zed explore可以查看对应相机分辨率时候的内外参数。

基础应用

这里我已经配置好了环境,zed的配置环境较为简单,大家可以参考这个博主的环境配置:

ZED 2i相机在配置ZED SDK、ZED API、官方示例zed-pytorch中遇到的问题详细解说(持续更新版)-CSDN博客

在导入不了zed的包的时候复制bin文件夹确实是解决办法,建议在环境变量上也配置一下,每个人电脑存放sdk位置不同这里就不说了。

Stereolabs 文档:API 参考、教程和集成 --- Stereolabs Docs: API Reference, Tutorials, and Integration

上面是官方对其zed-sdk的介绍以及初步教程,我觉得参考价值还是很高的。

官方教程代码

此处我在代码中进行了部分扩展,以及详细的解释就不单独解释了

认识zed——相机相关参数的详细获取

通过下面示例简单认识zed,通过这个例子知道怎么定义一个相机,并且获取它的相关信息。

官方示例:
import pyzed.sl as sl


def main():
    # Create a Camera object
    zed = sl.Camera() # 这是使用 ZED SDK 的第一步,为后续操作摄像头提供了基础。

    # Create a InitParameters object and set configuration parameters
    init_params = sl.InitParameters() # 创建一个初始化参数对象。
    init_params.sdk_verbose = 0 # 设置 SDK 的日志输出级别(控制SDK是否输出详细的日志信息)

    # Open the camera
    err = zed.open(init_params) # 打开摄像头,开始与 ZED SDK 进行通信,init_params 是传递给 open 方法的参数 \
        # 用于配置摄像头的行为。返回值 err 是一个枚举值,表示打开摄像头的结果。
    if err != sl.ERROR_CODE.SUCCESS: # sl.ERROR_CODE.SUCCESS表示成功打开摄像头
        exit(1)
    # breakpoint()
    # Get camera information (ZED serial number)
    zed_serial = zed.get_camera_information().serial_number # 获取摄像头的信息,包括序列号、分辨率、帧率等。serial_number 是摄像头的唯一标识符。
    # 除此之外可以用camera_model、camera_firmware_version、camera_resolution、camera_fps等获取摄像头的其他信息
    print("Hello! This is my serial number: {0}".format(zed_serial))
    # print(f'all camera information: {zed.get_camera_information()}') # 打印摄像头的所有信息

    # Close the camera
    zed.close() # 确保在使用完摄像头后,调用 close 方法关闭摄像头,释放资源。 

if __name__ == "__main__":
    main()

以上是官方提供的代码hello zed,首先给相机一个参数,然后可以对相机的参数进行设置,我们可以分开来看。而后在中间对相机进行处理,最后关闭相机。

个人第一个官方教程的扩展——获取zed相机型号,不过这一部分其实也可以用zed explore来获取

可以看到型号为zed2,但是有时候我们可能更想在代码里面告诉别人,这时候也是很简单的:

获取zed型号的示例代码
import pyzed.sl as sl

def get_zed_camera_model():
    # 创建ZED相机对象
    zed = sl.Camera()

    # 设置相机初始化参数
    init_params = sl.InitParameters()
    init_params.camera_resolution = sl.RESOLUTION.HD1080
    init_params.camera_fps = 30

    # 打开相机
    err = zed.open(init_params)
    if err != sl.ERROR_CODE.SUCCESS:
        print(f"相机打开失败: {err}")
        return

    # 获取相机信息
    camera_info = zed.get_camera_information()
    
    # 打印相机型号
    print(f"相机型号: {camera_info.camera_model}")
    
    # 关闭相机
    zed.close()

if __name__ == "__main__":
    get_zed_camera_model()
利用camera_info获取更详细的相机相关参数

初次之外,通过camera_info可以获取绝大部分信息,包括不限于相机自身,硬件配置,还包括各种imu信息,有时候我们可能需要其中一些信息放置于视频左上角来表示一下,比如分辨率或者帧率,然后相机内参,我更推荐取zed explore这个软件获取,这样更方便不是吗。

# 获取ZED相机信息
camera_info = zed.get_camera_information()

# 基本相机信息
print(f"相机型号: {camera_info.camera_model}")
print(f"序列号: {camera_info.serial_number}")
print(f"固件版本: {camera_info.camera_configuration.firmware_version}")
print(f"相机状态: {'已连接' if camera_info.camera_state else '未连接'}")

# 硬件信息
print(f"CUDA设备ID: {camera_info.camera_configuration.cuda_device_id}")
print(f"IMU类型: {camera_info.sensors_configuration.imu_type}")
print(f"IMU固件版本: {camera_info.sensors_configuration.imu_firmware_version}")

# 分辨率和FPS信息
resolution = camera_info.camera_configuration.resolution
print(f"分辨率: {resolution.width}x{resolution.height}")
print(f"当前FPS: {camera_info.camera_configuration.fps}")

# 相机参数
left_cam = camera_info.calibration_parameters.left_cam
right_cam = camera_info.calibration_parameters.right_cam
print("\n左相机内参:")
print(f"  焦距: {left_cam.fx}, {left_cam.fy}")
print(f"  主点: {left_cam.cx}, {left_cam.cy}")
print(f"  畸变系数: {left_cam.disto}")

print("\n右相机内参:")
print(f"  焦距: {right_cam.fx}, {right_cam.fy}")
print(f"  主点: {right_cam.cx}, {right_cam.cy}")
print(f"  畸变系数: {right_cam.disto}")

# 立体相机参数
print("\n立体相机参数:")
print(f"  基线(mm): {camera_info.calibration_parameters.T[0] * 1000}")
print(f"  旋转矩阵: {camera_info.calibration_parameters.R}")
print(f"  平移向量: {camera_info.calibration_parameters.T}")

# 镜头信息
print("\n镜头信息:")
print(f"  镜头类型: {camera_info.camera_configuration.lens_type}")
print(f"  镜头畸变: {camera_info.camera_configuration.lens_distortion}")

# 温度信息
if hasattr(camera_info, 'temperature_data'):
    print("\n温度信息:")
    print(f"  左相机温度: {camera_info.temperature_data.left_camera_temperature}°C")
    print(f"  右相机温度: {camera_info.temperature_data.right_camera_temperature}°C")
    print(f"  主板温度: {camera_info.temperature_data.main_board_temperature}°C")

图像捕获——相机相关模式的修改(初始模式,运行模式)

第二部分是图像捕捉,这个案例可以学到如何捕获相机图像以及对应的深度信息

下面是官方案例:

官方案例:
import pyzed.sl as sl


def main():
    # Create a Camera object
    zed = sl.Camera()

    # Create a InitParameters object and set configuration parameters
    init_params = sl.InitParameters()
    init_params.camera_resolution = sl.RESOLUTION.AUTO # 设置摄像头的分辨率。
    # init_params.camera_resolution = sl.RESOLUTION.HD2K # 2K分辨率
    # init_params.camera_resolution = sl.RESOLUTION.HD1080 # 1080p分辨率
    # init_params.camera_resolution = sl.RESOLUTION.HD720 # 720p分辨率
    # init_params.camera_resolution = sl.RESOLUTION.VGA # VGA分辨率
    init_params.camera_fps = 30  # Set fps at 30

    # Open the camera
    err = zed.open(init_params)
    if err != sl.ERROR_CODE.SUCCESS:
        print("Camera Open : "+repr(err)+". Exit program.")
        exit()


    # Capture 50 frames and stop
    i = 0
    image = sl.Mat() # 创建一个 sl.Mat 对象,用于存储捕获的图像。
    runtime_parameters = sl.RuntimeParameters() # sl.RuntimeParameters() 是 ZED SDK 提供的一个类,用于配置运行时的参数(如深度计算模式等)。
    while i < 50:
        # Grab an image, a RuntimeParameters object must be given to grab()
        if zed.grab(runtime_parameters) == sl.ERROR_CODE.SUCCESS: # zed.grab(runtime_parameters)用于捕获一帧图像,返回为sl.ERROR_CODE.SUCCESS则成功。
            # A new image is available if grab() returns SUCCESS
            zed.retrieve_image(image, sl.VIEW.LEFT) # 获取左视图的图像,存储在 image 对象中。
            # zed.retrieve_image(image, sl.VIEW.RIGHT) # 获取右视图的图像,存储在 image 对象中。
            # zed.retrieve_image(image, sl.VIEW.LEFT_UNRECTIFIED) # 获取左视图的非校正图像,存储在 image 对象中。
            timestamp = zed.get_timestamp(sl.TIME_REFERENCE.CURRENT)  # 获取实践戳
            print("Image resolution: {0} x {1} || Image timestamp: {2}\n".format(image.get_width(), image.get_height(),
                  timestamp.get_milliseconds())) # 打印图像的分辨率和时间戳(毫秒值)
            # Save the image to disk
            # filename = "image_" + str(i) + ".png"
            # image.write(filename)
            # print("Image saved to disk: " + filename)
            # # print("Image saved to disk: " + filename)
            i = i + 1

    # Close the camera
    zed.close()

if __name__ == "__main__":
    main()
利用init_params修改相机的初始参数

刚刚我们通过camera_info获取了相机的相关参数,但是对于相机自身的相关模式比如对其分辨率的选择,深度模式的选择,是需要根据我们自己来选择的,通过上面的官方例子,我们可以发现init_params = sl.InitParameters(),也就是init_params(markdown``的小块代码引用不知道为什么怎么在csdn里面用,这里用加粗替代下)来更改相机对应的模式的。

# 创建初始化参数对象
init_params = sl.InitParameters()

# 相机设置
init_params.camera_resolution = sl.RESOLUTION.HD1080  # 设置分辨率: AUTO, HD2K, HD1080, HD720, VGA
init_params.camera_fps = 30  # 设置帧率,根据分辨率调整可用值
init_params.camera_device_id = 0  # 指定要使用的相机设备ID
init_params.camera_image_flip = sl.FLIP_MODE.AUTO  # 图像翻转模式: AUTO, NO, HORIZONTAL, VERTICAL

# 深度设置
init_params.depth_mode = sl.DEPTH_MODE.PERFORMANCE  # 深度模式: PERFORMANCE, MEDIUM, QUALITY
init_params.coordinate_units = sl.UNIT.METER  # 深度单位: MILLIMETER, CENTIMETER, METER, KILOMETER
init_params.depth_minimum_distance = 0.3  # 最小深度距离(米)
init_params.depth_maximum_distance = 20.0  # 最大深度距离(米)
init_params.coordinate_system = sl.COORDINATE_SYSTEM.RIGHT_HANDED_Y_UP  # 坐标系: RIGHT_HANDED_Y_UP, RIGHT_HANDED_Z_UP等

# 视觉定位设置
init_params.enable_positional_tracking = True  # 启用视觉定位

# 电源模式
init_params.power_mode = sl.POWER_MODE.OPTIMAL  # 电源模式: ECONOMIC, OPTIMAL

# 图像增强
init_params.sdk_verbose = True  # 启用SDK日志输出
init_params.sdk_gpu_id = -1  # 指定使用的GPU ID,-1表示自动选择
init_params.sdk_verbose_level = sl.VERBOSE.INFO  # 日志详细程度: ERROR, WARNING, INFO, DEBUG

# 网络和流设置
init_params.input.set_from_stream("stream.svo")  # 从SVO文件读取
init_params.input.set_from_rtsp("rtsp://example.com/stream")  # 从RTSP流读取
init_params.input.set_from_svo_file("path/to/file.svo")  # 从SVO文件读取
init_params.svo_real_time_mode = True  # SVO实时模式
init_params.svo_real_time_mode = False  # SVO按帧读取模式

# 校准参数
init_params.camera_custom_calibration = None  # 设置自定义校准参数

    

以上代码在我们后续使用这个相机sdk是非常常用的。也非常方便用,比如你想设置分辨率就是init_params.camera_resolution,像设置FPS就是init_params.camera_fps,稍微懂点英语就行。

利用runtime_parameters修改相机运行时候的参数

除此之外,init_params我们可以理解为相机的初始化参数设置,当相机运行时的模式还有另一个参数runtime_parameters = sl.RuntimeParameters()就是这个,这个是在相机初始化后动态调整的。通常用于使用相机的特定功能比如网格、深度之类的。

# 深度处理参数
runtime_parameters.sensing_mode = sl.SENSING_MODE.STANDARD  # 深度感知模式: STANDARD, FILL
runtime_parameters.measure3D_reference_frame = sl.REFERENCE_FRAME.CAMERA  # 3D测量的参考坐标系
runtime_parameters.confidence_threshold = 100  # 深度置信度阈值(0-100)
runtime_parameters.textureness_confidence_threshold = 100  # 纹理置信度阈值(0-100)

# 图像增强参数
runtime_parameters.enable_depth = True  # 启用深度计算
runtime_parameters.enable_point_cloud = True  # 启用点云生成
runtime_parameters.enable_mesh = False  # 启用网格生成
runtime_parameters.enable_tracking = False  # 启用定位跟踪

# 性能优化参数
runtime_parameters.enable_image_enhancement = True  # 启用图像增强
runtime_parameters.enable_gpu_memory_sharing = True  # 启用GPU内存共享
runtime_parameters.enable_smooth_depth = True  # 启用平滑深度处理

# 空间映射参数
runtime_parameters.map_type = sl.SPATIAL_MAP_TYPE.FUSED_POINT_CLOUD  # 空间映射类型

# 运行时错误处理
runtime_parameters.verbose_errors = True  # 启用详细错误信息
init_params与runtime_parameters的对比

那有些朋友就好奇了,为什么runtime_parameters有些功能好像与init_params重复了,其实不然,我们通过官方第二个教程可以发现,init_params是在zed.open(init_params)中使用的,这样在相机运行时是不可变的,而runtime_parameterszed.open后配置zed.grab()前配置,这些都可以实时调整的。

深度信息获取——深度信息的选择并与图像同步

以下是官方案例:

官方案例:(内含镜像参考系的使用,方便以其他位置为参考系初始点)
import pyzed.sl as sl
import math
import numpy as np
import sys

def main():
    # Create a Camera object
    zed = sl.Camera()

    # Create a InitParameters object and set configuration parameters
    init_params = sl.InitParameters()
    init_params.depth_mode = sl.DEPTH_MODE.ULTRA  # Use ULTRA depth mode
# init_params.depth_mode = sl.DEPTH_MODE.PERFORMANCE  # 性能优先
# # 或
# init_params.depth_mode = sl.DEPTH_MODE.QUALITY  # 平衡模式
# # 或
# init_params.depth_mode = sl.DEPTH_MODE.ULTRA  # 精度优先
# # 或
# init_params.depth_mode = sl.DEPTH_MODE.NONE  # 禁用深度
    init_params.coordinate_units = sl.UNIT.MILLIMETER  # Use millimeter units (for depth measurements)
# 可以用三种单位
# init_params.coordinate_units = sl.UNIT.MILLIMETER  # 毫米(默认)
# # 或
# init_params.coordinate_units = sl.UNIT.CENTIMETER  # 厘米
# # 或
# init_params.coordinate_units = sl.UNIT.METER  # 米



    # Open the camera
    status = zed.open(init_params)
    if status != sl.ERROR_CODE.SUCCESS: #Ensure the camera has opened succesfully
        print("Camera Open : "+repr(status)+". Exit program.")
        exit()

    # Create and set RuntimeParameters after opening the camera
    runtime_parameters = sl.RuntimeParameters() # 创建一个运行时参数对象,用于配置运行时的参数。
    
    i = 0
    image = sl.Mat()
    depth = sl.Mat()
    point_cloud = sl.Mat()
# 下面代码作用:
# 用于坐标变换,在将相机坐标系转化为世界坐标系中使用
    mirror_ref = sl.Transform() # 创建一个变换对象,用于设置镜像参考系。(用户专制式)这里官方使用的是平移,但是除了平移还有旋转,缩放
# mirror_ref.set_translation(sl.Translation(x, y, z))这是平移
# 下面是两种旋转形式
# # 方式1:使用欧拉角 (roll, pitch, yaw)
# mirror_ref.set_rotation(sl.Rotation(roll, pitch, yaw))
# # 方式2:使用四元数
# mirror_ref.set_rotation(sl.Rotation(qx, qy, qz, qw))
# 缩放可以改变坐标系的尺度
# 沿x、y、z轴的缩放因子
# mirror_ref.set_scale(sl.Scale(sx, sy, sz))
    mirror_ref.set_translation(sl.Translation(2.75,4.0,0)) # 设置镜像参考系的平移部分。

    while i < 50:
        # A new image is available if grab() returns SUCCESS
        if zed.grab(runtime_parameters) == sl.ERROR_CODE.SUCCESS:
            # Retrieve left image
            # 用于有存储图像的对象,这里之前有image = sl.Mat(),通过这个获取的对象从里面获取自己想要的
            zed.retrieve_image(image, sl.VIEW.LEFT)# 这里获取想要的就是左摄像头图像,这也是默认的.
            # 有以下可以获取的图像
# sl.VIEW.LEFT:左摄像头图像(默认)。
# sl.VIEW.RIGHT:右摄像头图像。
# sl.VIEW.LEFT_GRAY/sl.VIEW.RIGHT_GRAY:灰度图。
# sl.VIEW.SIDE_BY_SIDE:左右摄像头的拼接图像。
# sl.VIEW.DEPTH:深度图的可视化效果(伪彩色图)。
# 通常使用与深度数据的关系,这里图像和深度数据是同步的
# 获取深度数据:
            # Retrieve depth map. Depth is aligned on the left image
            zed.retrieve_measure(depth, sl.MEASURE.DEPTH) # 获取深度图像,深度图与左图像对齐。
            # Retrieve colored point cloud. Point cloud is aligned on the left image.
            zed.retrieve_measure(point_cloud, sl.MEASURE.XYZRGBA)

            # Get and print distance value in mm at the center of the image
            # We measure the distance camera - object using Euclidean distance
            x = round(image.get_width() / 2)
            y = round(image.get_height() / 2)
            err, point_cloud_value = point_cloud.get_value(x, y) # 获取点云数据(指定坐标值)
            

            if math.isfinite(point_cloud_value[2]): # 检查是否为有限数
                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]) # 勾股定理(三维)(0,1,2分别为xyz)
                print(f"Distance to Camera at {{{x};{y}}}: {distance}")
            else : 
                print(f"The distance can not be computed at {{{x};{y}}}")
            i += 1    
           

    # Close the camera
    zed.close()

if __name__ == "__main__":
    main()

在这个示例中,官方主要是想告诉我们mirror_ref = sl.Transform()镜像参考系的使用,众所周知,有时候我们其实获取的位置可能不是相机的位置,这时候我们就需要手眼标定来对其进行坐标轴的原点重新选择,就可以使用镜像参考系来改变其原点位置,具体可以移动旋转等功能,这些我在代码里面都有补充。

利用zed.retrieve_image,zed.retrieve_measure获取图像以及匹配深度信息(内含其他获取深度信息的测量类型)

还有个就是zed.retrieve_image,zed.retrieve_measure,zed.retrieve_measure的使用retrieve在英文中有读取的意思,在这里就是用这几个函数来读取信息的。

我们可以发现在这里获取深度信息的代码分别是zed.retrieve_measure(depth,sl.MEASURE.DEPTH)以及zed.retrieve_measure(point_cloud, sl.MEASURE.XYZRGBA)这里面sl.MEASURE.DEPTH,sl.MEASURE.XYZRGBA分别用于获取深度图以及获取带颜色的点云,可以用来测量距离、3D重建。但初次之外还有其他的方式,见下方代码:

zed.retrieve_measure
# 其中第一个参数无论是depth_map,还是point_cloud_xyzrgba都是用sl.Mat()存储的,只是用来区分一下放不同测量类型的mat对象
# 获取深度图-距离测量(每个像素值代表点到相机距离)
zed.retrieve_measure(depth_map, sl.MEASURE.DEPTH)
# 获取带颜色的点云,每个点包含3D坐标和颜色信息(RGBA)
zed.retrieve_measure(point_cloud_xyzrgba, sl.MEASURE.XYZRGBA)
# 获取仅包含3D坐标的点云,不含颜色信息,相比上面的代码占用内存更少速度更快
zed.retrieve_measure(point_cloud_xyz, sl.MEASURE.XYZ)
# 相比上面的多了强度信息(识别物体材质用的)
zed.retrieve_measure(point_cloud_xyz, sl.MEASURE.XYZI)
# 获取表面法线向量
zed.retrieve_measure(normals, sl.MEASURE.NORMALS)
# 获取视差图(视差与深度是反比的,需通过基线和焦距转换为深度)
zed.retrieve_measure(disparity_map, sl.MEASURE.DISPARITY)
# 获取深度置信度图,每个像素值表示对应点深度的可靠程度(这个真的很有用了,有时候由于环境确实不确定靠不靠谱,就可以用这个过滤掉低质量深度数据,来提高位置精度了)
zed.retrieve_measure(confidence_map, sl.MEASURE.CONFIDENCE)
zed.retrieve_image

关于zed.retrieve_image的使用的第二个参数在代码里面已经说了还可以选择哪些

# sl.VIEW.LEFT:左摄像头图像(默认)。
# sl.VIEW.RIGHT:右摄像头图像。
# sl.VIEW.LEFT_GRAY/sl.VIEW.RIGHT_GRAY:灰度图。
# sl.VIEW.SIDE_BY_SIDE:左右摄像头的拼接图像。
# sl.VIEW.DEPTH:深度图的可视化效果(伪彩色图)。
# 通常使用与深度数据的关系,这里图像和深度数据是同步的

通常这个函数适用于最后展示图像的(以下代码是用opencv展示图像):

image_ocv = image.get_data()
cv2.imshow("ZED Depth Viewer", image_ocv)

经过上面的讲解来一个小小的使用:

利用zed-sdk获取画面鼠标所在位置到相机的距离以及点击地方到相机的距离(其中主要是修改了官方的对图像中间的点的深度信息获取,使其可以用鼠标回调):

import pyzed.sl as sl
import math
import numpy as np
import cv2
import sys

# 全局变量
mouse_x, mouse_y = 0, 0
clicked_x, clicked_y = -1, -1
distance_text = ""

# 鼠标回调函数
def mouse_callback(event, x, y, flags, param):
    global mouse_x, mouse_y, clicked_x, clicked_y, distance_text
    mouse_x, mouse_y = x, y
    
    if event == cv2.EVENT_LBUTTONDOWN:
        clicked_x, clicked_y = x, y
        print(f"Clicked at: ({x}, {y})")

def main():
    global mouse_x, mouse_y, clicked_x, clicked_y, distance_text
    
    # 创建相机对象
    zed = sl.Camera()
    
    # 初始化参数设置
    init_params = sl.InitParameters()
    init_params.depth_mode = sl.DEPTH_MODE.ULTRA
    init_params.coordinate_units = sl.UNIT.MILLIMETER
    
    # 打开相机
    status = zed.open(init_params)
    if status != sl.ERROR_CODE.SUCCESS:
        print(f"Camera Open : {repr(status)}. Exit program.")
        exit()
    
    # 创建运行时参数
    runtime_parameters = sl.RuntimeParameters()
    
    # 创建存储图像和深度的对象
    image = sl.Mat()
    depth = sl.Mat()
    point_cloud = sl.Mat()
    
    # 设置坐标变换
    mirror_ref = sl.Transform()
    mirror_ref.set_translation(sl.Translation(2.75, 4.0, 0))
    
    # 创建窗口并设置鼠标回调
    cv2.namedWindow("ZED Depth Viewer", cv2.WINDOW_NORMAL)
    cv2.setMouseCallback("ZED Depth Viewer", mouse_callback)
    
    # 主循环
    while True:
        # 抓取一帧
        if zed.grab(runtime_parameters) == sl.ERROR_CODE.SUCCESS:
            # 获取左摄像头图像
            zed.retrieve_image(image, sl.VIEW.LEFT)
            
            # 获取深度图
            zed.retrieve_measure(depth, sl.MEASURE.DEPTH)
            
            # 获取点云
            zed.retrieve_measure(point_cloud, sl.MEASURE.XYZRGBA)
            
            # 将ZED图像转换为OpenCV格式
            image_ocv = image.get_data()
            
            # 获取鼠标位置的深度信息
            err, point_cloud_value = point_cloud.get_value(mouse_x, mouse_y)
            
            # 计算距离
            if math.isfinite(point_cloud_value[2]):
                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]
                )
                distance_text = f"Distance: {distance:.2f} mm"
            else:
                distance_text = "Distance: N/A"
            
            # 在图像上显示鼠标位置和距离信息
            cv2.circle(image_ocv, (mouse_x, mouse_y), 5, (0, 255, 0), -1)
            cv2.putText(image_ocv, f"Position: ({mouse_x}, {mouse_y})", (10, 30), 
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
            cv2.putText(image_ocv, distance_text, (10, 60), 
                        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
            
            # 如果有点击,显示点击位置的深度信息
            if clicked_x >= 0 and clicked_y >= 0:
                cv2.circle(image_ocv, (clicked_x, clicked_y), 8, (0, 0, 255), 2)
                err, click_point_value = point_cloud.get_value(clicked_x, clicked_y)
                if math.isfinite(click_point_value[2]): # 检查是否为有限数(存在深度)
                    click_distance = math.sqrt(
                        click_point_value[0] * click_point_value[0] +
                        click_point_value[1] * click_point_value[1] +
                        click_point_value[2] * click_point_value[2]
                    )
                    cv2.putText(image_ocv, f"Clicked Distance: {click_distance:.2f} mm", 
                                (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
                else:
                    cv2.putText(image_ocv, "Clicked Distance: N/A", 
                                (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
            
            # 显示图像
            cv2.imshow("ZED Depth Viewer", image_ocv)
            
            # 按ESC键退出
            if cv2.waitKey(1) == 27:
                break
    
    # 关闭窗口和相机
    cv2.destroyAllWindows()
    zed.close()

if __name__ == "__main__":
    main()

运行以后可以得到下面示例:其中绿色的是鼠标飘过的位置,这里由于截图时下滑,所以下面的地方没有在左右两边相机同时获取到,也就是地方离相机太近了导致检测不到,红色的是鼠标点击的结果:当然你也可以在cv2.putText中修改文字颜色或者是cv2.circle修改圆圈大小,反正影响也不大就是看个人喜好吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值
OSZAR »