我怎样才能从iPhone相机快速处理图像?

我正在写一个iPhone应用程序,它将做一些实时的相机image processing。 我使用AVFoundation文档中提供的示例作为出发点:设置捕获会话,从样本缓冲区数据制作UIImage,然后通过-setNeedsDisplay (在主线程中调用)绘制图像。

这是有效的,但速度相当慢(每帧50毫秒,在-drawRect:调用之间测量,对于192 x 144预设),而且我在App Store上看到的应用程序比这更快。
大约一半的时间都花在-setNeedsDisplay

我怎样才能加快这个image processing?

正如Steve指出的那样,在我的回答中,我鼓励人们在使用iPhone相机处理和渲染图像到屏幕上时,最好的性能是看OpenGL ES。 原因是使用Quartz来不断地将UIImage更新到屏幕上是一种相当慢的将原始像素数据发送到显示器的方法。

如果可能的话,我鼓励你看看OpenGL ES做你的实际处理,因为这种工作的GPU是多么好调整。 如果您需要保持OpenGL ES 1.1的兼容性,那么您的处理选项比2.0的可编程着色器更有限,但是您仍然可以进行一些基本的图像调整。

即使使用CPU上的原始数据进行所有image processing,对于图像数据使用OpenGL ES纹理,也可以通过每帧更新。 只要切换到渲染路线,您就会看到性能的飞跃。

(更新:2012年2月18日)正如我在上面链接的答案的更新中所描述的那样,我使用新的开放源代码GPUImage框架使得这个过程变得更加简单。 这将为您处理所有的OpenGL ES交互,所以您可以专注于在传入的video中应用您想要的滤镜和其他效果。 它比用CPU限制例程和手动显示更新进行这种处理的速度快5-70倍。

如下面的示例代码所示,将捕获会话的sessionPresent设置为AVCaptureSessionPresetLow,这将提高处理速度,但来自缓冲区的图像质量较差。



 - (void)initCapture {
     AVCaptureDeviceInput * captureInput = [AVCaptureDeviceInput 
                                           deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] 
                                          误差:无];
     AVCaptureVideoDataOutput * captureOutput = [[AVCaptureVideoDataOutput alloc] init];
     captureOutput.alwaysDiscardsLateVideoFrames = YES; 
     captureOutput.minFrameDuration = CMTimeMake(1,25);
     dispatch_queue_t队列
     queue = dispatch_queue_create(“cameraQueue”,NULL);
     [captureOutput setSampleBufferDelegate:self queue:queue];
     dispatch_release(队列);
     NSString * key =(NSString *)kCVPixelBufferPixelFormatTypeKey; 
     NSNumber * value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA]; 
     NSDictionary * videoSettings = [NSDictionary dictionaryWithObject:value forKey:key]; 
     [captureOutput setVideoSettings:videoSettings]; 
     self.captureSession = [[AVCaptureSession alloc] init];
     [self.captureSession addInput:captureInput];
     [self.captureSession addOutput:captureOutput];
     self.captureSession.sessionPreset = AVCaptureSessionPresetLow;
     / * sessionPresentselect合适的值来获得所需的速度* /

     if(!self.prevLayer){
         self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
     }
     self.prevLayer.frame = self.view.bounds;
     self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
     [self.view.layer addSublayer:self.prevLayer];

 }