Realsense Camera SDK 开发手记(一)

时间:2024-03-31 00:04:55

0x01

第一次使用SDK写代码,有很多不懂的地方,在设备来之前把文档看了一下,大概明白了点,东平西凑大概写了点,但是当把设备连接上去进行测试的时候就出现了各种问题,用RealSenseCamera进行开发的人还比较少,只有论坛上的一些零星的讨论,并且用C#进行开发的人还是占多数,毕竟和Unity3D结合起来还是比较有趣的。文档里写了入门的教程,但是因为和我的使用场景不太一样,其中又有些奇葩的地方,文档里又没有说明,对编程又不是很熟悉,导致到后来才大概猜到了一点,理解了一点,在这里写下来给大家一个参考。

0x02

Realsense Camera SDK 开发手记(一)

我们这次采用的设备是intel RealSense Camera R200,它有RGB摄像头以及两个IR摄像头,通过与IR Laser Projector的结合可以得到场景的深度信息。SDK中还有很多内置的面部识别和手势识别等函数。但是我们并不需要用到那些,我只想获取它的左右两个红外摄像头采集到的图片。

0x03

首先遇到的问题的就是visual studio 2013配置的问题,本来它很贴心的提供了直接导入Property Sheet一键式的配置,可是我试了两次都失败了,而且传到github上以后发现其他人下载下来就没办法打开我的Solution了(里面出现我的配置文件的具体路径),于是还是进行了手动的配置。其实手动配置也挺好的,下次遇到其他的时候需要配置就可以自己动手了。原来配置opencv的时候就是各种不懂,别人怎么说我就怎么做,虽然最后可以写代码了,但是下次遇到这些问题又要把博客翻出来看看是怎么回事了。

本来按部就班按照他的指导手册一步一步来就可以了,可是各种报错。

Create Session

The SDK core is represented by two interfaces:

  • PXCSessionmanages all of the modules of the SDK
  • PXCSenseManagerorganizes a pipeline by starting,stopping,and pausing the operations of its varies modalities.
PXCSenseManager *psm=0;
psm = PXCSenseManager::CreateInstance();
if (!psm)
{
wprintf_s(L"Unable to create the PXCSenseManager\n");
return 1;// select the color stream of size 640x480 and depth stream of size 640x480
}
psm->EnableStream(PXCCapture::STREAM_TYPE_LEFT, 640, 480);
psm->EnableStream(PXCCapture::STREAM_TYPE_RIGHT, 640, 480);
psm -> Init()
}

然后初始化的时候就报错了,前面的配置没有问题。我就看了一下它的例子,然后把其中一段拷贝了出来

// Select the color and depth streams
PXCVideoModule::DataDesc ddesc={};
ddesc.deviceInfo.streams=PXCCapture::STREAM_TYPE_RIGHT |PXCCapture::STREAM_TYPE_LEFT;
sm->EnableStreams(&ddesc);

然后初始化没有问题,我当时就可想不通为什么这么来就行,用EnableStream就是不行呢,明明官方文档里没有提到这个问题啊。各种不理解,困惑了很长世间,导致我下面也没办法写下去。

0x04

后来在论坛里看到了这段代码

// Get the raw 16bit data from the infrared image
PXCMImage.ImageData irImageData;
irImageSource.AcquireAccess(PXCMImage.Access.ACCESS_READ,PXCMImage.PixelFormat.PIXEL_FORMAT_Y16,out irImageData);
irImageData.ToUShortArray(0, irData);
// despite the ir camera being 628 pixels wide, the raw bytes are stored with a "pitch" of 640
// in the case of 16bit data, the pitch is returned as 1280
int pitch = irImageData.pitches[0]/2;
int width = irImageSource.info.width;
int height = irImageSource.info.height;
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++){
int iA = (height-y-1) * pitch + x;
int iB = (y * width + x) * 4;
byte intensity = (byte)(irData[iA]/4);// raw pixels range between 0-1024
imgData[iB] = intensity;
imgData[iB+1] = intensity;
imgData[iB+2] = intensity;
imgData[iB+3] = 255; // Alpha
}
}

仔细琢磨了以后我发现自己对于PXCMImage::ImageData里面的pichespanels并不理解。重新看了文档以后我的理解是这样的:PXCMImage::ImageData里面存储的数据是在内存的某段空间,这段空间的首地址(类似于数组名)就放在panels[0]里。而piches(间距)表示的则是这段内存空间的宽度

但是还是不明白,为什么我上面的初始化会失败。我们后来还曾经尝试过用Github上面的一段代码把读取到的图像中的信息放到cv::Mat的格式里(长和宽设置为640×480)。它会提示超出了内存范围。尝试了各种断点之后发现,设备的信息返回的图像的大小是很诡异的628×468,当把图像大小设置为这个数字的时候按照教程来就不会出现无法初始化的问题了,看来问题出在这个图像的大小上。

于是搜索了一下SDK的文档,关于红外成像的大小的,发现是这样的

Realsense Camera SDK 开发手记(一)

返回的并没有640×480这个选项。到这里就恍然大悟了。

首先为什么初始化失败:我把图像的大小设置成了640×480,虽然能够启动数据流,但是初始化就出问题了,而后面提到的那种设置方式是采用了默认的大小。

第二,为什么后面会出现超出内存空间的错误,是因为虽然他的piches是640,但是在红外的情况下,实际上只在前面的628位上存储有图像的数据,后面的索引自然是失效的。但是如果要把图像的信息传输完全就要把循环结构中的int iA = (height-y-1) * pitch + x;使用pich而不是628

0x05

写了这么几段,也不知道有没有把问题说清楚,第一次写这样子的所谓技术博客还是没什么经验,但是我相信会越写越好的,下次用_visio_画图把问题说的更清楚。