OpenCV: в поисках менее ресурсоемкого захвата кадров + изменения размера и в буферный режим: как оптимизировать мой код? - PullRequest
0 голосов
/ 13 ноября 2010

Итак, я создал функцию (C ++)

void CaptureFrame(char* buffer, int w, int h, int bytespan)
{
 /* get a frame */
 if(!cvGrabFrame(capture)){              // capture a frame 
  printf("Could not grab a frame\n\7");
  //exit(0);
 }
 CVframe =cvRetrieveFrame(capture);           // retrieve the captured frame

 /* always check */
 if (!CVframe)
 {
  printf("No CV frame captured!\n");
  cin.get();
 }

 /* resize buffer for current frame */
 IplImage* destination = cvCreateImage(cvSize(w, h), CVframe->depth, CVframe->nChannels);

 //use cvResize to resize source to a destination image
 cvResize(CVframe, destination);

 IplImage* redchannel = cvCreateImage(cvGetSize(destination), 8, 1);
 IplImage* greenchannel = cvCreateImage(cvGetSize(destination), 8, 1);
 IplImage* bluechannel = cvCreateImage(cvGetSize(destination), 8, 1);

 cvSplit(destination, bluechannel, greenchannel, redchannel, NULL);
 for(int y = 0; y < destination->height; y++)
 {
  char* line = buffer + y * bytespan;
  for(int x = 0; x < destination->width; x++)
  {
   line[0] = cvGetReal2D(redchannel, y, x);
   line[1] = cvGetReal2D(greenchannel, y, x);
   line[2] = cvGetReal2D(bluechannel, y, x);
   line += 3;
  }
 }
 cvReleaseImage(&redchannel);
 cvReleaseImage(&greenchannel);
 cvReleaseImage(&bluechannel);
 cvReleaseImage(&destination);
}

Поэтому обычно он захватывает кадр с устройства, создает кадр для изменения размера и копирует его в буфер (RGB или YUV420P мне необходимы).

Так что мне интересно, что я делаю неправильно, потому что моя функция интенсивно использует 2 процессора и что можно сделать, чтобы это исправить?

Обновление:

Моя функция запущенав потоке:

     void ThreadCaptureFrame()
    {
        while(1){
        t.restart();
        CaptureFrame((char *)frame->data[0], videoWidth, videoHeight, frame->linesize[0]);
        AVFrame* swap = frame;
        frame = readyFrame;
        readyFrame = swap;
        spendedTime = t.elapsed();
        if(spendedTime < desiredTime){
            Sleep(desiredTime - spendedTime);
        }
    }
 }

, который запускается в начале int main (после некоторой инициализации):

boost::thread workerThread(ThreadCaptureFrame);

Так что если он может работать 24 раза в секунду, он съедает 28% основного квад.Разрешение камеры, которое я снимаю, составляет 320x240.Итак: как это оптимизировать?

Ответы [ 3 ]

1 голос
/ 14 ноября 2010
  1. Во-первых, не выделяйте и не высвобождайте изображения для каждого кадра!Это, вероятно, занимает больше всего времени.Распределите все свои IplImage заранее и выпускайте их только тогда, когда ваше приложение готово.Вы можете использовать boost::shared_ptr с пользовательским средством удаления, чтобы избежать необходимости помнить о выпуске изображений.
  2. Я не понимаю, почему вы разделяете и почему вы копируете так.Если вы должны скопировать, то просто скопируйте все destination->imageData в buffer.Если это ошибочное заполнение, вы должны делать это в цикле, как вы это делали, но прямо из destination->imageData.Вам не нужно разделять цветовые каналы.
  3. Используйте cvResize с CV_INTER_NN.Это снизит качество изображения, но будет быстрее.
1 голос
/ 13 ноября 2010

Что вы можете сделать:

  • Вместо того, чтобы снимать изображения с камеры с разрешением по умолчанию, выберите необходимое разрешение.
  • Я думаю, вы можете просто установить buffer = destination->imageData

Эти статьи могут быть полезны:

0 голосов
/ 13 ноября 2010

Я не знаком с OpenCV, но если я правильно читаю ваш код, вы:

  1. читаете из буфера камеры в память (1 копирование)
  2. изменение размера изображения (1 копирование)
  3. разбиение изображения на канал RGB (3 копирования)
  4. повторное объединение каналов в буфер (1 копирование)

Iдумаю, что это много ненужного копирования, для каждого кадра вы сделали 6 копий изображения (т.е. если ваше изображение имеет размер 320x240 при 24-битном цвете и 24 кадра в секунду, вы будете перемещаться со скоростью не менее 32 МБ / с, с кадром 1000x1000 выГоворя о половине гигабайта в секунду, обратите внимание, что это очень грубая недооценка обратной стороны конверта, в зависимости от алгоритма изменения размера, может быть выполнено дополнительное копирование, чтение / запись в невыровненную область памяти может потребовать некоторых затрат и т. д., так далее).

Вероятно, вы можете пропустить шаг № 3 и / или № 4, хотя я недостаточно знаком с OpenCV, чтобы предположить, как это сделать.

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