2010-11-23 3 views
8

Я пытаюсь выполнить некоторую обработку изображений на iPhone. Я использую http://developer.apple.com/library/ios/#qa/qa2010/qa1702.html для захвата кадров камеры.Низкий FPS при доступе к видеоизображению видеоизображения iPhone

Моя проблема заключается в том, что когда я пытаюсь получить доступ к захваченному буфере, камера FPS падает с 30 до 20. Кто-нибудь знает, как я могу это исправить?

Я использую самое низкое качество захвата, которое я мог найти (AVCaptureSessionPresetLow = 192x144) в формате kCVPixelFormatType_32BGRA. Если кто-то знает более низкое качество, которое я мог бы использовать, я готов попробовать.

Когда я делаю тот же доступ к изображениям на других платформах, таких как Symbian, он работает нормально.

Вот мой код:

#pragma mark - 
#pragma mark AVCaptureSession delegate 
- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
    fromConnection:(AVCaptureConnection *)connection 
{ 
/*We create an autorelease pool because as we are not in the main_queue our code is 
    not executed in the main thread. So we have to create an autorelease pool for the thread we are in*/ 
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
//Lock the image buffer 
    if (CVPixelBufferLockBaseAddress(imageBuffer, 0) == kCVReturnSuccess) 
    { 

    // calculate FPS and display it using main thread 
    [self performSelectorOnMainThread:@selector(updateFps:) withObject: (id) nil waitUntilDone:NO]; 


    UInt8 *base = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); //image buffer start address 

    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    int size = (height*width); 
    UInt8* pRGBtmp = m_pRGBimage; 

     /* 
     Here is the problem; m_pRGBimage is RGB image I want to process. 
     In the 'for' loop I convert the image from BGRA to RGB. As a resault, the FPS drops to 20. 
     */ 
    for (int i=0;i<size;i++) 
    { 
    pRGBtmp[0] = base[2]; 
    pRGBtmp[1] = base[1]; 
    pRGBtmp[2] = base[0]; 
    base = base+4; 
    pRGBtmp = pRGBtmp+3;  
    } 


    // Display received action 
    [self performSelectorOnMainThread:@selector(displayAction:) withObject: (id) nil waitUntilDone:NO]; 
    //[self displayAction:&eyePlayOutput]; 
    //saveFrame(imageBuffer); 

    //unlock the image buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

} 


[pool drain]; 
} 

В последующее к ответам, мне нужно обработать изображение в режиме реального времени, оно отображается.

Я заметил, что когда я использую AVCaptureSessionPresetHigh, самое простое, что я делаю, как:

for (int i=0;i<size;i++) 
    x = base[0]; 

вызывает фреймрейт снизится до 4-5 кадров в секунду. Я предполагаю, потому что изображение в этом размере не кэшируется.

В принципе мне нужно изображение 96x48. есть ли простой способ уменьшить изображение камеры, способ использования аппаратного ускорения, чтобы я мог работать с маленьким?

ответ

8

Все, что перебирает каждый пиксель в изображении будет довольно медленным на всех, кроме самых быстрых IOS устройств. Например, я сравнивал все пиксели в видеокадре 640 x 480 (307,200 пикселей) с простым пиксельным цветовым тестом и обнаружил, что он работает только на 4 FPS на iPhone 4.

Вы глядя на обработку 27 648 пикселей в вашем случае, которая должна работать достаточно быстро, чтобы нанести 30 FPS на iPhone 4, но это гораздо более быстрый процессор, чем тот, который был в оригинальном iPhone и iPhone 3G. IPhone 3G, вероятно, по-прежнему будет бороться с этой нагрузкой на обработку. Вы также не говорите, насколько быстро процессор был на ваших устройствах Symbian.

Я бы предложил переработать алгоритм обработки, чтобы избежать преобразования цветового пространства. Не нужно переупорядочивать цветовые компоненты для их обработки.

Кроме того, вы можете выборочно обрабатывать только несколько пикселей путем выборки с определенными интервалами внутри строк и столбцов изображения.

Наконец, если вы настроитесь на новые устройства iOS, поддерживающие OpenGL ES 2.0 (iPhone 3G S и новее), вам может потребоваться использовать шейдер фрагмента GLSL для обработки видео кадра полностью на графическом процессоре. Я описываю процесс here, а также пример кода для отслеживания объектов на основе цвета в реальном времени. Графический процессор может обрабатывать этот вид обработки в 14 - 28 раз быстрее, чем процессор, в моих тестах.

1

отказа от ответственности: Этот ответ догадки :)

Вы делаете довольно много работы, в то время как буфер заблокирован; это удерживание потока, который захватывает изображение с камеры?

Вы можете скопировать данные из буфера во время работы на нем, так что вы можете открыть его как можно скорее то есть что-то вроде

if (CVPixelBufferLockBaseAddress(imageBuffer, 0) == kCVReturnSuccess) { 
    // Get the base address and size of the buffer 
    UInt8 *buffer_base = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); //image buffer start address 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Copy it's contents out 
    Uint8 *base = malloc(width * height * 4); 
    memcpy(base, buffer_base, size); 

    // Unlock the buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

    // base now points to a copy of the buffers' data - do what you want to it . . . 
    ... 

    // remember to free base once you're done ;) 
    free(base); 

Если это замок, который держит захват, то это должно помочь.

NB Вы можете ускорить это, если знаете, что все буферы будут того же размера, что вы можете просто вызвать malloc один раз, чтобы получить память, а затем просто повторно использовать ее каждый раз и только освобождать ее, когда вы закончили обработку всех буферов ,


Или, если это не проблема, вы можете попробовать уменьшить приоритет этой нити

[NSThread setThreadPriority:0.25]; 
+0

Я согласен, что это, скорее всего, медленная обработка, которая перетаскивает весь снимок, но я не уверен, что простое освобождение блокировки рано сделает много, чтобы помочь. Чтобы иметь дело с кадрами при 30 FPS, обратный вызов для каждого кадра должен завершиться менее чем за 1/30 секунды. Если это не так, операции обработки просто затмевают поток, в котором они работают. – 2010-11-23 19:29:07

+0

Не, если он работал в качестве шаблона производителя-> потребителя - обратные вызовы просто встали в очередь - все зависит от того, что он делает с измененным изображением. Если это просто сохранить его, тогда эй, пусть он будет где-то в буфере. Если он отображается, то у него проблема :) – deanWombourne 2010-11-24 11:32:20

0

Скопируйте содержимое рамки камеры в выделенный буфер и оперируйте его оттуда. Это приводит к значительному увеличению скорости в моем опыте. Мое лучшее предположение заключается в том, что область памяти, в которой находится кадр камеры, имеет специальные защиты, которые затрудняют чтение/запись.

Проверьте адрес памяти данных камеры. На моем устройстве буфер камеры находится в 0x63ac000. Это ничего не значит для меня, за исключением того, что другие объекты кучи находятся в адресах ближе к 0x1300000. Предложение блокировки не решило моего замедления, но memcpy сделал.

Смежные вопросы