Новосибирский Государственный Университет
Опубликован: 20.08.2013 | Доступ: свободный | Студентов: 858 / 36 | Длительность: 14:11:00
Самостоятельная работа 6:

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

< Самостоятельная работа 5 || Самостоятельная работа 6: 1234567

2.5. Реализация операций с использованием функционала библиотеки OpenCV

Первые три задачи из выбранных нами средствами OpenCV решаются очень просто. Рассмотрим их подробнее.

2.5.1. Функция медианной фильтрации

Медианная фильтрация в библиотеке OpenCV реализуется с помощью функции medianBlur(). Ее подробное описание может быть найдено в лабораторной работе "Базовые операции обработки изображений" настоящего курса. Здесь же лишь отметим, что в экспериментах мы будем использовать размер ядра, равный 3, но предусмотрим возможность его изменения.

double median_opencv(const Mat &srcImg, Mat &dstImg, 
  const int kSize = 3); 
 
double median_opencv(const Mat &srcImg, Mat &dstImg, 
  const int kSize) 
{ 
  clock_t start, finish; 
   
  start = clock(); 
  medianBlur(srcImg, dstImg, kSize); 
  finish = clock(); 
 
  return double(finish - start) / CLOCKS_PER_SEC; 
} 
      
2.5.2. Функция вычисления эрозии

Эрозия изображения выполняется в OpenCV с помощью функции erode(). Используем простейший вариант ее вызова с тремя параметрами, при котором применяется квадратный шаблон 3 \times 3.

double erode_opencv(const Mat &srcImg, Mat &dstImg) 
{ 
  clock_t start, finish; 
 
  start = clock(); 
  Mat element = Mat(); 
  erode(srcImg, dstImg, element); 
  finish = clock(); 
 
  return double(finish - start) / CLOCKS_PER_SEC; 
}   
      
2.5.3. Функция вычисления дилатации

Полностью аналогично обстоит дело с функцией дилатации.

double dilate_opencv(const Mat &srcImg, Mat &dstImg) 
{ 
  clock_t start, finish; 
 
  start = clock(); 
  Mat element = Mat(); 
  dilate(srcImg, dstImg, element); 
  finish = clock(); 
 
  return double(finish - start) / CLOCKS_PER_SEC; 
}   
      

За описанием функций erode() и dilate() также отсылаем к лабораторной работе "Базовые операции обработки изображений".

2.5.4. Функция вычисления гистограммы

Для вычисления гистограммы используем часть кода, приведенного в соответствующем разделе лабораторной работы "Базовые операции обработки изображений". Будем строить гистограмму по каждому каналу цветного изображения, предварительно расщепляя его по каналам с помощью функции split().

double hist_opencv(const Mat &srcImg, Mat &dstImg) 
{ 
  Mat bgrChannels[3], bHist, gHist, rHist; 
  // количество бинов гистограммы 
  int kBins = 256; 
  // интервал изменения значений бинов 
  float range[] = {0.0f, 256.0f}; 
  const float* histRange = { range }; 
  // равномерное распределение интервала по бинам 
  bool uniform = true; 
  // запрет очищения перед вычислением гистограммы 
  bool accumulate = false; 
  clock_t start, finish; 
 
  start = clock(); 
  split(srcImg, bgrChannels); 
  // вычисление гистограммы для каждого канала 
  calcHist(&bgrChannels[0], 1, 0, Mat(), bHist, 1, 
    &kBins, &histRange, uniform, accumulate); 
  calcHist(&bgrChannels[1], 1, 0, Mat(), gHist, 1, 
    &kBins, &histRange, uniform, accumulate); 
  calcHist(&bgrChannels[2], 1, 0, Mat(), rHist, 1, 
    &kBins, &histRange, uniform, accumulate); 
  finish = clock(); 
 
  return double(finish - start) / CLOCKS_PER_SEC; 
}   
      

2.6. Реализация операций с использованием функционала библиотеки Intel IPP

2.6.1. Функция медианной фильтрации

