Опубликован: 02.09.2013 | Доступ: свободный | Студентов: 429 / 54 | Длительность: 19:27:00

Самостоятельная работа 5: Сборка и установка Intel® Integrated Performance Primitives. Использование библиотеки в среде Microsoft® Visual Studio

4. Разработка приложения для медианной фильтрации с использованием библиотеки Intel® Integrated Performance Primitives

4.1. Постановка задачи

Фильтрация изображения – одна из наиболее типичных операций обработки изображений. Медианный фильтр – простейший фильтр, который позволяет удалить шумы, либо выполнить размытие изображения. Медианный фильтр строится подобно линейному фильтру. Выбирается некоторый шаблон, который накладывается на каждый пиксель изображения, в соответствии с шаблоном определяется новое значение интенсивности. Набор интенсивностей пикселей, которые накрыты шаблоном, сортируются, и выбирается интенсивность, находящаяся в середине отсортированного множества. По сути, определяется медиана в отсортированном наборе данных.

Задача первой части лабораторной работы состоит в том, чтобы разработать приложение, которое отвечает следующим требованиям:

  1. Поддержка медианной фильтрации с использованием библиотеки OpenCV.
  2. Поддержка медианной фильтрации средствами библиотеки Intel® IPP.
  3. Проверка корректности результата медианной фильтрации, полученного с помощью реализации на базе Intel® IPP, посредством сравнения с результатом работы соответствующей функции библиотеки OpenCV.

Условимся, что на входе программы имеется цветное изображение в формате RGB и размер шаблона медианного фильтра.

4.2. Общая структура приложения и основной функции

Приложение состоит из основной функции и модуля median_filtering, содержащего пару функций-оберток, которые реализуют медианную фильтрацию средствами библиотек Intel® IPP и OpenCV соответственно.

Рассмотрим структуру основной функции. На входе программы имеется цветное изображение и размер шаблона фильтра, поэтому функция имеет два параметр командной строки – название файла изображения и величину стороны шаблона фильтра (необязательный параметр). Основная функция включает выполнение нескольких действий:

  1. Загрузка исходного изображения с использованием функции imread библиотеки OpenCV.
  2. Вызов функции медианной фильтрации median_opencv, реализованной в модуле median_filtering, которая по существу является оберткой соответствующей операции OpenCV.
  3. Вызов функции median_ipp, также реализованной в модуле median_filtering. Функция выполняет медианную фильтрацию средствами библиотеки Intel® IPP.
  4. Попиксельное сравнение результатов медианной фильтрации с помощью функции compare, которая объявлена и реализована в модуле median_filtering. Функция возвращает количество пикселей с различающимися цветами (проверка выполняется по трем каналам).
  5. Отображение отфильтрованных изображений.
  6. Освобождение ресурсов, использованных для работы с изображениями.
#include <opencv2/opencv.hpp> 
#include "median_filtering.h" 
 
using namespace cv; 
 
char helper[] =  
"01_IPP_MedianFiltering.exe <image> [<kernel>]\n\ 
\t<image> - image name\n\ 
\t<kernel> - kernel size\n\ 
"; 
 
int main(int argc, char **argv) 
{ 
    Mat srcImgOCV, srcImgIPP, dstImgOCV, dstImgIPP; 
    int kDiffPoints, kSize = 5; 
    if (argc < 2) 
    { 
        printf("%s", helper); 
        return 1; 
    } 
    if (argc > 2) 
    { 
        kSize = atoi(argv[2]); 
    } 
    // 1. загрузить изображение 
    srcImgOCV = imread(argv[1]); 
    if (srcImgOCV.data == 0) 
    { 
        printf("ERROR!!! imread(...)"); 
        return 1; 
    } 
    srcImgOCV.copyTo(srcImgIPP); 
    // 2. отфильтровать с помощью OpenCV 
    median_opencv(srcImgOCV, dstImgOCV, kSize); 
    // 3. отфильтровать с помощью IPP 
    median_ipp(srcImgIPP, dstImgIPP, kSize); 
    // 4. сравнить результаты фильтрации 
    kDiffPoints = compare(dstImgOCV, dstImgIPP); 
    if (kDiffPoints == 0) 
    { 
        printf("OpenCV and IPP give the same result.\n"); 
    } 
    else 
    {         printf("Number of different points %d\n",  
               kDiffPoints); 
    } 
    // 5. отобразить то, что получилось 
    namedWindow("srcImg"); 
    imshow("srcImg", srcImgOCV); 
    namedWindow("dstImgOCV"); 
    imshow("dstImgOCV", dstImgOCV); 
    namedWindow("dstImgIPP"); 
    imshow("dstImgIPP", dstImgIPP); 
    waitKey();    
    // 6. освободить память 
    srcImgOCV.release(); 
    srcImgIPP.release(); 
    dstImgOCV.release(); 
    dstImgIPP.release(); 
    return 0; 
} 

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

