Подтвердить что ты не робот

Как я могу выполнить быструю обработку изображений с камеры iPhone?

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

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

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

4b9b3361

Ответ 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];

}