官术网_书友最值得收藏!

2.3 原始數據流獲取和處理

這一節將介紹獲取和處理原始視頻流和音頻流的常見任務。

1.獲取單個彩色或深度流

SenseManager接口實現I/O設備配置和獲取數據流,可以采用過程調用或事件回調方法來使用該接口。

(1)采用過程調用獲取彩色圖像樣本

例2-3說明了如何采用過程調用獲取彩色圖像樣本。

1)使用EnableStream函數選擇一個彩色流,再利用Init函數初始化流水線。

2)在循環中使用AcquireFrame函數來等待彩色圖像采樣到達,然后通過QuerySample進行獲取。

3)使用ReleaseFrame函數釋放這一幀,并等待下一個樣本。

4)利用Close函數進行清理過程。

可以使用CaptureManager接口中的過濾函數(如FilterByDeviceInfo)來自定義數據流選擇過程,例如選擇一個指定的攝像頭;也可使用QueryCaptureManager函數(或者captureManager屬性)來獲取CaptureManager接口實例。

例2-3 采用過程調用獲取彩色圖像樣本

// 創建PXCMSenseManager實例
PXCMSenseManager sm=PXCMSenseManager.CreateInstance();
// 選擇彩色數據流
sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR,640,480);
// 初始化流樣本
sm.Init();
for (;;) {
    // 該函數阻塞直到彩色樣本到達
    if (sm.AcquireFrame(true).isError()) break;
    // 獲取樣本
    PXCMCapture.Sample sample=sm.QuerySample(); 
    // 對圖像sample.color進行操作
    ......
    // 獲取下一個樣本
    sm.ReleaseFrame();
} 
// 清理過程
sm.close();

(2)利用事件回調獲取深度樣本

例2-4展示了如何使用SenseManager接口的事件回調函數來獲取60 fps的深度樣本,其中主要過程是創建事件處理程序和調用StreamFrame函數。

例2-4 利用SenseManager的事件回調函數獲取深度樣本

class MyHandler implements PXCMSenseManager.Handler {
    //注冊事件處理程序
   public pxcmStatus OnNewSample(int mid, PXCMCapture.Sample sample) {
       // sample.color進行操作 
       ......
        // 返回NO ERROR繼續;如有錯誤則退出循環
       return pxcmStatus.PXCM_STATUS_NO_ERROR;
   }
   ......
}; 
// 創建SenseManager實例
PXCMSenseManager sm=PXCMSenseManager.CreateInstance(); 
// 320×240×60fps啟動深度流
sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_DEPTH,320,240,60);
// 初始化事件處理器
MyHandler handler=new MyHandler();
sm.Init(handler); 
// 深度流樣本
sm.StreamFrames(true); 
// 清理過程
sm.close();
2.采集非對齊的彩色和深度樣本

例2-5展示了如何采集非對齊的彩色和深度樣本。例子中,當采樣數據準備好時,SenseManager單獨處理某個數據流的每個樣本。每個數據流可能以不同的幀率呈現樣本。例2-5做了如下工作:

1)使用EnableStream函數選擇彩色和深度流,然后使用Init函數初始化處理流水線。

2)在循環中,使用AcquireFrame函數ifall=false來等待樣本到達并讀取樣本。

3)使用QuerySample函數獲取樣本,并檢驗彩色和深度樣本相應的狀態和過程。

4)使用ReleaseFrame函數釋放當前幀,并讀取下一個樣本。

5)使用Close函數清理過程。

例2-5 利用SenseManager捕捉非對齊的彩色和深度數據

// 創建SenseManager實例
PXCMSenseManager sm=PXCMSenseManager.CreateInstance();
// 選擇彩色和深度流
sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR,640,480,30);
sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_DEPTH,320,240,30);
// 初始化流樣本
sm.Init();
for (;;) {
   // 該函數阻塞直到有樣本到達
   if (sm.AcquireFrame(false).isError()) break; 
   // 獲取樣本
   PXCMCapture.Sample sample=sm.QuerySample();
   if (sample!=null) {
       if (sample.color!=null) {   
       // 對彩色樣本進行操作
           ......
       } 
       if (sample.depth!=null) {   
       // 對深度樣本進行操作
           ......
       }
   }
 // 獲取下一樣本
   sm.ReleaseFrame();
}
// 清理過程
sm.close();

同樣可以使用StreamFrame函數和SenseManager事件回調實現獲取非對齊彩色和深度樣本,如例2-6所示。

例2-6 利用SenseManager事件回調獲取彩色和深度樣本

class MyHandler implements PXCMSenseManager.Handler {
   public pxcmStatus OnNewImage(int mid, PXCMCapture.Sample sample) {
       if (sample.color!=null) {
           // 對彩色樣本進行操作
           ......
       }
       if (sample.depth!=null) {
           // 對深度樣本進行操作
           ......
       }
       //返回NO ERROR繼續;有錯誤則退出循環
       return pxcmStatus.PXCM_STATUS_NO_ERROR;
   }
};

// 創建SenseManager實例
PXCMSenseManager sm=PXCMSenseManager.CreateInstance(); 
// 選擇彩色和深度流
sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR,640,480,30);
sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_DEPTH,320,240,30);
// 初始化處理器
MyHandler handler=new MyHandler();
sm.Init(handler); 
// 生成樣本流
sm.StreamFrames(true); 
// 清理
sm.close();
3.采集對齊的彩色和深度流

例2-7展示了如何采集對齊的彩色和深度樣本。該例子在同步了兩種數據幀的到達時間之后立刻處理數據。

例2-7的具體工作如下:

1)使用EnableStream函數選擇彩色和深度流,之后利用Init函數初始化處理流水線。

2)在循環中,AcquireFrame函數采用ifall=true選項來等待所有流的樣本都準備好。

3)用QuerySample函數獲取彩色和深度樣本。

4)用ReleaseFrame函數釋放幀,并等待讀取下一個樣本。

5)用Close函數進行清理。

例2-7 采集對齊的彩色和深度樣本

// 創建一個 SenseManager 實例
PXCMSenseManager sm=PXCMSenseManager.CreateInstance(); 
// 選擇彩色和深度數據流
sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR,640,480,30);
sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_DEPTH,320,240,30);
// 初始化數據流
sm.Init();
for (;;) {
   // 這個函數保持阻塞直到樣本準備好
   if (sm.AcquireFrame(true).isError()) break; 
   // 獲取樣本
   PXCMCapture.Sample sample=sm.QuerySample(); 
   // 在樣本上進行處理: sample.color & sample.depth
   ......
   // 準備下一幀處理
   sm.ReleaseFrame();
} 
// 清理
sm.close();

可以使用StreamFrames函數和SenseManager事件回調來采集彩色和深度樣本,如例2-8所示。

例2-8 利用SenseManager回調函數獲取對齊的彩色和深度樣本

class MyHandler implements PXCMSenseManager.Handler {
    public pxcmStatus OnNewSample(int mid, PXCMCapture.Sample sample) {
        //  sample.color  sample.depth樣本上處理
        ......
        //返回NO_ERROR繼續;如果出錯則報錯并放棄
        return pxcmStatus.PXCM_STATUS_NO_ERROR;
    }
}; 
// 創建一個 SenseManager 實例
PXCMSenseManager sm=PXCMSenseManager.CreateInstance(); 
// 選擇彩色和深度數據流
PXCMVideoModule.DataDesc ddesc=new PXCMVideoModule.DataDesc();
ddesc.deviceInfo.streams=EnumSet.of(PXCMCapture.StreamType.STREAM_TYPE_COLOR, PXCMCapture.StreamType.STREAM_TYPE_DEPTH);
sm.EnableStreams(ddesc); 
// 初始化處理器 handler
MyHandler handler=new MyHandler();
sm.Init(handler); 
// 流式處理
sm.StreamFrames(true); 
// 清理
sm.close();
4.啟動強力同步化

SDK支持基于硬件的彩色和深度流同步,可以產生成對的擁有相近時間戳的彩色和深度樣本。這種同步環節在很多應用場合非常有用,例如3D背景分割。

可以利用STREAM_OPTION_STRONG_STREAM_SYNC選項來啟動強力同步化。選項必須設置對所有需要同步的數據流生效,否則該選項將被忽略。毋庸置疑,這些流需要擁有相同的幀率。例如需要同步彩色和深度流,就可以利用EnableStreams函數對彩色和深度流同時指定這個選項,如例2-9所示。

 以攝像頭F200為例,如果有應用程序請求啟動強力同步化,系統將會有明顯的停頓并重啟攝像頭流。因此,只有當確實需要時才使用強力同步化。

例2-9 通過強力同步獲取對齊的彩色和深度樣本

  // 創建一個 SenseManager 實例
PXCMSenseManager sm=PXCMSenseManager.CreateInstance(); 
  // 選擇彩色和深度流
PXCMVideoModule.DataDesc ddesc=new PXCMVideoModule.DataDesc();
ddesc.deviceInfo.streams=EnumSet.of(PXCMCapture.StreamType.STREAM_TYPE_COLOR, PXCMCapture.StreamType.STREAM_TYPE_DEPTH);
ddesc.streams.color.options=EnumSet.Of(PXCMCapture.Device.StreamOption.STREAM_OPTION_STRONG_STREAM_SYNC);
ddesc.streams.depth.options=EnumSet.Of(PXCMCapture.Device.StreamOption.STREAM_OPTION_STRONG_STREAM_SYNC);
sm.EnableStreams(ddesc); 
  // 初始化
sm.Init();
for (;;) {
    // 函數保持阻塞直到采樣數據準備好
    if (sm.AcquireFrame(true).isError()) break; 
    // 獲取樣本
    PXCMCapture.Sample sample=sm.QuerySample(); 
    //  sample.color  sample.depth樣本上處理
    ......
    // 獲取下一幀數據
    sm.ReleaseFrame();
} 
// 清理
sm.close();
5.采集未矯正數據流

SDK支持R200攝像頭采集未矯正的數據流。矯正是修正鏡頭失真以及對齊的過程。未矯正的數據流是從攝像頭傳感器得來的原始圖像。

SDK利用STREAM_OPTION_UNRECTIFIED選項識別未矯正的數據流配置(參見StreamProle結構)。如果沒有指定這個命令選項,數據流默認配置為采用矯正。可以指定STREAM_OPTION_UNRECTIFIED選項獲取一個未矯正數據流,如例2-10所示。

 不是所有的R200算法模塊都支持未矯正數據流,只有當需要時才能使用這種方式。

可以通過QueryStreamProjectionParametersEx函數指定STREAM_OPTION_UNRECTIFIED選項來獲取未矯正攝像頭標定參數。

例2-10 獲取未校正彩色樣本

void CaptureAlignedColorDepthSamples() {
   // 創建一個 SenseManager 實例
   PXCMSenseManager sm=PXCMSenseManager.CreateInstance(); 
   // 選擇彩色和深度流
   PXCMVideoModule.DataDesc ddesc=new PXCMVideoModule.DataDesc();
   ddesc.deviceInfo.streams=EnumSet.of(PXCMCapture.StreamType.STREAM_TYPE_COLOR);
   ddesc.streams.color.options=EnumSet.Of(PXCMCapture.Device.StreamOption.STREAM_OPTION_UNRECTIFIED);
   sm.EnableStreams(ddesc); 
   //初始化
   sm.Init();
   for (;;) {       
       if (sm.AcquireFrame(true).isError()) break; 
       // 獲取樣本
       PXCMCapture.Sample sample=sm.QuerySample(); 
       //  sample.color上進行處理
       ......
       // 進行下一幀準備
       sm.ReleaseFrame();
   } 
   // 清理
   sm.close();
}
6.記錄和回放

可以記錄任何流序列到文件,并在之后播放這些流文件。

啟動文件記錄和回放需要的工作如下:

1)在CaptureManager實例中使用SetFileName函數。

2)在記錄模式,提供一個文件名并設定為記錄模式。

3)在回放模式,提供一個文件名并設定為非記錄模式。

SDK對文件名沒有限制,但在記錄模式中文件必須是可寫的。

 可以利用QueryCaptureManager函數獲取一個CaptureManager實例。

例2-11展示了如何記錄和回放已采集的彩色樣本。

 在記錄過程中,樣本按應用程序所處理后的狀態記錄到硬盤。如果應用程序采集未對齊的彩色和深度樣本,那么在硬盤上的樣本就是未對齊的。如果應用程序使樣本對齊,那么在硬盤上的樣本就是已對齊的。

例2-11 利用SenseManager進行彩色數據流的記錄和回放

void RecordORPlayback(string file, boolean record) {
   // 創建一個 SenseManager 實例
   PXCMSenseManager sm=PXCMSenseManager.CreateInstance(); 
   // 設置文件記錄和回放
   sm.QueryCaptureManager().SetFileName(file,record); 
   // 選擇彩色數據流
   sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR,640,480,0); 
   // 初始化并記錄300
   sm.Init();
   for (int i=0;i<300;i++) {       
       if (sm.AcquireFrame(true).isError()) break; 
       // 獲取樣本
       PXCMCapture.Sample sample=sm.QuerySample(); 
       // sample.color上進行處理
       ......
       // 進行下一幀數據處理準備
       sm.ReleaseFrame();
   } 
   // 清理
   sm.close();
   }
7.回放模式

可以按以下配置SDK的文件回放操作:

如果想要精確定位回放中的任意幀,可以選擇pause=true和realtime=false。例2-12展示了如何基于幀索引精確獲取幀數據。

例2-12 精確幀定位

// 創建SenseManager實例
PXCMSenseManager sm = PXCMSenseManager.CreateInstance(); 
// 設置回放文件名稱
sm.QueryCaptureManager().SetFileName(filename, false); 
// 啟動流和初始化
sm.EnableStream(PXCMCapture.StreamType.STREAM_TYPE_COLOR, 0, 0);
sm.Init(); 
// 設置realtime=truepause=false
sm.QueryCaptureManager().SetRealtime(false);
sm.QueryCaptureManager().SetPause(true); 
// 流循環
for (int i = 0; i < nframes; i+=3) {
   // 設置在每3幀數據上進行操作
   sm.captureManager.SetFrameByIndex(i);
   sm.FlushFrame(); 
   // 等待幀到達
   pxcmStatus sts = sm.AcquireFrame(true);
   if (sts < pxcmStatus.PXCM_STATUS_NO_ERROR) break; 
   // 獲取樣本并進行操作,圖像在sample.color
   PXCMCapture.Sample sample = sm.QuerySample();
   ......
   // 等待處理下一幀
   sm.ReleaseFrame();
} 
// 清除
sm.close();
8.文件壓縮

在磁盤上記錄原始彩色和深度圖像數據會給系統增加巨大的負擔。舉個例子,假設彩色分辨率配置為RGB32×1920×1080×30fps,深度分辨率配置為640×480×30fps,SDK需要大約272MB/s的磁盤I/O帶寬來寫入數據。這個要求使得大多數旋轉磁盤和某些緩慢的SSD無法進行文件記錄。

為了解決這個問題,SDK開發了一個試驗性的功能,即在數據寫入磁盤之前對其進行壓縮。這個壓縮功能采用H.264(I-frame only,constant QP)進行彩色圖像編碼和Lempel–Ziv–Oberhumer(LZO)進行深度圖像編碼。壓縮率在彩色圖像數據上大約為10:1,在深度圖像數據上為2:1。而相比之前例子的高寫入帶寬要求,磁盤I/O帶寬可降低為32MB/s。

文件壓縮功能要求系統具有如下配置:Intel Iris Graphics和最新的Intel Iris Graphics驅動。

需要設置以下注冊項來控制文件記錄功能:

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Intel\RSSDK\FileRecording]
"DisableH264Compression"=dword:0
"H264_QPI"=dword:8
"DisableLZOCompression"=dword:0

SDK默認H.264壓縮在彩色圖像流中應用,LZO在其他數據流中應用。H.264 QPI(I-frame quantization parameter)取值范圍為0(最小壓縮)到50(最大壓縮)。一個利用H.264壓縮的記錄文件只能在安裝Intel Iris Graphics的系統中播放。

SDK文件的記錄和回放功能有以下限制:

1)文件記錄可能會影響應用程序運行時間,而組織數據并寫入磁盤也是較重的工作負載,因此只有在必要的時候才啟用文件記錄。

2)計時程序在實時回放模式下計算數據流的準確呈現時間,故對運行時間敏感。因此如果系統在重負載時,文件回放程序可能會跳幀播放。為了保證數據幀的準確回放,應關閉實時模式。

9.訪問圖像和音頻數據

為了和其他運行庫實現共享訪問或互操作,SDK提供了圖像接口提取圖像存儲。

可以利用AcquireAccess函數來鎖定訪問圖像存儲,并在ImageData結構中獲取圖像存儲細節。圖像存儲的數據平面由data.planes[0-3]指出,其基址(pitch)存儲在data.pitches[0-3]。當圖像存儲訪問完成時,需要使用ReleaseAccess函數來解除訪問鎖定。例2-13展示了如何讀取圖像緩存。

例2-13 讀取圖像緩沖

// 圖像是一個PXCMImage實例
PXCMImage.ImageData data;
image.AcquireAccess(PXCMImage.Access.ACCESS_READ,data);
...... //圖像平面由data.planes[0-3]指出,pitch存儲在data.pitches[0-3]
image.ReleaseAccess(data);
10.創建圖像實例

可以利用Session接口的CreateImage函數來創建一個圖像實例。應用程序需要保證用來創建圖像實例(PXCMImage)的圖像緩存具有更長的生命周期。例2-14展示了如何在位圖中創建PXCMImage實例。

例2-14 從位圖創建圖像實例

// 讀取位圖存入內存
Bitmap bitmap = (Bitmap)Image.FromFile(file); 
// 圖像信息
PXCMImage.ImageInfo iinfo = new PXCMImage.ImageInfo();
iinfo.width  = bitmap.Width;
iinfo.height = bitmap.Height;
iinfo.format = PXCMImage.PixelFormat.PIXEL_FORMAT_RGB32; 
/* 創建圖像 */
PXCMImage image=session.CreateImage(iinfo); 
/* 復制數據 */
PXCMImage.ImageData idata;
image.AcquireAccess(PXCMImage.Access.ACCESS_WRITE, out idata); 
BitmapData bdata = new BitmapData();
bdata.Scan0 = idata.planes[0];
bdata.Stride = idata.pitches[0];
bdata.PixelFormat = PixelFormat.Format32bppRgb;
bdata.Width = bitmap.Width;
bdata.Height = bitmap.Height;
BitmapData bdata2 = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
          ImageLockMode.ReadOnly | ImageLockMode.UserInputBuffer,
          PixelFormat.Format32bppRgb, bdata);
image.ReleaseAccess(idata);
bitmap.UnlockBits(bdata2); 
...... // 對圖像進行其他操作
image.Dispose();
主站蜘蛛池模板: 吴忠市| 眉山市| 双江| 内黄县| 龙井市| 连平县| 清徐县| 平舆县| 台东县| 五家渠市| 卢氏县| 贡山| 芦溪县| 衡东县| 长沙县| 略阳县| 阿勒泰市| 丰台区| 东阿县| 共和县| 霍城县| 宜良县| 老河口市| 二连浩特市| 抚远县| 兴和县| 西贡区| 开化县| 雷州市| 英德市| 湖州市| 潍坊市| 邵阳市| 浦城县| 扎赉特旗| 郑州市| 襄樊市| 湖南省| 梁山县| 洛宁县| 株洲县|