2

Kinect、Xtion、PMD nano、Softkinetic DepthSense の 4 つの異なる深度カメラを使用できます。

OpenNI、PMD ドライバー、Softkinetic ドライバーなど、すべてを読み取る方法を知っているライブラリがあります。

理想的には、カメラの種類ごとに単純なグラバーを作成し、それを他のプログラムへのプラグインとして使用したいと考えています。つまり、データ ストリームへの高速で非冗長なアクセス (つまり、メモリ コピーが多すぎない) を取得します。

問題の 1 つは、多くの場合、32 ビットまたは 64 ビットの適切なライブラリがないため、同じプロジェクトですべてのグラバーをコンパイルできないことです。

これを達成するための最良の方法は何ですか?

4

1 に答える 1

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 で次のようにコンパイルします。mex getSKFrame.cpp -IC:\Development\boost_1_48_0

そして最後に、Matlab で使用します。D = getSKFrame()'; imagesc(D)

于 2013-01-18T21:47:39.560 に答える