【问题标题】:How can one share depth images between two processes?如何在两个进程之间共享深度图像?
【发布时间】:2013-01-02 17:03:33
【问题描述】:

我有 4 种不同的深度相机可供使用:Kinect、Xtion、PMD nano、Softkinetic DepthSense。

我有知道如何阅读所有这些的库:OpenNI、PMD 驱动程序、Softkinetic 驱动程序。

理想情况下,我希望为每种相机制作一个简单的抓取器,然后将其用作任何其他程序的插件,即快速、非冗余地访问数据流(即没有太多的内存副本)。

其中一个问题是,在许多情况下,我没有正确的 32 位或 64 位库,因此我无法在同一个项目中编译所有抓取器。

实现这一目标的最佳方法是什么?

【问题讨论】:

  • 我假设您想要一个 Matlab 解决方案?您没有提及,但您的标签暗示了这一点。
  • 不具体。我用 Matlab 标记它,因为我写的答案使用了 Matlab 客户端示例,我不知道如何标记答案。

标签: image matlab boost kinect shared-memory


【解决方案1】:

我是一名研究人员,所以这个想法不一定对生产代码有用,但考虑到这种情况,我最好的解决方案是为每种类型的相机创建一个服务器进程。每个服务器进程都知道如何加载自己类型的摄像头流,然后将其扔到其他进程可以读取的共享内存空间中。 显然可以使用不同类型的锁定机制,但我在下面的代码中没有任何锁定。

服务器进程将包括以下内容:

#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 编译:mex getSKFrame.cpp -IC:\Development\boost_1_48_0

最后在 Matlab 中使用它:D = getSKFrame()'; imagesc(D)

【讨论】:

    猜你喜欢
    • 2022-01-03
    • 2011-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多