Спонсор: Intel
Опубликован: 20.08.2013 | Уровень: для всех | Доступ: платный | ВУЗ: Новосибирский Государственный Университет
Самостоятельная работа 6:

Сравнение производительности некоторых алгоритмов в библиотеках OpenCV и IPP

< Самостоятельная работа 5 || Самостоятельная работа 6: 1234567
2.6.4. Функция вычисления гистограммы

Вычислить гистограмму для многоканального изображения, можно используя функции IPP вида ippiHistogramRange_<mod>. Как и ранее в нашем случае mod – 8u_C3R. Для вызова этой функции необходимо предварительно подготовить:

  • параметр pHisto вида

      Ipp32s *pHisto[3]; 
      pHisto[0] = new Ipp32s[kBins + 1]; 
      pHisto[1] = new Ipp32s[kBins + 1]; 
      pHisto[2] = new Ipp32s[kBins + 1];   
              

    для размещения гистограмм по каждому каналу (kBins – число бинов гистограммы),

  • константный параметр pLevels вида

      Ipp32s level1[kBins + 1], level2[kBins + 1], 
        level3[kBins + 1]; 
      const Ipp32s *pLevels[3] = { level1, level2, level3 };   
              

    для указания уровней

      for (i = 0; i < kBins + 1; i++) 
        level1[i] = level2[i] = level3[i] = i;   
              
  • и массив nLevels вида

      int nLevels[3] = {kBins + 1, kBins + 1, kBins + 1};   
              

    для задания числа уровней по каждому каналу.

Смысл параметров pHisto и pLevels для выбранного канала можно проиллюстрировать так: pHisto[k] – это число пикселей изображения, таких что pLevels[k] <= pHisto[k] < pLevels[k+1].

Получим следующий код.

double hist_ipp(const Mat &srcImg, Mat &dstImg) 
{ 
  // количество бинов гистограммы 
  const int kBins = 256; 
  Ipp8u *pSrcData; 
  IppiSize srcSize; 
  int i; 
  Ipp32s level1[kBins + 1], level2[kBins + 1], 
    level3[kBins + 1]; 
  Ipp32s *pHisto[3]; 
  const Ipp32s *pLevels[3] = { level1, level2, level3 }; 
  int nLevels[3] = {kBins + 1, kBins + 1, kBins + 1}; 
  clock_t start, finish; 
 
  pHisto[0] = new Ipp32s[kBins + 1]; 
  pHisto[1] = new Ipp32s[kBins + 1]; 
  pHisto[2] = new Ipp32s[kBins + 1]; 
 
  for (i = 0; i < kBins + 1; i++) 
    level1[i] = level2[i] = level3[i] = i; 
 
  pSrcData = (Ipp8u *)srcImg.data; 
  srcSize.width = srcImg.size().width; 
  srcSize.height = srcImg.size().height; 
 
  start = clock(); 
  ippiHistogramRange_8u_C3R(pSrcData, srcImg.step1(), 
    srcSize, pHisto, pLevels, nLevels); 
  finish = clock(); 
 
  delete [] pHisto[0]; 
  delete [] pHisto[1]; 
  delete [] pHisto[2]; 
 
  return double(finish - start) / CLOCKS_PER_SEC; 
} 
 
      

2.7. Анализ корректности

Для медианного фильтра, эрозии и дилатации результирующие изображения, полученные средствами OpenCV и IPP, можно сравнить попиксельно. Для этого напишем следующую функцию, возвращающую число точек в двух изображениях с несовпадающими значениями.

int compare(const Mat &srcImgOCV, const Mat &srcImgIPP) 
{ 
  int kPoints = 0; 
  int w, h, i, j, idx; 
  w = srcImgOCV.size().width; 
  h = srcImgOCV.size().height; 
  for (i = 0; i < h; i++) 
  { 
    idx = 3 * i * w; 
    for (j = 0; j < w; j++, idx += 3) 
      if (((srcImgOCV.data[idx]-srcImgIPP.data[idx])!=0) 
        ||((srcImgOCV.data[idx+1]- 
          srcImgIPP.data[idx+1])!=0) 
        ||((srcImgOCV.data[idx+2]- 
          srcImgIPP.data[idx+2])!=0)) 
    { 
      kPoints++; 
    } 
  } 
 
  return kPoints; 
}   
    

Осталось добавить в функцию main() фрагмент для проверки корректности.

  int kDiffPoints = 0; 
... 
  // сравнить результаты 
  if (mode < 4) 
  { 
    kDiffPoints = compare(dstImgOCV, dstImgIPP); 
    if (kDiffPoints == 0) 
      printf("OpenCV and IPP give the same result.\n"); 
    else 
      printf("OpenCV and IPP give different results in %d\ 
        points.\n", kDiffPoints); 
  } 
    

Сравнение результатов построения гистограммы средствами OpenCV и IPP предоставляем провести читателю самостоятельно.

2.8. Запуск приложения

С учетом использованных нами функций OpenCV для запуска программы потребуются следующие динамические библиотеки: opencv_core242.dll, opencv_highgui242.dll, opencv_imgproc242.dll, tbb.dll.

Первые три располагаются в папке build\x86\vc10\bin\. Последняя – в build\common\tbb\ia32\vc10\.

Использование функций IPP предполагает, что следующий путь должен быть известен операционной системе "C:\Program Files (x86)\Intel\Composer XE 2013\redist\ia32\ipp\".

Собственно запуск можно выполнить, используя командную строку вида

OpenCVvsIPP.exe Desert.jpg 1

< Самостоятельная работа 5 || Самостоятельная работа 6: 1234567
Александра Максимова
Александра Максимова

При прохождении теста 1 в нем оказались вопросы, который во-первых в 1 лекции не рассматривались, во-вторых, оказалось, что вопрос был рассмаотрен в самостоятельно работе №2. Это значит, что их нужно выполнить перед прохождением теста? или это ошибка?
 

Алена Борисова
Алена Борисова

В лекции по обработке полутоновых изображений (http://www.intuit.ru/studies/courses/10621/1105/lecture/17979?page=2) увидела следующий фильтр:


    \begin{array}{|c|c|c|}
    \hline \\
    0 & 0 & 0 \\
    \hline \\
    0 & 2 & 0 \\
    \hline \\
    0 & 0 & 0 \\
    \hline 
    \end{array} - \frac{1}{9} \begin{array}{|c|c|c|}
    \hline \\
    0 & 0 & 0 \\
    \hline \\
    0 & 1 & 0 \\
    \hline \\
    0 & 0 & 0 \\
    \hline 
    \end{array}

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

Что вижу я в конструкции фильтра (скорее всего ошибочно): F(x, y) = 2 * I(x, y) - 1/9 I(x, y) = 17/9 * I(x, y), где F(x, y) - яркость отфильтрованного пикселя, а I(x, y) - яркость исходного пикселя с координатами (x, y). Что означает обычное повышение яркости изображения, при этом без учета соседних пикселей (так как их множители равны 0).

Объясните, пожалуйста, как данный фильтр может повышать четкость изображения?

Сергей Кротов
Сергей Кротов
Россия
Дмитрий Донсков
Дмитрий Донсков
Россия, Москва, Московский Авиационный Институт