Как я могу выполнить быструю обработку изображений с камеры iPhone?
Я пытаюсь написать приложение для iPhone, которое будет выполнять обработку изображений в реальном времени в режиме реального времени. Я использовал пример, представленный в документах AVFoundation, в качестве отправной точки: установка сеанса захвата, создание UIImage из данных буфера образца, а затем рисование изображения в точке через -setNeedsDisplay
, которое я вызываю в основном потоке.
Это работает, но он довольно медленный (50 мс на кадр, измеренный между -drawRect:
вызовами, для 192 x 144 пресетов), и я видел приложения в App Store, которые работают быстрее, чем это.
Примерно половина моего времени проведена в -setNeedsDisplay
.
Как ускорить обработку этого изображения?
Ответы
Ответ 1
Как указывает Стив, в моем ответе здесь я призываю людей взглянуть на OpenGL ES на лучшую производительность при обработке и рендеринге изображений на экране с камеры iPhone, Причина этого заключается в том, что использование Quartz для постоянного обновления UIImage на экране является довольно медленным способом отправки необработанных пиксельных данных на дисплей.
Если возможно, я рекомендую вам взглянуть на OpenGL ES, чтобы сделать вашу фактическую обработку, из-за того, насколько хорошо настроены графические процессоры для такого рода работ. Если вам необходимо поддерживать совместимость с OpenGL ES 1.1, ваши параметры обработки намного более ограничены, чем с 2.0 программируемыми шейдерами, но вы все равно можете выполнить некоторую базовую настройку изображения.
Даже если вы выполняете всю обработку изображений с использованием исходных данных на CPU, вам все равно будет намного лучше, используя текстуру OpenGL ES для данных изображения, обновив их с каждым фреймом. Вы увидите скачок производительности, просто перейдя на этот маршрут рендеринга.
(Обновление: 2/18/2012) Как я описываю в своем обновлении вышеприведенного ответа, я сделал этот процесс намного проще с моим новым открытым исходным кодом GPUImage. Это поможет вам полностью взаимодействовать с OpenGL ES, поэтому вы можете просто сосредоточиться на применении фильтров и других эффектов, которые вы хотите использовать на своем входящем видео. Это где-то от 5-70X быстрее, чем выполнение этой обработки с использованием подпрограмм, связанных с процессором, и обновлений ручного дисплея.
Ответ 2
Установите sessionPresent сеанса захвата в AVCaptureSessionPresetLow, как показано в приведенном ниже примере кода, это увеличит скорость обработки, но изображение из буфера будет низкого качества.
- (void)initCapture {
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput
deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]
error:nil];
AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init] ;
captureOutput.alwaysDiscardsLateVideoFrames = YES;
captureOutput.minFrameDuration = CMTimeMake(1, 25);
dispatch_queue_t queue;
queue = dispatch_queue_create("cameraQueue", NULL);
[captureOutput setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);
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;
/*sessionPresent choose appropriate value to get desired speed*/
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];
}