Как я могу сделать быструю обработку изображений с камеры iPhone? - PullRequest
12 голосов
/ 09 марта 2011

Я пытаюсь написать приложение для iPhone, которое будет выполнять некоторую обработку изображений с камеры в реальном времени. В качестве отправной точки я использовал пример, представленный в документации AVFoundation: установление сеанса захвата, создание UIImage из данных буфера выборки, затем рисование изображения в точке с помощью -setNeedsDisplay, которую я вызываю в главном потоке.

Это работает, но это довольно медленно (50 мс на кадр, измеряется между -drawRect: вызовами, для предустановки 192 x 144), и я видел приложения в App Store, которые работают быстрее, чем эта.
Около половины моего времени уходит на -setNeedsDisplay.

Как я могу ускорить обработку этого изображения?

Ответы [ 2 ]

21 голосов
/ 09 марта 2011

Как отмечает Стив, в моем ответе здесь я призываю людей взглянуть на OpenGL ES для лучшей производительности при обработке и рендеринге изображений на экран с камеры iPhone. Причина этого в том, что использование Quartz для постоянного обновления UIImage на экране - довольно медленный способ отправки необработанных данных пикселей на дисплей.

Если возможно, я рекомендую вам обратиться к OpenGL ES, чтобы выполнить вашу фактическую обработку, потому что хорошо настроенные графические процессоры предназначены для такой работы. Если вам необходимо поддерживать совместимость с OpenGL ES 1.1, ваши возможности обработки намного более ограничены, чем у программируемых шейдеров 2.0, но вы все равно можете выполнить некоторые базовые настройки изображения.

Даже если вы выполняете всю обработку изображений с использованием необработанных данных на ЦП, вам все равно будет намного лучше, если использовать текстуру OpenGL ES для данных изображений, обновляя ее с каждым кадром. Вы увидите скачок в производительности, просто переключившись на этот маршрут рендеринга.

(Обновление: 18.02.2012). Как я описал в своем обновлении к ответу, приведенному выше, я значительно упростил этот процесс с моей новой открытой GPUImage инфраструктурой. Это обрабатывает все взаимодействия OpenGL ES для вас, так что вы можете просто сфокусироваться на применении фильтров и других эффектов, которые вы хотели бы использовать во входящем видео. Это где-то в 5-70 раз быстрее, чем выполнять эту обработку с использованием подпрограмм с привязкой к ЦП и обновлений отображения вручную.

5 голосов
/ 10 марта 2011

Установите для 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];

}



Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...