/ PYTHON, ZED, COMPUTERVISION

ZED2相机api使用心得

一. ZED相机的选型

STEREOLABS(ZED相机厂家)的官网:https://www.stereolabs.com/zed/

ZED双目相机有以下四种型号:

ZED 2i:ZED相机最新款(ZED相机二代的进阶版,防尘防水

ZED 2 :ZED相机二代(相较于1代多了支持IMU

ZED mini:功能上和二代基本一致,尺寸更小性能上要差,比如这里支持的景深在15m以内,而二代的景深最大支持20m。

ZED:ZED相机一代,支持2K视频,景深范围在(0.3m,25m),无IMU,所以对于需要玩SLAM的这款就不推荐了。

二. 安装ZED的SDK

2.1 安装SDK

ZED相机SDK官网:https://www.stereolabs.com/developers/release/

我们可以看到是,所有的SDK基本都需要你安装cuda,因此我选择了cuda11.0进行安装,具体的cuda安装过程可参考我之前的一篇博客:Windows10环境下搭建CUDA10.1和pytorch1.6

直接安装即可,将下载下来的exe双击运行ZED_SDK_Windows10_cuda11.0_v3.5.2_4.exe即可,如下图所示

一直往下走即可。

2.2 安装python API

安装完成之后,可以在 C:\Program Files (x86)\ZED SDK\下看到get_python_api.py,如下图

直接进行安装python的api:python get_python_api.py

三. python API的使用

  • 导入zed的python包

    import pyzed.sl as sl
    
  • 查看zed相机版本,这里说下,如果检测到是ZED一代的化,是不支持拿IMU数据的。

    zed = sl.Camera()
    info = zed.get_camera_information()
    print("Camera Model: " + str(info.camera_model))
    
  • 拿到相机的温度信息(本人亲测可用,讲真别用官方教程里的例子,得到的温度全是0,坑)
      sensors_data = sl.SensorsData()
      if zed.get_sensors_data(sensors_data, sl.TIME_REFERENCE.CURRENT) == sl.ERROR_CODE.SUCCESS:
          	# 这里分别拿到左、右相机,imu,气压计4者的温度
          	temperature_left = sensors_data.get_temperature_data().get(sl.SENSOR_LOCATION.ONBOARD_LEFT)
              temperature_right = sensors_data.get_temperature_data().get(sl.SENSOR_LOCATION.ONBOARD_RIGHT)
              temperature_imu = sensors_data.get_temperature_data().get(sl.SENSOR_LOCATION.IMU)
              temperature_barometer = sensors_data.get_temperature_data().get(sl.SENSOR_LOCATION.BAROMETER)
              print("Left: {:.2f}, Right: {:.2f}, IMU: {:.2f}, Barometer: {:.2f}\r\n".format(temperature_left,
                                                                                             temperature_right,
                                                                                             temperature_imu,
                                                                                        temperature_barometer))
    
  • 拿到相机的惯导(IMU)信息,注意这里使用的是Y轴向上的右手定律,这里即Z轴方向是车头/飞机头的方向。

    # 初始化
    zed = sl.Camera()  # Create a ZED camera object
    input_type = sl.InputType()  # Set configuration parameters
      
    init = sl.InitParameters(input_t=input_type)  # 初始化
              
            self.init.coordinate_system = sl.COORDINATE_SYSTEM.RIGHT_HANDED_Y_UP  # 右手定律Y轴向上
      
    while True:
        runtime_parameters = sl.RuntimeParameters()
        if zed.grab(runtime_parameters) == sl.ERROR_CODE.SUCCESS:
            zed_imu = zed_sensors.get_imu_data()
            zed_imu_pose = sl.Transform()
                    ox = round(zed_imu.get_pose(zed_imu_pose).get_orientation().get()[0], 3)
                    oy = round(zed_imu.get_pose(zed_imu_pose).get_orientation().get()[1], 3)
                    oz = round(zed_imu.get_pose(zed_imu_pose).get_orientation().get()[2], 3)
                    ow = round(zed_imu.get_pose(zed_imu_pose).get_orientation().get()[3], 3)
                    print("IMU Orientation: Ox: {0}, Oy: {1}, Oz {2}, Ow: {3}\n".format(ox, oy, oz, ow))
    

    这里拿到的数据是四元数,如果我们想转成欧拉角,这里推推荐使用scipy的转换函数Rotation.from_quat

    from scipy.spatial.transform import Rotation
    # 将上面拿到的四元数转成欧拉角
    rot = Rotation.from_quat([ox,oy,oz,ow])
    eular_angle = rot.as_euler('xyz', degrees=True)
    print(f'翻滚角:{eular_angle[2]},俯仰角:{eular_angle[0]},方位角:eular_angle[1]')
    
  • 拿取当前时间(毫秒级)

    # 当前时间戳(毫秒)
    time_zed = zed_pose.timestamp.get_milliseconds()
    
  • 拿到前景图

    # 定义图像数据
    image_size = zed.get_camera_information().camera_resolution
    image_zed = sl.Mat(image_size.width, image_size.height, sl.MAT_TYPE.U8_C4)
      
    while True
    	# 从zed相机中拿到前景图
        zed.grab()
        # 拿取图像
        zed.retrieve_image(image_zed, sl.VIEW.LEFT, sl.MEM.CPU, image_size)
        # 转成numpy
        image_np = image_zed.get_data()
    
  • 拿到景深图(当然也可以拿到3D点云数据)

    # 这里需要在初始化中加入深度模式
    init.depth_mode = sl.DEPTH_MODE.ULTRA  # 深度模式  (默认-PERFORMANCE)
    init.coordinate_units = sl.UNIT.MILLIMETER  # 毫米级    (默认-MILLIMETER)
      
    # 定义测量数据
    depth_zed = sl.Mat(image_size.width / 2, image_size.height / 2)  # 16位进行保存
    point_cloud_zed = sl.Mat(image_size.width / 2,image_size.height / 2)
      
    while True
    	# 从zed相机中拿到景深图
        zed.grab()
        # 拿取景深图像
        zed.retrieve_measure(depth_zed, sl.MEASURE.DEPTH,sl.MEM.CPU,image_size)
        # 拿取3D点云图像
        zed.retrieve_measure(point_cloud_zed, sl.MEASURE.XYZRGBA)
        # 转成numpy
        depth_np = depth_zed.get_data()
        point_cloud_value = point_cloud_zed.get_value(x, y)[1]