2012-05-14 44 views
2

我正在編寫一個應用程序來顯示iphone相機看到的光照條件的統計數據。我每秒都會拍攝一張照片,並在其上進行計算。從iphone上的視頻輸出中獲取靜止圖像?

要拍攝圖像,我使用下面的方法:

-(void) captureNow 
{ 
    AVCaptureConnection *videoConnection = nil; 
    for (AVCaptureConnection *connection in captureManager.stillImageOutput.connections) 
    { 
     for (AVCaptureInputPort *port in [connection inputPorts]) 
     { 
      if ([[port mediaType] isEqual:AVMediaTypeVideo]) 
      { 
       videoConnection = connection; 
       break; 
      } 
     } 
     if (videoConnection) { break; } 
    } 

    [captureManager.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) 
    { 
     NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; 
     latestImage = [[UIImage alloc] initWithData:imageData]; 
    }]; 
} 

然而,captureStillImageAsynhronously....方法將導致通過電話,這是不利於我的應用程序中播放的「快門」聲,它會不斷捕捉圖像。

我讀過,它是不可能禁用此音效。相反,我想從手機視頻輸入捕捉幀:

AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backFacingCamera] error:nil]; 

,並希望把這些變成UIImage對象。

我該怎麼做到這一點?我不太瞭解AVFoundation的工作原理 - 我下載了一些示例代碼,並將其修改用於我的目的。

回答

5

請勿爲此使用靜態照相機。相反,從設備的視頻攝像頭抓取並處理您獲得的像素緩衝區中的數據,以作爲AVCaptureVideoDataOutputSampleBufferDelegate的響應。

您可以使用類似的代碼進行視頻連接如下:

// Grab the back-facing camera 
AVCaptureDevice *backFacingCamera = nil; 
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; 
for (AVCaptureDevice *device in devices) 
{ 
    if ([device position] == AVCaptureDevicePositionBack) 
    { 
     backFacingCamera = device; 
    } 
} 

// Create the capture session 
captureSession = [[AVCaptureSession alloc] init]; 

// Add the video input 
NSError *error = nil; 
videoInput = [[[AVCaptureDeviceInput alloc] initWithDevice:backFacingCamera error:&error] autorelease]; 
if ([captureSession canAddInput:videoInput]) 
{ 
    [captureSession addInput:videoInput]; 
} 

// Add the video frame output 
videoOutput = [[AVCaptureVideoDataOutput alloc] init]; 
[videoOutput setAlwaysDiscardsLateVideoFrames:YES]; 
[videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; 

[videoOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; 

if ([captureSession canAddOutput:videoOutput]) 
{ 
    [captureSession addOutput:videoOutput]; 
} 
else 
{ 
    NSLog(@"Couldn't add video output"); 
} 

// Start capturing 
[captureSession setSessionPreset:AVCaptureSessionPreset640x480]; 
if (![captureSession isRunning]) 
{ 
    [captureSession startRunning]; 
}; 

然後,您需要來處理,看起來像下面這樣的委託方法將這些幀:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
    CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(cameraFrame, 0); 
    int bufferHeight = CVPixelBufferGetHeight(cameraFrame); 
    int bufferWidth = CVPixelBufferGetWidth(cameraFrame); 

     // Process pixel buffer bytes here 

    CVPixelBufferUnlockBaseAddress(cameraFrame, 0); 
} 

BGRA圖像的原始像素字節將包含在從CVPixelBufferGetBaseAddress(cameraFrame)開始的數組中。你可以遍歷這些來獲得你想要的值。

但是,您會發現在CPU上的整個圖像上執行的任何操作都會有點慢。您可以使用加速來幫助進行平均顏色操作,就像您在這裏所需的一樣。過去我使用vDSP_meanv()來平均亮度值,一旦你有一個數組。對於這樣的事情,您可能最好從相機抓取YUV平面數據,而不是我在此處拉下的BGRA值。

我也寫過an open source framework來處理使用OpenGL ES的視頻,雖然我還沒有像那裏的圖像分析那樣需要整體圖像縮減操作。我的直方圖生成器可能是最接近我想要做的。

+0

這真的很方便,非常感謝。目前,我只是用stock功能來實現我的應用程序的基礎知識,但是我肯定會在之後檢查你的框架,它看起來非常整齊。 – Oliver

相關問題