|
Нахожу в тесте вопросы, которые в принципе не освещаются в лекции. Нужно гуглить на других ресурсах, чтобы решить тест, или же он всё же должен испытывать знания, полученные в ходе лекции? |
Базовые операции обработки изображений
2. Обзор возможностей модуля imgproc библиотеки OpenCV
2.1. Cвертка и линейные фильтры
Линейные фильтры – семейство самых простых фильтров изображений с точки зрения математического описания [6]. Предположим, что имеется полутоновое изображение I. Тогда любой линейный фильтр определяется вещественнозначной функцией F, заданной на растре. Данная функция называется ядром фильтра, а операция фильтрации выполняется посредством вычисления дискретной свертки:

Как правило, ядро фильтра применяется к некоторой окрестности O точки, поэтому пределы изменения индексов i и j определяются выбранной формой и размером окрестности. Данная окрестность в некоторых источниках называется шаблоном или апертурой. В процессе вычисления свертки выполняется проход по пикселям всего изображения, шаблон накладывается на каждый текущий пиксель посредством совмещения пикселя с конкретной точкой шаблона – ведущей позицией шаблона, после чего вычисляется свертка. Необходимо отдельно обратить внимание на ситуацию, когда текущий пиксель находится на границе изображения. Указанную проблему можно решить несколькими способами:
- Обрезать края, т.е. не проводить фильтрацию для всех граничных пикселей, на которые невозможно наложить шаблон без выхода за пределы изображения.
- Не учитывать в процессе суммирования пиксель, который реально не существует.
- Доопределить окрестности граничных пикселей посредством экстраполяции (например, простым дублированием граничных пикселей).
- Доопределить окрестности граничных пикселей посредством зеркального отражения, т.е. завернуть изображение в тор.
Выбор решения во многом зависит от приложения, так например, зеркальное отражение на практике не совсем естественный способ.
Для вычисления сверток в библиотеке OpenCV присутствует функция filter2D.
void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel,
Point anchor=Point(-1, -1), double delta=0,
int borderType=BORDER_DEFAULT)
Рассмотрим подробнее параметры приведенной функции.
- src – исходное изображение.
- dst – свертка. Имеет такое же количество каналов и глубину, что и исходное изображение.
- ddepth – глубина результирующего изображения. Если на вход функции передано отрицательное значение, то глубина совпадает с глубиной входного изображения.
- kernel – ядро свертки, одноканальная вещественная матрица.
- anchor – ведущая позиция ядра. По умолчанию принимает значение (-1,-1), которое означает, что ведущая позиция расположена в центре ядра.
- delta – константа, которая может быть добавлена к значению интенсивности после фильтрации перед непосредственной записью результата.
- borderType – параметр, определяющий метод дополнения границы, чтобы можно было применять фильтр к граничным пикселям исходного изображения. Принимает любое значение вида BORDER_* за исключением BORDER_TRANSPARENT и BORDER_ISOLATED.
Функция обеспечивает применение произвольного линейного фильтра с ядром kernel к изображению src. Результат фильтрации записывается в массив dst. Если апертура выходит за пределы изображения, то граничные пиксели дополняются в соответствии с методом, указанным в borderType. Новое значение интенсивности пикселя вычисляется по формуле:

В случае многоканального изображения ядро применяется к каждому каналу в отдельности.
Ниже приведен пример использования функции filter2D. Представленная программа обеспечивает загрузку изображения и применение линейного фильтра с вещественным ядром, заданным константой kernel. Также выполняется отображение исходного и результирующего изображений.
#include <stdlib.h>
#include <stdio.h>
#include <opencv2/opencv.hpp>
using namespace cv;
const char helper[] =
"Sample_filter2D.exe <img_file>\n\
\t<img_file> - image file name\n";
int main(int argc, char* argv[])
{
// константы для определения названия окон
const char *initialWinName = "Initial Image",
*resultWinName = "Filter2D";
// константы для хранения ядра фильтра
const float kernelData[] = {-0.1f, 0.2f, -0.1f,
0.2f, 3.0f, 0.2f,
-0.1f, 0.2f, -0.1f};
const Mat kernel(3, 3, CV_32FC1, (float *)kernelData);
// объекты для хранения исходного
// и результирующего изображений
Mat src, dst;
// проверка аргументов командной строки
if (argc < 2)
{
printf("%s", helper);
return 1;
}
// загрузка изображения
src = imread(argv[1], 1);
// применение фильтра
filter2D(src, dst, -1, kernel);
// отображение исходного изображения и
// результата применения фильтра
namedWindow(initialWinName, CV_WINDOW_AUTOSIZE);
imshow(initialWinName, src);
namedWindow(resultWinName, CV_WINDOW_AUTOSIZE);
imshow(resultWinName, dst);
waitKey();
// закрытие окон
destroyAllWindows();
// освобождение ресурсов
src.release();
dst.release();
return 0;
}
Далее на рисунке показан результат работы приведенной программы (рис.9.1, справа). Очевидно, что применение фильтра с ядром, зафиксированным в программной коде (выделено полужирным), привело к уменьшению контраста исходного тестового изображения (рис.9.1, слева).
Отметим, что в случае больших ядер (размера порядка 11x11 пикселей) для вычисления свертки используется быстрое преобразование Фурье, в случае небольших ядер – прямой алгоритм. Также если ядро сепарабельное, т.е. может быть представлено в виде пары ядер, которые могут быть последовательно применены к строкам и столбцам изображения в отдельности, то предусмотрена более эффективная реализация линейного фильтра с использованием функции sepFilter2D . При вызове данная функция требует явного указания двух одномерных ядер rowKernel и columnKernel.
void sepFilter2D(const Mat& src, Mat& dst, int ddepth,
const Mat& rowKernel,
const Mat& columnKernel,
Point anchor=Point(-1, -1),
double delta=0,
int borderType=BORDER_DEFAULT)

"