2

我正在编写一个应用程序来显示 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 的工作原理——我下载了一些示例代码并为我的目的对其进行了修改。

4

1 回答 1

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 上对整个图像执行的任何操作都会有点慢。您可以使用 Accelerate 来帮助进行平均颜色操作,就像您在这里想要的那样。我过去曾使用vDSP_meanv()过平均亮度值,一旦你将它们放在数组中。对于类似的事情,最好从相机中获取 YUV 平面数据,而不是我在此处下拉的 BGRA 值。

我还编写了一个开源框架来使用 OpenGL ES 处理视频,尽管我还没有像你需要的那种图像分析那样的全图像缩减操作。我的直方图生成器可能是最接近你想要做的事情的。

于 2012-05-14T21:43:03.403 回答