Нахожу в тесте вопросы, которые в принципе не освещаются в лекции. Нужно гуглить на других ресурсах, чтобы решить тест, или же он всё же должен испытывать знания, полученные в ходе лекции? |
Самостоятельная работа 5: Сборка и установка Intel® Integrated Performance Primitives. Использование библиотеки в среде Microsoft® Visual Studio
4. Разработка приложения для медианной фильтрации с использованием библиотеки Intel® Integrated Performance Primitives
4.1. Постановка задачи
Фильтрация изображения – одна из наиболее типичных операций обработки изображений. Медианный фильтр – простейший фильтр, который позволяет удалить шумы, либо выполнить размытие изображения. Медианный фильтр строится подобно линейному фильтру. Выбирается некоторый шаблон, который накладывается на каждый пиксель изображения, в соответствии с шаблоном определяется новое значение интенсивности. Набор интенсивностей пикселей, которые накрыты шаблоном, сортируются, и выбирается интенсивность, находящаяся в середине отсортированного множества. По сути, определяется медиана в отсортированном наборе данных.
Задача первой части лабораторной работы состоит в том, чтобы разработать приложение, которое отвечает следующим требованиям:
- Поддержка медианной фильтрации с использованием библиотеки OpenCV.
- Поддержка медианной фильтрации средствами библиотеки Intel® IPP.
- Проверка корректности результата медианной фильтрации, полученного с помощью реализации на базе Intel® IPP, посредством сравнения с результатом работы соответствующей функции библиотеки OpenCV.
Условимся, что на входе программы имеется цветное изображение в формате RGB и размер шаблона медианного фильтра.
4.2. Общая структура приложения и основной функции
Приложение состоит из основной функции и модуля median_filtering, содержащего пару функций-оберток, которые реализуют медианную фильтрацию средствами библиотек Intel® IPP и OpenCV соответственно.
Рассмотрим структуру основной функции. На входе программы имеется цветное изображение и размер шаблона фильтра, поэтому функция имеет два параметр командной строки – название файла изображения и величину стороны шаблона фильтра (необязательный параметр). Основная функция включает выполнение нескольких действий:
- Загрузка исходного изображения с использованием функции imread библиотеки OpenCV.
- Вызов функции медианной фильтрации median_opencv, реализованной в модуле median_filtering, которая по существу является оберткой соответствующей операции OpenCV.
- Вызов функции median_ipp, также реализованной в модуле median_filtering. Функция выполняет медианную фильтрацию средствами библиотеки Intel® IPP.
- Попиксельное сравнение результатов медианной фильтрации с помощью функции compare, которая объявлена и реализована в модуле median_filtering. Функция возвращает количество пикселей с различающимися цветами (проверка выполняется по трем каналам).
- Отображение отфильтрованных изображений.
- Освобождение ресурсов, использованных для работы с изображениями.
#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.
- srcImg.data – указатель на область памяти, содержащую исходное изображение.
- srcImg.step1() – шаг, с которым необходимо выполнять проход от начала массива цветов исходного изображения, чтобы обратиться к элементу следующей строки.
- ippSrcSize – размер исходного изображения.
- pSrcData – указатель на область памяти, в которую будет записано результирующее изображение с продублированной границей.
- srcImg.step1() + 3 * 2 * borderSize – шаг, с которым необходимо выполнять проход от начала массива цветов результирующего изображения, чтобы обратиться к элементу следующей строки (коэффициент 3 обозначает количество каналов, коэффициент 2 возникает в результате дублирования слева и справа от границы изображения).
- ippDstSize – размер результирующего изображения.
- borderSize – размер границы по вертикали.
- 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.
- 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 – ведущая позиция (определяется в системе координат, связанной с левым правым углом шаблона).
На данном этапе необходимо скопировать область интереса, соответствующую размерам исходного изображения, в результирующее изображение посредством вызова функции 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; }