Низкий FPS при доступе к буферу изображения на iPhone - PullRequest
8 голосов
/ 23 ноября 2010

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

Моя проблема в том, что когда я пытаюсь получить доступ к захваченному буферу, 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 кадров в секунду. Я думаю, потому что изображение такого размера не кэшируется.

В основном мне нужно изображение 96х48. Есть ли простой способ уменьшить выходное изображение с камеры, способ, использующий аппаратное ускорение, чтобы я мог работать с маленьким?

Ответы [ 3 ]

8 голосов
/ 23 ноября 2010

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

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

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

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

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

1 голос
/ 23 ноября 2010

отказ от ответственности: ЭТО ОТВЕТ - УГЛЯ :):

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

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

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 голосов
/ 08 декабря 2010

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

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

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