|
При прохождении теста 1 в нем оказались вопросы, который во-первых в 1 лекции не рассматривались, во-вторых, оказалось, что вопрос был рассмаотрен в самостоятельно работе №2. Это значит, что их нужно выполнить перед прохождением теста? или это ошибка? |
Сравнение производительности некоторых алгоритмов в библиотеках OpenCV и IPP
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(). Используем простейший вариант ее вызова с тремя параметрами, при котором применяется квадратный шаблон
.
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 по умолчанию.
