私は研究者なので、このアイデアは生産コードには必ずしも有用ではありませんが、このシナリオを考えると、私の最善の解決策は、カメラの種類ごとにサーバー プロセスを作成することです。各サーバー プロセスは、独自のタイプのカメラ ストリームをロードする方法を認識しており、それを他のプロセスが読み取れる共有メモリ スペースにスローします。さまざまな種類のロック メカニズムを使用することは明らかに可能ですが、以下のコードではロックを使用していません。
サーバー プロセスには次のものが含まれます。
#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)