2013-01-18 52 views
2

我有4種不同的深度相機可供我使用:Kinect,Xtion,PMD nano,Softkinetic DepthSense。如何在兩個進程之間共享深度圖像?

我有知道如何閱讀它們的庫:OpenNI,PMD驅動程序,Softkinetic驅動程序。

我希望爲每種相機制作一個簡單的抓取器,然後將其用作任何其他程序的插件,即對數據流進行快速,非冗餘訪問(即不會有太多內存拷貝)。

其中一個問題是,在很多情況下,我沒有正確的庫在32或64位,所以我不能在同一個項目中編譯所有的抓取器。

達到此目的的最佳方法是什麼?

+0

我假設你想要一個Matlab的解決方案嗎?你不提,但你的標籤暗示它。 –

+0

不是特別的。我用Matlab對它進行了標記,因爲我寫的答案使用了Matlab客戶端示例,我無法弄清楚如何標記答案。 – twerdster

回答

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。那麼你可以爲深度節點編寫下面的回調函數。

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)

相關問題