Intel RealSense开发一
更新: 通过一位同事的对比校验,在重装了驱动和SDK后一切正常,F200的案例都可以正常运行了,而我俩的操作区别仅在于,我在安装SDK完成后没有重启电脑!由此浪费了大量精力,无话可说….
更新: 后续研究中发现了不少问题,SDK版本问题不说了,R3已经不支持R200,R2版本中UnityToolkit中的例子都无法使用,解决的过程中发现不仅有特性支持的问题,代码问题,还有Unity官方bug的问题,另本篇描述的过程在之后也是时灵时不灵,最后发现只要涉及深度数据的获取,不论是这里的代码还是UnityToolkit中的代码都会有问题,最后建议各位,如果做RealSense的开发,还是别用R200了,当然我只是站在我的技术水平上做的建议,大牛请忽略。
另外列出过程中遇到的问题的参考链接:
解决EnsureRunningOnMainThread报错;
解决unable to initialize all modalities报错;
解决rendererupdatemanager.updateall报错;
对于一个菜鸟程序员来说,入手RealSense开发真不是一件轻松的事。网上关于这方面的开发文章偏少,且只记录了重点,细节没有,官方Demo也不够“贴心”,好在经历一番曲折之后,成功实现了彩色图像和深度图像的抓取,特此记录,以供大家参考。由于水平所限,不对代码含义进行解读,请见谅。
开发环境
摄像头: Intel RealSense R200
CPU: Intel Core I7 7700K
GPU: GeForce GTX 1070
软件: Win10 + Visual Studio 2015 + Unity 5.6.1
这里要特别说明一下,RealSense的开发对软硬件都有要求,官方SDK文档中是这样描述的:
这里的硬件特别是CPU的描述太过笼统,实际上不用看型号,而需要看CPU以及GPU是否支持OpenCL 1.2以上版本,注意是CPU和GPU都必须满足该条件,我在官网论坛上看到有人的GPU支持OpenCL 1.2,CPU支持OpenCL 1.1,结果导致初始化失败。但是如何检测呢,大家可以用Geeks3D GPU Caps Viewer这款软件,如下图,第一条红线处会显示支持OpenCL的硬件(包括CPU和GPU),选中可在下方显示支持的OpenCL版本。
另外,需要安装:
1. 对应的DCM(Depth Camera Manager),也是驱动;
2. 对应的SDK,至少需要core,其他可按需下载face,hand,cursor,scan3d,seg3d等;
提醒一下:以上文件需要翻墙上Intel官网,并注册账号才能下载,下载后都是exe文件,默认安装即可。
开发正文
SDK安装完毕后,可使用生成到桌面的“Intel® RealSense™ SDKTools”中Tools: “Camera Explorer”检测摄像头是否可正常使用。
这个文件夹中包含了一些官方的样例(Samples文件夹下),但遗憾的是我选择的样例“RawStreams.unity”是无法正常使用的,用Unity直接打开后没有报错,两个分别用于显示彩色图像和深度图像的Plane只是由白色变成了灰色,仅此而已,使用断点调试可以发现SenesManger实例.Init()返回的Status值为Status_Item_Unavaliable,因为这个原因,我先后更换了Unity版本和RealSense SDK版本,耗费了大量时间(没办法,菜鸟程序员会瞎猜),后面说初始化失败的真实原因。
这里顺便说一下,当前Intel RealSense SDK的版本是R3,这个版本不再支持R200,参考这里,所以需要下载R2版本,参考这里,,请注意。
好了,下面正式贴工程代码。
一、新建Unity工程,导入SDK R2提供的UnityToolkit.unitypackage开发包,默认存放目录是:C:Program Files (x86)IntelRSSDKframeworkUnity。
二、创建两个RawImage分别用于显示彩色图像和深度图像,创建两个Material分别赋予两个RawImage,Shader可以用Unlit/Texture。
三、创建空物体,命名为RawStreamController,并创建同名C#脚本,赋给该空物体。
四、编写代码。
1. 定义变量
[Header("Color Settings")]
public int colorWidth = 640;
public int colorHeight = 480;
public Material RGBMaterial;
[Header("Depth Settings")]
public int depthWidth = 628;
public int depthHeight = 468;
public Material DepthMaterial;
//实例
private PXCMSenseManager psm = null;
//深度图像
private Texture2D depthImageTexture2D = null;
//彩色图像
private Texture2D colorImageTexture2D = null;
特别说明:注意depthWidth和depthHeight两个值,官方文档和网上教程大多都是640和480,但是这是错误的,这两个数字就是导致初始化失败的原因,这里要特别感谢理想国的博客,是他指出了问题所在,简单说就是Intel实感摄像头的颜色和深度分辨率是有限制的,官方SDK文档给出的条件如下:
放大一点:
内容在开发手册“Developer Guide (CHM)”中的Advanced Topics/Working With Multiple Modalities目录下。
2. 初始化
void Start () {
if (psm != null) return;
//创建实例
psm = PXCMSenseManager.CreateInstance();
if(psm == null)
{
Debug.LogError("PXCMSenseManager Initialization Failed!");
return;
}
//激活流事件
psm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR, colorWidth, colorHeight);
psm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_DEPTH, depthWidth, depthHeight);
//初始化
pxcmStatus status = psm.Init();
if(status < pxcmStatus.PXCM_STATUS_NO_ERROR)
{
Debug.LogError("Stream Pipeline Init Failed!");
return;
}
}
- 每帧获取数据
void Update () {
if (psm == null)
return;
//抓取帧数据
if(psm.AcquireFrame(false,0) < pxcmStatus.PXCM_STATUS_NO_ERROR)
{
return;
}
//创建Sample
PXCMCapture.Sample sample = psm.QuerySample();
if(sample != null)
{
OnSampleRetrieve(sample);
}
psm.ReleaseFrame();
}
4.处理图像
private void OnSampleRetrieve(PXCMCapture.Sample sample)
{
//接收颜色数据
PXCMImage.ImageInfo colorImgInfo = new PXCMImage.ImageInfo();
colorImgInfo.width = colorWidth;
colorImgInfo.height = colorHeight;
colorImgInfo.format = PXCMImage.PixelFormat.PIXEL_FORMAT_RGB24;
PXCMImage colorImg = psm.session.CreateImage(colorImgInfo);
colorImg = sample.color;
//接收深度数据
PXCMImage.ImageInfo depthImgInfo = new PXCMImage.ImageInfo();
depthImgInfo.width = depthWidth;
depthImgInfo.height = depthHeight;
depthImgInfo.format = PXCMImage.PixelFormat.PIXEL_FORMAT_RGB24;
PXCMImage depthImg = psm.session.CreateImage(depthImgInfo);
depthImg = sample.depth;
//
if (colorImg != null)
{
if (colorImageTexture2D == null)
{
colorImageTexture2D = new Texture2D(colorWidth, colorHeight, TextureFormat.RGB24, false);
RGBMaterial.mainTexture = colorImageTexture2D;
RGBMaterial.mainTextureScale = new Vector2(-1, -1);
}
}
if(depthImg != null)
{
if(depthImageTexture2D == null)
{
depthImageTexture2D = new Texture2D(depthWidth, depthHeight, TextureFormat.RGB24, false);
DepthMaterial.mainTexture = depthImageTexture2D;
DepthMaterial.mainTextureScale = new Vector2(-1, -1);
}
}
//
PXCMImage.ImageData colorImageData;
colorImg.AcquireAccess(PXCMImage.Access.ACCESS_READ, out colorImageData);
colorImageData.ToTexture2D(0, colorImageTexture2D);
colorImg.ReleaseAccess(colorImageData);
colorImageTexture2D.Apply();
PXCMImage.ImageData depthImageData;
depthImg.AcquireAccess(PXCMImage.Access.ACCESS_READ, out depthImageData);
depthImageData.ToTexture2D(0, depthImageTexture2D);
depthImg.ReleaseAccess(depthImageData);
depthImageTexture2D.Apply();
}
获取颜色图像和深度图像的过程是一样的,大家可以省略着看。
5.结束
private void OnDisable()
{
if (psm != null)
psm.Dispose();
}
最后贴上运行成功的结果: