2010-11-23 74 views
8

我正試圖在iPhone上做一些圖像處理。我使用http://developer.apple.com/library/ios/#qa/qa2010/qa1702.html來捕捉相機幀。訪問iPhone視頻輸出圖像緩衝區時的低FPS

我的問題是,當我試圖訪問捕獲的緩衝區時,相機FPS從30下降到20左右。有誰知道我該如何修復它?

我使用kCVPixelFormatType_32BGRA格式的最低捕獲質量(AVCaptureSessionPresetLow = 192x144)。如果有人知道我可以使用的質量較低,我願意嘗試。

當我在其他平臺(如Symbian)上進行相同的圖像訪問時,它可以正常工作。

這裏是我的代碼:

#pragma mark - 
#pragma mark AVCaptureSession delegate 
- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
    fromConnection:(AVCaptureConnection *)connection 
{ 
/*We create an autorelease pool because as we are not in the main_queue our code is 
    not executed in the main thread. So we have to create an autorelease pool for the thread we are in*/ 
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
//Lock the image buffer 
    if (CVPixelBufferLockBaseAddress(imageBuffer, 0) == kCVReturnSuccess) 
    { 

    // calculate FPS and display it using main thread 
    [self performSelectorOnMainThread:@selector(updateFps:) withObject: (id) nil waitUntilDone:NO]; 


    UInt8 *base = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); //image buffer start address 

    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    int size = (height*width); 
    UInt8* pRGBtmp = m_pRGBimage; 

     /* 
     Here is the problem; m_pRGBimage is RGB image I want to process. 
     In the 'for' loop I convert the image from BGRA to RGB. As a resault, the FPS drops to 20. 
     */ 
    for (int i=0;i<size;i++) 
    { 
    pRGBtmp[0] = base[2]; 
    pRGBtmp[1] = base[1]; 
    pRGBtmp[2] = base[0]; 
    base = base+4; 
    pRGBtmp = pRGBtmp+3;  
    } 


    // Display received action 
    [self performSelectorOnMainThread:@selector(displayAction:) withObject: (id) nil waitUntilDone:NO]; 
    //[self displayAction:&eyePlayOutput]; 
    //saveFrame(imageBuffer); 

    //unlock the image buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

} 


[pool drain]; 
} 

作爲後續的答案,我需要實時處理圖像,它被顯示出來。

我注意到,當我使用AVCaptureSessionPresetHigh,最簡單的事我做的,如:

for (int i=0;i<size;i++) 
    x = base[0]; 

導致幀率下降到4-5 FPS。我猜是因爲這個尺寸的圖像沒有被緩存。

基本上我需要96x48圖像。有沒有一種簡單的方法來縮小相機輸出圖像,這是一種使用硬件加速的方式,所以我可以使用小圖像?

回答

8

凡是每個像素遍歷圖像中的將是所有,但最快的iOS設備相當緩慢的優先問題。例如,我用一個簡單的每像素顏色測試對基於640 x 480視頻幀(307,200像素)中的每個像素進行基準測試,發現這僅在iPhone 4上以大約4 FPS運行。

您是看你的情況下,處理27,648像素,它應該足夠快,以在iPhone 4上達到30 FPS,但這是一個比原始iPhone和iPhone 3G更快的處理器。 iPhone 3G可能仍然會遇到這種處理負擔。你也不會說你的Symbian設備處理器有多快。

我建議重做你的處理算法,以避免顏色空間轉換。應該不需要重新排列顏色組件以便處理它們。

另外,您可以通過在圖像的行和列內以特定間隔進行採樣來選擇性地僅處理幾個像素。最後,如果您針對的是支持OpenGL ES 2.0(iPhone 3G S及更新版本)的較新iOS設備,則可能需要考慮使用GLSL片段着色器來完全在GPU上處理視頻幀。我描述了過程here,以及用於實時基於顏色的對象跟蹤的示例代碼。在我的基準測試中,GPU可以處理比CPU快14 - 28倍的處理速度。

1

免責聲明:這個答案是猜測:)

而緩衝區被鎖定你做了很多工作;這是否阻擋了從相機捕捉圖像的線程?

你,你可以將數據複製出來的緩衝區,而你在它的工作,所以你可以當它是一個的阻礙了捕獲那麼這應該有助於鎖定儘快解鎖即像

if (CVPixelBufferLockBaseAddress(imageBuffer, 0) == kCVReturnSuccess) { 
    // Get the base address and size of the buffer 
    UInt8 *buffer_base = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); //image buffer start address 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Copy it's contents out 
    Uint8 *base = malloc(width * height * 4); 
    memcpy(base, buffer_base, size); 

    // Unlock the buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

    // base now points to a copy of the buffers' data - do what you want to it . . . 
    ... 

    // remember to free base once you're done ;) 
    free(base); 

注意:如果你知道所有的緩衝區大小相同,你可以調用malloc一次來獲取內存,然後每次只重用它,並且只有在完成所有緩衝區的處理時才釋放它。


或者,如果這不是你可以嘗試降低此線程

[NSThread setThreadPriority:0.25]; 
+0

我同意這很可能是拖慢整個捕獲速度的緩慢處理,但我不確定早期簡單釋放鎖定會有很大幫助。爲了處理30 FPS的幀,每幀的回調需要在不到1/30秒的時間內完成。如果沒有,處理操作會阻塞它們正在運行的線程。 – 2010-11-23 19:29:07

+0

如果它作爲生產者 - >消費者模式工作 - 回調會被排隊 - 這一切都取決於他對修改後的圖像所做的操作。如果只是保存它然後嘿,讓它在某處緩衝。如果它被顯示,那麼他有一個問題:) – deanWombourne 2010-11-24 11:32:20

0

將攝像機幀的內容複製到專用緩衝區並從那裏進行操作。這導致我的體驗大幅提升。我最好的猜測是,相機框架所在的內存區域具有特殊的保護功能,使讀/寫訪問變慢。

檢出攝像機幀數據的內存地址。在我的設備上,相機緩衝區位於0x63ac000。這對我來說並不意味着什麼,除了其他堆對象的地址更接近0x1300000。鎖定建議並未解決我的放緩問題,但memcpy確實如此。