考虑到生成深度信息网上都是直接用的相机生成的,我的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_parameters在zed.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修改圆圈大小,反正影响也不大就是看个人喜好吧。