Нахожу в тесте вопросы, которые в принципе не освещаются в лекции. Нужно гуглить на других ресурсах, чтобы решить тест, или же он всё же должен испытывать знания, полученные в ходе лекции? |
Самостоятельная работа 6: Сравнение производительности некоторых алгоритмов в библиотеках OpenCV и IPP
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 по умолчанию.
2.6.2. Функция вычисления эрозии
Реализацию функций для вычисления эрозии и дилатации средствами IPP мы выполним несколько по-другому. Дело в том, что представленные выше варианты вызовов функций erode() и dilate() из OpenCV выпол- няют обработку только внутренних пикселей исходного изображения. Таким образом, и в IPP-версии нам нет необходимости расширять матрицу изображения. Вместо этого мы можем соответствующим образом определить область интереса (ROI).
double erode_ipp(const Mat &srcImg, Mat &dstImg) { IppiMaskSize msk; Ipp8u *pSrcData, *pDstData; IppiSize srcSize, dstRoiSize; clock_t start, finish; srcImg.copyTo(dstImg); start = clock(); pSrcData = (Ipp8u *)srcImg.data; pDstData = (Ipp8u *)dstImg.data; srcSize.width = srcImg.size().width; srcSize.height = srcImg.size().height; msk = ippMskSize3x3; dstRoiSize.width = srcImg.size().width - 2; dstRoiSize.height = srcImg.size().height - 2; ippiErode3x3_8u_C3R(pSrcData + srcSize.width * 3 * 1 + 3 * 1, srcImg.step1(), pDstData + srcSize.width * 3 * 1 + 3 * 1, srcImg.step1(), dstRoiSize); finish = clock(); return double(finish - start) / CLOCKS_PER_SEC; }
2.6.3. Функция вычисления дилатации
Реализация функции вычисления дилатации средствами IPP совпадает с таковой для функции эрозии за исключением вызова функции ippiDilate3x3_8u_C3R() вместо ippiErode3x3_8u_C3R().
double erode_ipp(const Mat &srcImg, Mat &dstImg) { IppiMaskSize msk; Ipp8u *pSrcData, *pDstData; IppiSize srcSize, dstRoiSize; clock_t start, finish; srcImg.copyTo(dstImg); start = clock(); pSrcData = (Ipp8u *)srcImg.data; pDstData = (Ipp8u *)dstImg.data; srcSize.width = srcImg.size().width; srcSize.height = srcImg.size().height; msk = ippMskSize3x3; dstRoiSize.width = srcImg.size().width - 2; dstRoiSize.height = srcImg.size().height - 2; ippiDilate3x3_8u_C3R(pSrcData + srcSize.width * 3 * 1 + 3 * 1, srcImg.step1(), pDstData + srcSize.width * 3 * 1 + 3 * 1, srcImg.step1(), dstRoiSize); finish = clock(); return double(finish - start) / CLOCKS_PER_SEC; }