Медианная фильтрация в IPP выполняется при помощи одной из функций вида ippiFilterMedian_<mod>. В случае цветного изображения mod – 3uC3R. Кроме того, в документации к IPP указано, что если мы хотим применить фильтр с шаблоном размера msk, необходимо расширить матрицу изображения на msk / 2 пикселов с каждой стороны. Для расширения используем функцию ippiCopyReplicateBorder_8u_C3R(). Наконец, после получения "расширенного" отфильтрованного изображения, необходимо выполнить обратную операцию – выделить изображение исходного размера. Это можно сделать, просто скопировав внутреннюю часть расширенной матрицы пикселей с помощью функции ippiCopy_8u_C3R().

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

double median_ipp(const Mat &srcImg, Mat &dstImg, 
  const int msk = 3); 
 
double median_ipp(const Mat &srcImg, Mat &dstImg, 
  const int msk) 
{ 
  const int borderSize = msk / 2; 
  IppiSize mskSize = { msk , msk }; 
  IppiPoint anchor = { msk / 2, msk / 2 }; 
  Mat ippSrcImg, ippDstImg; 
  Size ippImgSize; 
  IppiSize ippSrcSize, ippDstSize; 
  Ipp8u *pSrcData, *pDstData; 
  clock_t start, finish; 
 
  ippImgSize.width = 
    srcImg.size().width + 2 * borderSize; 
  ippImgSize.height = 
    srcImg.size().height + 2 * borderSize; 
  ippSrcImg.create(ippImgSize, srcImg.type()); 
  ippDstImg.create(ippImgSize, srcImg.type()); 
  pSrcData = (Ipp8u *)ippSrcImg.data; 
  pDstData = (Ipp8u *)ippDstImg.data; 
 
  start = clock(); 
  ippSrcSize.width = srcImg.size().width; 
  ippSrcSize.height = srcImg.size().height; 
  ippDstSize.width = 
    srcImg.size().width + 2 * borderSize; 
  ippDstSize.height = 
    srcImg.size().height + 2 * borderSize; 
  ippiCopyReplicateBorder_8u_C3R(srcImg.data, 
    srcImg.step1(), ippSrcSize, 
    pSrcData, srcImg.step1() + 3 * 2 * borderSize, 
    ippDstSize, borderSize, borderSize); 
 
  ippiFilterMedian_8u_C3R(pSrcData + 
    ippImgSize.width * 3 * borderSize + 3 * borderSize, 
    srcImg.step1() + 3 * 2 * borderSize, pDstData + 
    ippImgSize.width * 3 * borderSize + 3 * borderSize, 
    srcImg.step1() + 3 * 2 * borderSize, ippSrcSize, 
    mskSize, anchor); 
  finish = clock(); 
 
  dstImg.create(srcImg.size(), srcImg.type()); 
  pSrcData = pDstData; 
  pDstData = (Ipp8u *)dstImg.data; 
  ippiCopy_8u_C3R(pSrcData + 
    ippImgSize.width * 3 * borderSize + 3 * borderSize, 
    srcImg.step1() + 3 * 2 * borderSize, pDstData, 
  dstImg.step1(), ippSrcSize); 
 
  ippSrcImg.release(); 
  ippDstImg.release(); 
 
  return double(finish - start) / CLOCKS_PER_SEC; 
} 
      

Отметим, что для построения "расширенной" матрицы изображения мы использовали функции OpenCV для работы c типом Mat.

  ippImgSize.width = 
    srcImg.size().width + 2 * borderSize; 
  ippImgSize.height = 
    srcImg.size().height + 2 * borderSize; 
  ippSrcImg.create(ippImgSize, srcImg.type()); 
  ippDstImg.create(ippImgSize, srcImg.type()); 
  pSrcData = (Ipp8u *)ippSrcImg.data; 
  pDstData = (Ipp8u *)ippDstImg.data;   
      

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

Также отметим, что, как и в OpenCV-версии, здесь мы предусмотрели возможность задания ядра произвольного размера, но в экспериментах далее будем использовать значение msk по умолчанию.

< Самостоятельная работа 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).

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