zed2相机使用技巧(基于官方教程)_zed2i相机默认ip
考虑到生成深度信息网上都是直接用的相机生成的,我的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 sldef 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 sldef 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.resolutionprint(f\"分辨率: {resolution.width}x{resolution.height}\")print(f\"当前FPS: {camera_info.camera_configuration.fps}\")# 相机参数left_cam = camera_info.calibration_parameters.left_camright_cam = camera_info.calibration_parameters.right_camprint(\"\\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 sldef 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, VGAinit_params.camera_fps = 30 # 设置帧率,根据分辨率调整可用值init_params.camera_device_id = 0 # 指定要使用的相机设备IDinit_params.camera_image_flip = sl.FLIP_MODE.AUTO # 图像翻转模式: AUTO, NO, HORIZONTAL, VERTICAL# 深度设置init_params.depth_mode = sl.DEPTH_MODE.PERFORMANCE # 深度模式: PERFORMANCE, MEDIUM, QUALITYinit_params.coordinate_units = sl.UNIT.METER # 深度单位: MILLIMETER, CENTIMETER, METER, KILOMETERinit_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, FILLruntime_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 slimport mathimport numpy as npimport sysdef 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 slimport mathimport numpy as npimport cv2import sys# 全局变量mouse_x, mouse_y = 0, 0clicked_x, clicked_y = -1, -1distance_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修改圆圈大小,反正影响也不大就是看个人喜好吧。