我们在之前的 Azure Kinect 编程实战系列文章中写的都是 C++ 下的使用,用到的都是 C++ 下的第三方库,比如 OpenCV,OpenGL,PCL,Open3D等。
后面的几篇文章,我将简述如何在 Unity 下调用 Azure Kinect,并显示 RGB + Depth + Point Cloud 的程序。
在 Unity 下调用 Azure Kinect
对于熟悉 Unity 编程开发的同学来说,一个典型的 Unity C# 源码文件有如下形式。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Program : MonoBehaviour
{
void Start()
{
}
void Update()
{
}
}Start() 函数用来初始化环境。Update() 函数无限循环调用直到程序退出。
那么我们回顾一下之前在 C++ 环境下如何调用 Azure Kinect。
int main(int argc, char **argv)
{
//1. device capture
//2.
//3. while loop
while (1)
{
//4. capture =>
//5. show
//6. waitKey
}
return 0;
}在 C++ 的写法中,
1. device capture + 2. 应该类似的写在 Unity C# 脚本中的 Start() 函数。
3. while loop + 4. capture => + 5. show 则类似的写在 Update() 函数中。
那么我们重新写一下 Unity C# 脚本。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.Azure.Kinect.Sensor;
public class Program : MonoBehaviour
{
private Device device = null;
private Capture capture = null;
void Start()
{
device = Device.Open(0);
device.StartCameras(new DeviceConfiguration
{
ColorFormat = ImageFormat.ColorBGRA32,
ColorResolution = ColorResolution.R720p,
DepthMode = DepthMode.NFOV_2x2Binned,
SynchronizedImagesOnly = true,
CameraFPS = FPS.FPS30
});
}
void Update()
{
capture = device.GetCapture();
}
private void OnDestroy()
{
device.StopCameras();
}
}首先引入命名空间,
using Microsoft.Azure.Kinect.Sensor;
然后在 Program 类中声明两个私有变量,并初始化为 null。
private Device device = null;private Capture capture = null;
在 Start() 函数中启动设备,并设置深度摄像头模式,关于模式设置的讲解请参看我之前发表的文章。
Azure Kinect 深度摄像头参数设置 KinectAzureDK编程实战_OpenCV 1
void Start()
{
device = Device.Open(0);
device.StartCameras(new DeviceConfiguration
{
ColorFormat = ImageFormat.ColorBGRA32,
ColorResolution = ColorResolution.R720p,
DepthMode = DepthMode.NFOV_2x2Binned,
SynchronizedImagesOnly = true,
CameraFPS = FPS.FPS30
});
}在 Update() 函数中,类似于在 C++ 中的写法,为获取实时帧,需要实时循环获取当前设备的 Capture。
void Update()
{
capture = device.GetCapture();
}我们引入了新的函数 onDestroy(),当 Unity 程序退出时,要关闭摄像头。
private void OnDestroy()
{
device.StopCameras();
}在 Unity 下显示 RGB 帧
我们以上面的代码为基础显示实时 RGB 帧。
我个人的习惯是,在 Unity 下新建一个 3D Game => Plane。
然后将实时 RGB 帧作为这个 Plane 的纹理来显示。后面的 Depth 图的显示也如此。
那么我们需要再声明几个变量来辅助显示 RGB 帧。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.Azure.Kinect.Sensor;
public class Program : MonoBehaviour
{
public Game colorImagePlane;
private Device device = null;
private Capture capture = null;
protected byte[] colorImageBytes;
private int colorImageWidth;
private int colorImageHeight;
void Start()
{
//...
}
void Update()
{
//...
}
private void OnDestroy()
{
//...
}
}Azure Kinect 输出的 RGB 帧的内存格式是 uint8 型的数组。那么在 C# 脚本中,我们就要写成相应的 byte[]。
在 Start() 函数中,初始化这些变量。
void Start()
{
colorImagePlane = Game .Find("ColorImagePlane");
device = Device.Open(0);
device.StartCameras(new DeviceConfiguration
{
ColorFormat = ImageFormat.ColorBGRA32,
ColorResolution = ColorResolution.R720p,
DepthMode = DepthMode.NFOV_2x2Binned,
SynchronizedImagesOnly = true,
CameraFPS = FPS.FPS30
});
colorImageWidth = device.GetCalibration().ColorCameraCalibration.ResolutionWidth;
colorImageHeight = device.GetCalibration().ColorCameraCalibration.ResolutionHeight;
colorImageBytes = new byte[colorImageWidth * colorImageHeight * 4];
colorImagePlane.transform.localScale =
new Vector3((float)colorImageWidth / (float)colorImageHeight, 1.0f, 1.0f);
}RGB 帧的每个像素保存了 B G R A,共 4 个 uint8。那么我们初始化的 byte[] 数组大小为 colorImageWidth * colorImageHeight * 4。
在 Update() 函数中,需要从 capture 中获取实时 RGB 帧,并将 RGB 帧转为 Unity 下纹理格式 Texture2D。
void Update()
{
capture = device.GetCapture();
Image colorImage = capture.Color.Reference();
colorImageBytes = colorImage.Memory.ToArray();
Texture2D colorImageTex2D =
new Texture2D(colorImageWidth, colorImageHeight, TextureFormat.BGRA32, false);
colorImageTex2D.wrapMode = TextureWrapMode.Clamp;
colorImageTex2D.filterMode = FilterMode.Point;
colorImageTex2D.LoadRawTextureData(colorImageBytes);
colorImageTex2D.Apply();
colorImagePlane.GetComponent<Renderer>().material.mainTexture = colorImageTex2D;
}根据 Azure Kinect 在 Github 开源的官方 SDK 中给出的 C# 代码。
Azure Kinect 官方开源 C# SDK: WPF 示例 https://github.com/microsoft/Azure-Kinect-Sensor-SDK/blob/develop/src/csharp/Examples/WPF/MainWindow.xaml.cs
官方推荐的获取图片的形式是获取其 引用 。
Image colorImage = capture.Color.Reference();
作为 Azure Kinect SDK 的 C# SDK代码中,Image 类有一个可以直接返回 byte 数组的函数。
public Memory<byte> Memory { get; }那么我们可以直接获取 Image 所含像素的 byte 数组。
colorImageBytes = colorImage.Memory.ToArray();
然后,我们转换该 byte 数组为 Unity 下的纹理格式 Texure2D。
Texture2D colorImageTex2D =
new Texture2D(colorImageWidth, colorImageHeight,
TextureFormat.BGRA32, false);
colorImageTex2D.wrapMode = TextureWrapMode.Clamp;
colorImageTex2D.filterMode = FilterMode.Point;
colorImageTex2D.LoadRawTextureData(colorImageBytes);
colorImageTex2D.Apply();注意 Azure Kinect 返回的 RGB 的分辨率都不是严格的2次方幂。
那么 Texture2D 的格式还需要特别设置一下。
colorImageTex2D.wrapMode = TextureWrapMode.Clamp; colorImageTex2D.filterMode = FilterMode.Point;
其实这个和 C++ OpenGL 面对非2次方幂分辨率纹理的处理方式一样。
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
设置 wrap 模式和过滤方式。
下面一篇文章,我将讲述如何在 Unity 彩色化的显示 Depth Map。
商业合作请联系:
E-mail:forestsen@vip.qq.com
继续阅读与本文标签相同的文章
-
瓯海新增省级4家工业设计中心
2026-05-15栏目: 教程
-
PDA定制注意事项
2026-05-15栏目: 教程
-
喜马拉雅激活用户破6亿 付费会员数突破400万
2026-05-15栏目: 教程
-
刷脸支付应以安全为底线
2026-05-15栏目: 教程
-
极客晨星专题:孩子周末忙也有必要学编程
2026-05-15栏目: 教程
