|
Нахожу в тесте вопросы, которые в принципе не освещаются в лекции. Нужно гуглить на других ресурсах, чтобы решить тест, или же он всё же должен испытывать знания, полученные в ходе лекции? |
Самостоятельная работа 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;
}
"