Unity+C#+ZED相机——获取矩阵格式的点云数据

Unity+C#+ZED相机——获取矩阵格式的点云数据

引言

上礼拜把ZED-UNITY插件的原生接口的代码和核心的脚本看了一遍。有了比较系统的了解,里面的注释用插件翻译了一下,自己校正了,并把中文附带在脚本注释里面了,同时把自己经过思考或者搜索资料才整明白的知识点,代码关系也注释在相应的地方。 对于自己不懂的函数,Unity的相关概念,也把自己查找到的博客资料,官网说明的网站链接直接放在代码的附近,可以直接点进去网站查看。
在前面一篇文章中,我对插件中对点云数据的显示案例进行了注释。 ZED插件在Unity中很少提到类似RGB图像、Pointcloud这种概念,而是根据Unity的习惯,把RGB图像和Depth图像称为图像型的纹理(texture_image type),把点云数据,深度数据称为测量型纹理(texture measure type ),这也是我为什么我刚开始接触这个插件的时候误以为没有提供接口,而去配置了C#与ZED-SDK的接口。 在插件的示例中都是把这两种数据直接与纹理对象捆绑在一起,不能像操作矩阵一样对其中的数据进行操作。(也有可能是我对Unity还不熟悉)
所以这篇主要记录一下如何在Unity中用ZED插件提供的矩阵数据类型存储点云数据。图像数据是类似的。

基础环境

操作系统:win10专业版
ZED相机型号:zed-mini
ZED SDK:3.1版本(插件目前只支持3.1版本)
ZED-Unity插件:3.1版本
Unity版本:2019
C#版本:8.0
编辑器:Rider

程序代码

  • 要获得这个数据的关键在于调用ZEDCamera.cs的函数 RetrieveMeasure。如下图,在这里插入图片描述
    这个函数里面封装了一个.dll的外部声明的函数,这个函数是底层SDK定义的,用于读取相机的measure类型的数据。

  • 脚本名称: MyPointCloudFromZED.cs

  • 代码

/*
*FileName: MyPointCloudFromZED.cs
*Author: Lance
*UnityVersion:2019.4.4f1
*Date: 2020-09-02
*Connect: 261983626
*Description: 
 *
 * 应用对象:任意
 * 生命周期:在ZED准备好后
 * 脚本功能:获取ZED相机中的点云数据
 * 依赖对象:
 * 1、组件:ZEDManager.cs,如果不需要用这个相机实现透视功能,可以挂在其他的空对象上
 * 2、类文件:ZEDCommon.cs类文件   主要是一些功能函数
            ZEDCamera.cs类文件  主要是相机的对象
            ZEDMat.cs类文件  主要是数据类型
 * 备注说明:ZEDManager已经帮我们做好了大量的相机管理工作,我们只需要在这里面实现几个函数的调用即可
*
*History:
 * 2020-09-02:  
 *
*/

using System.Collections;
using System.Collections.Generic;
using sl;
using UnityEngine;

/// <summary>
/// 获得ZED相机的点云
/// </summary>
public class MyPointCloudFromZED : MonoBehaviour
{
    
    
    [Header("点云数据获取")] public string Header;

    /// <summary>
    /// 点云数据矩阵
    /// </summary>
    private sl.ZEDMat myPointCloud; //定义点云矩阵

    /// <summary>
    /// 图像数据矩阵
    /// </summary>
    private sl.ZEDMat myRgbImage; //定义图像矩阵

    /// <summary>
    /// Instance of the ZEDManager interface
    /// ZEDManager界面的实例,后面应该是要将外部的ZedManager赋值给下面这个变量才对
    /// </summary>
    public ZEDManager zedManager = null;

    /// <summary>
    /// 相机的分辨率
    /// </summary>
    private sl.Resolution resolution;

    /// <summary>
    /// zed Camera controller by zedManager
    /// zedManager的zed相机控制器
    /// </summary>
    private sl.ZEDCamera zed = null;


    /// <summary>
    /// 是否更新数据
    /// </summary>
    public bool update = true; //暂时没用上

    /// <summary>
    /// 前一次update的状态
    /// </summary>
    private bool previousUpdate = true; //暂时没用上

    /// <summary>
    /// 某个值
    /// </summary>
    private float4 onePointCloud; //定义某个接收单个点数据的变量

    void Start()
    {
    
    
        if (zedManager == null) //如果还没有实例化
        {
    
    
            zedManager = FindObjectOfType<ZEDManager>(); //找到ZEDManager组件
            if (ZEDManager.GetInstances().Count > 1 //如果这个组件的实例化不只一个,我的情况一般只有一个
                ) //We chose a ZED arbitrarily, but there are multiple cams present. Warn the user.
                 我们任意选择一个ZED,但是有多个相机存在。所以需要警告用户。
            {
    
    
                Debug.Log("Warning: " + gameObject.name +
                          "'s zedManager was not specified, so the first available ZEDManager instance was " +
                          "assigned. However, there are multiple ZEDManager's in the scene. It's recommended to specify which ZEDManager you want to " +
                          "use to display a point cloud.");
            }
        }

        if (zedManager != null) //实例化后的
            zed = zedManager.zedCamera; //相机设备赋值
        myPointCloud = new ZEDMat(); //实例化矩阵,内部获得指针,
        myRgbImage = new ZEDMat(); //实例化矩阵,内部获得指针
        onePointCloud = new float4();
        resolution = new sl.Resolution((uint) zed.ImageWidth, (uint) zed.ImageHeight); //设置图像分辨率
        myPointCloud.Create(resolution, ZEDMat.MAT_TYPE.MAT_32F_C4); //分配指定的大小和类型的数据内存
        myRgbImage.Create(resolution, ZEDMat.MAT_TYPE.MAT_8U_C3); //分配指定的大小和类型的数据内存
    }

    // Update is called once per frame
    void Update()
    {
    
    
        //Don't do anything unless the ZED has been initialized.
        // 除非ZED已初始化,否则请勿执行任何操作。

        if (zed.IsCameraReady)
        {
    
    
            ERROR_CODE getPointCloudResult = zed.RetrieveMeasure(myPointCloud, MEASURE.XYZ); //返回注册点云数据的结果
            if (getPointCloudResult == ERROR_CODE.SUCCESS)  //如果获得矩阵数据成功的话
            {
    
    
                myPointCloud.GetValue(400, 400, out float4 point, ZEDMat.MEM.MEM_CPU); // 从矩阵中取出某个像素点的点云数据,  这边指定从cpu内存中获得
                onePointCloud = point; 
                //输出点云数据值   
                print("x:"+onePointCloud.r.ToString()+"y:"+onePointCloud.g.ToString()+"z:"+onePointCloud.b);
            }
        }
    }
}
  • 运行结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/scy261983626/article/details/108355662
今日推荐