Перейдем к рассмотрению функции median_opencv. По существу функция представляет собой обертку для операции medianBlur библиотеки OpenCV. В качестве входных параметров функция принимает исходное и результирующее изображения srcImg и dstImg, а также размер шаблона медианного фильтра.

int median_opencv(const Mat &srcImg, Mat &dstImg,  
                  const int kSize) 
{ 
    medianBlur(srcImg, dstImg, kSize); 
    return 0; 
} 

4.4. Реализация с использованием функций Intel® Integrated Performance Primitives

Последовательно рассмотрим шаги реализации функции median_ipp. Параметры функции в точности соответствуют тем, что были приведены при описании реализации median_opencv.

В начале функции объявим необходимые переменные.

int 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; 
    

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

    // размер изображения по горизонтали и по вертикали  
    // с дополнительной границей 
    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; 
    

Теперь продублируем граничные пиксели изображения с использованием функции ippiCopyReplicateBorder_8u_C3R.

    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); 
        

Остановимся более подробно на параметрах функции ippiCopyReplicateBorder_8u_C3R.

  1. srcImg.data – указатель на область памяти, содержащую исходное изображение.
  2. srcImg.step1() – шаг, с которым необходимо выполнять проход от начала массива цветов исходного изображения, чтобы обратиться к элементу следующей строки.
  3. ippSrcSize – размер исходного изображения.
  4. pSrcData – указатель на область памяти, в которую будет записано результирующее изображение с продублированной границей.
  5. srcImg.step1() + 3 * 2 * borderSize – шаг, с которым необходимо выполнять проход от начала массива цветов результирующего изображения, чтобы обратиться к элементу следующей строки (коэффициент 3 обозначает количество каналов, коэффициент 2 возникает в результате дублирования слева и справа от границы изображения).
  6. ippDstSize – размер результирующего изображения.
  7. borderSize – размер границы по вертикали.
  8. borderSize – размер границы по горизонтали.

После того, как изображение дополнено границей, можно применить медианный фильтр. Для этого необходимо вызвать функцию ippiFilterMedian_8u_C3R .

    // медианная фильтрация 
    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); 
        

Рассмотрим входные параметры функции ippiFilterMedian_8u_C3R.

  1. pSrcData + ippImgSize.width * 3 * borderSize + 3 * borderSize – указатель на начало области изображения, к которой будет выполняться медианная фильтрация. Второе слагаемое – число элементов, которые дополняют верхнюю границу изображения (дополнительные строки), третье слагаемое – количество дополнительных элементов в начале первой строки исходного изображения.
  2. srcImg.step1() + 3 * 2 * borderSize – шаг, с которым необходимо выполнять проход от начала исходного массива цветов, чтобы обратиться к элементу следующей строки.
  3. pDstData + ippImgSize.width * 3 * borderSize + 3 * borderSize – указатель на начало области, в которую будет записан результат фильтрации. Результат записывается во внутреннюю область результирующего изображения без граничных пикселей.
  4. srcImg.step1() + 3 * 2 * borderSize – шаг, с которым необходимо выполнять проход от начала результирующего массива цветов, чтобы обратиться к элементу следующей строки.
  5. ippSrcSize – размер исходного изображения, включая продублированную границу.
  6. mskSize – размер шаблона медианного фильтра.
  7. anchor – ведущая позиция (определяется в системе координат, связанной с левым правым углом шаблона).

На данном этапе необходимо скопировать область интереса, соответствующую размерам исходного изображения, в результирующее изображение посредством вызова функции ippiCopy_8u_C3R. Первые два параметра определяют указатель на область памяти, где находится результирующее изображение, и шаг, чтобы получить начало следующей строки. pDstData – указатель на блок памяти для записи результата фильтрации, dstImg.step1() – шаг для перехода на следующую строку, ippSrcSize – размер отфильтрованного изображения.

    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 0; 
    
} 
Андрей Терёхин
Андрей Терёхин

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

Демянчик Иван
Демянчик Иван

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

" Искомый объект можно описать с помощью фильтра F= \lbrace f_{x',y'},x' \in \lbrace0, ...,w_f \rbrace , y' \in \lbrace 0,...,h_f \rbrace \rbrace "