альтернатива cvGet2D - PullRequest
       6

альтернатива cvGet2D

1 голос
/ 03 марта 2012

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

В двух словах, мой алгоритм выглядит так:

     //videoFrame is IplImage, 8 bit, 4 channel
     for(int i=0;i<videoFrame.width;i++){
        for(int j=0;j<videoFrame.height;j++){

            CvScalar pixel = cvGet2D(&videoFrame, i, j);

            double red = pixel.val[0];
            double green = pixel.val[1];
            double blue = pixel.val[2];

            //do some math


            if (someCondition) {
                cvSet2D(&videoFrame, i, j, white);
            }
        }       
    }

но я считаю, что звонки cvGet2D(&videoFrame, i, j); и cvSet2D(&videoFrame, i, j, white); действительно дорогие (медленные). Есть ли альтернативный способ быстрее получить доступ к значению красного / зеленого / синего каждого пикселя?

Спасибо!

Ответы [ 4 ]

2 голосов
/ 04 марта 2012

Ответы, предоставленные здесь

Пиксельный доступ в OpenCV 2.2

Etarion (для нового интерфейса, с Mat) и Эндрю (для IplImage, как в вашем случае) чище и быстрее, чем пример, предоставленный johnlinvc, потому что они устраняют все ненужные приведения и получают доступ к пикселям в порядке строк, сводя к минимуму потери кеша.

И они работают для общего случая, даже для областей интереса (подматрицы).

2 голосов
/ 03 марта 2012

Попробуйте получить доступ к данным напрямую с помощью указателя следующим образом.

for(int i=0;i<videoFrame.width;i++){
  for(int j=0;j<videoFrame.height;j++){
    uchar B =((uchar *)(videoFrame.imageData + j*videoFrame.widthStep))[i*videoFrame.nChannels + 0];                      
    uchar G =((uchar *)(videoFrame.imageData + j*videoFrame.widthStep))[i*videoFrame.nChannels + 1];       
    uchar R =((uchar *)(videoFrame.imageData + j*videoFrame.widthStep))[i*videoFrame.nChannels + 2];       


    //do some math

    ((uchar *)(videoFrame.imageData + j*videoFrame.widthStep))[i*videoFrame.nChannels + 0] = B;
    ((uchar *)(videoFrame.imageData + j*videoFrame.widthStep))[i*videoFrame.nChannels + 1] = G;
    ((uchar *)(videoFrame.imageData + j*videoFrame.widthStep))[i*videoFrame.nChannels + 2] = R;

  }
}
1 голос
/ 03 марта 2012

Общее лекарство от неэффективности из-за поиска во время выполнения - переместить этот поиск во время компиляции.

Определить шаблон итератора пикселей. Перед зацикливанием и, возможно, даже перед генерацией кадра, получают итератор пикселей, соответствующий характеристикам кадров изображения. Затем используйте этот итератор для доступа к пикселям.

В основном вы можете обойтись с помощью последовательного доступа. Обязательно реализуйте итератор так, чтобы логический последовательный доступ соответствовал последовательному доступу на уровне необработанных байтов. Это помогает (а не потому, что текущий код несовместим с) стратегиями кэширования оборудования.

1 голос
/ 03 марта 2012

В дополнение к ответу johnlinvc, возможно, будет хорошей идеей поменять местами итерации i и j, чтобы вы могли получить непрерывный доступ к элементам изображения, поскольку OpenCV хранит изображения в главном порядке строк.

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