我有4种不同深度的相机可供我使用:Kinect,Xtion,PMD nano,Softkinetic DepthSense。
我有知道如何阅读所有这些库的库:OpenNI,PMD驱动程序,Softkinetic驱动程序。
理想情况下,我希望为每种摄像机制作一个简单的抓取器,然后将其用作任何其他程序的插件,即对数据流进行快速,非冗余访问(即,没有太多的存储器拷贝)。其中一个问题是在很多情况下我没有32或64位的正确库,所以我无法在同一个项目中编译所有的抓取器。
实现这一目标的最佳方法是什么?
答案 0 :(得分:0)
我是一名研究员,所以这个想法对于生产代码并不一定有用,但鉴于这种情况,我最好的解决方案是为每种类型的摄像机创建一个服务器进程。每个服务器进程都知道如何加载自己类型的摄像机流,然后将其抛入其他进程可以读取的共享内存空间。 显然可以使用不同类型的锁定机制,但是我没有任何锁定就留下了下面的代码。
服务器进程将包括以下内容:
#define BOOST_ALL_NO_LIB
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
using namespace std;
using namespace boost::interprocess;
struct sharedImage
{
enum { width = 320 };
enum { height = 240 };
enum { dataLength = width*height*sizeof(unsigned short) };
sharedImage(){}
interprocess_mutex mutex;
unsigned short data[dataLength];
};
shared_memory_object shm;
sharedImage * sIm;
mapped_region region;
int setupSharedMemory(){
// Clear the object if it exists
shared_memory_object::remove("ImageMem");
shm = shared_memory_object(create_only /*only create*/,"ImageMem" /*name*/,read_write/*read-write mode*/);
printf("Size:%i\n",sizeof(sharedImage));
//Set size
shm.truncate(sizeof(sharedImage));
//Map the whole shared memory in this process
region = mapped_region(shm, read_write);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in the preallocated memory of shm
sIm = new (addr) sharedImage;
return 0;
}
int shutdownSharedMemory(){
shared_memory_object::remove("ImageMem");
return 0;
}
要启动它,请致电setupSharedMemory()
并关闭来电shutdownSharedMemory()
。
在这个简单的例子中,所有的值都是硬编码的,但很容易想象它会更灵活。
现在让我们假设您正在使用SoftKinetic的DepthSense。那么您可以为Depth节点编写以下回调。
void onNewDepthSample(DepthNode node, DepthNode::NewSampleReceivedData data) {
//scoped_lock<interprocess_mutex> lock(sIm->mutex);
memcpy(sIm->data, data.depthMap, sIm->dataLength);
}
这样做只是将最新的深度图复制到共享内存空间。 你还可以添加一个时间戳和一个锁以及你需要的任何东西,但这个基本代码对我来说效果很好,所以我会保持原样。
现在在其他一些过程中,您可以以非常类似的方式访问数据。 下面的代码是我用来将实时SoftKinetic DepthSense深度流导入Matlab进行实时处理的代码。这种方法比试图专门为SoftKinetic编写自己的mex包装器有一个巨大的优势,因为如果我为它们编写服务器,我可以对所有其他相机使用相同的代码。
#include <math.h>
#include <windows.h>
#include "mex.h"
#define BOOST_ALL_NO_LIB
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace boost::interprocess;
struct sharedImage
{
enum { width = 320 };
enum { height = 240 };
enum { dataLength = width*height*sizeof(short) };
sharedImage(): dirty(true){}
interprocess_mutex mutex;
uint8_t data[dataLength];
bool dirty;
};
void getFrame(unsigned short *D)
{
//Open the shared memory object.
shared_memory_object shm(open_only ,"ImageMem", read_write);
//Map the whole shared memory in this process
mapped_region region(shm ,read_write);
//Get the address of the mapped region
void * addr = region.get_address();
//Construct the shared structure in memory
sharedImage * sIm = static_cast<sharedImage*>(addr);
//scoped_lock<interprocess_mutex> lock(sIm->mutex);
memcpy((char*)D, (char*)sIm->data, sIm->dataLength);
}
void mexFunction(int nlhs, mxArray *plhs[ ], int nrhs, const mxArray *prhs[ ])
{
// Build outputs
mwSize dims[2] = {320, 240};
plhs[0] = mxCreateNumericArray(2, dims, mxUINT16_CLASS, mxREAL);
unsigned short *D = (unsigned short*)mxGetData(plhs[0]);
try
{
getFrame(D);
}
catch (interprocess_exception &ex)
{
mexPrintf("getFrame:%s\n", ex.what());
}
}
在我的计算机上,我在Matlab中编译:{{1}}
最后在Matlab中使用它:mex getSKFrame.cpp -IC:\Development\boost_1_48_0