Вернуться наверх
aco.ifmo.ru photonic
вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


Масочная фильтрация

В практике цифровой обработки изображений широко используется некаузальная масочная фильтрация. Ее линейная разновидность является одним из вариантов двумерной КИХ-фильтрации. В этом случае функцию называют маской, которая представляет собой весовых коэффициентов, заданных во всех точках окрестности, обычно симметрично окружающих рабочую точку кадра. Распространенным видом окрестности, часто применяемым на практике, является квадрат размером 3 на 3 элемента с рабочим элементом в центре. Применяют различные разновидности масок, одним из эвристических вариантов является равномерная маска, когда все девять весовых коэффициентов которой равны 1/9. Такой выбор коэффициентов отвечает условию сохранения средней яркости и центрировать изображение в процессе обработки не требуется.

Для выполнения такой процедуры фильтрации библиотека IPL предоставляет функцию iplBlur, которая имеет следующий прототип.

void iplBlur(IplImage* srcImage, IplImage* dstImage, int nCols, int nRows, int anchorX, int anchorY);

где srcImage – указатель на исходное изображение, а dstImage – указатель на изображение, в котором будет сохраняться результат. Остальные параметры используются для формирования маски: nCols - количество столбцов, nRows – количество строк в окрестности рабочей точки (в маске), anchorX и anchorY – координата центра маски. В системе координат маски ее верхнему левому углу соответствует точка с координатами (0,0), а её правому нижнему углу соответствует точка с координатами (nCols-1, nRows-1). Таким образом для маски размером 3 на 3 должна быть координата центра (1,1). Действие этой функции подобно размытию или усреднению интенсивности изображения.

Но основная функция библиотеки IPL, с помощью которой можно выполнять фильтрацию с произвольными масками называется iplConvolve2D, так как выполняет непосредственно процедуру свертки изображения с маской. Для выполнения свертки необходимо выполнить подготовку маски (или ядра свертки) с помощью функции iplCreateConvKernel. Получить ядро сверки, которое будет использоваться при выполнений свертки можно с помощью функции iplGetConvKernel. А после выполнения свертки ядро должно быть удалено с помощью функции iplDeleteConvKernel. Перечисленные выше функции имеют следующие прототипы:

IplConvKernel* iplCreateConvKernel(int nCols, int nRows, int anchorX, int anchorY, int* values, int nShiftR);
void iplGetConvKernel(IplConvKernel* kernel, int* nCols, int* nRows, int* anchorX, int* anchorY, int** values, int* nShiftR);
void iplDeleteConvKernel(IplConvKernel* kernel);

Аргументы nCols и nRows определяют соответственно количество столбцов и строк в окрестности рабочей точки (в маске), anchorX и anchorY – координата центра маски. Аргумент values – представляет собой ссылку на массив, в элементах которого сохранены значения весовых коэффициентов маски. Аргумент nShiftR определяет количество бит для сдвига вправо каждого значения изображения-результата. Аргумент типа IplConvKernel представляет собой структуру, в которой хранятся все параметры необходимые для выполнения фильтрации.

Функция для выполнения свертки (и соответственно масочной фильтрации) имеет следующий прототип:

void iplConvolve2D(IplImage* srcImage, IplImage* dstImage, IplConvKernel** kernel, int nKernels, int combineMethod);

где srcImage – как всегда указатель на исходное изображение, а dstImage – указатель на изображение, в котором будет сохраняться результат. Аргумент kernel – указатель на массив указателей ядер свертки. Количество элементов в этом массиве определяется следующим аргументом nKernels, а то как они будут использоваться определяется последним аргументом combineMethod, который может быть равен одному из следующих значений:

IPL_SUM // результат сверток суммируется
IPL_SUMSQ // суммируются квадраты результатов
IPL_SUMSQROOT // суммируются квадраты результатов а затем вычисляется корень квадратный
IPL_MAX // Выбирается максимальный результат
IPL_MIN // Выбирается минимальный результат

Если аргумент nKernels=1, то аргумент combineMethod игнорируется, так как выполняется одна свертка, результат которой записывается в dstImage. Используя всевозможные ядра фильтрации можно решать не только задачу фильтрации, но и многие другие задачи обработки изображений. Итак, процедура выполнения масочной фильтрации по месту может быть реализована следующим образом:

void MaskFiltering(IplImage* img)
{
// Скопировать исходное изображение во временное
    IplImage* tmp = iplCloneImage(img);

// Подготовить массив ядра свертки
    int one[9] = {1,-1,1,-1,1,-1,1,-1,1};
// Создать ядро свертки
    IplConvKernel* kernel=iplCreateConvKernel(3, 3, 1, 1, one, 0);

// Выполнить свертку
    iplConvolve2D(img, tmp, &kernel, 1, IPL_SUM);

// Удалить ядро свертки
    iplDeleteConvKernel(kernel);

// Освободить память исходного изображения
    iplDeallocate(img, IPL_IMAGE_ALL);

// Скопировать результат в исходное изображение
    img=iplCloneImage(tmp);

// Освободить память временного изображения
    iplDeallocate(tmp, IPL_IMAGE_ALL);
}

Библиотека IPL предоставляет возможность выполнить раздельную свертку по строкам и столбцам с помощью функции, которая имеет прототип:

void iplConvolveSep2D (IplImage* srcImage, IplImage* dstImage, IplConvKernel* xKernel, IplConvKernel* xKernel);

где srcImage – указатель на исходное изображение, а dstImage – указатель на изображение, в котором будет сохраняться результат. Аргументы xKernel и yKernel принимают ядра для выполнения свертки по строкам и столбцам соответственно. Один из этих аргументов может быть равен NULL.

Библиотека IPL также предоставляет возможность выполнить свертку изображения с ранее определенными масками. Это можно сделать с использованием функции, которая имеет следующий прототип:

int iplFixedFilter(IplImage* srcImage, IplImage* dstImage, IplFilter filter);

где srcImage – указатель на исходное изображение, а dstImage – указатель на изображение, в котором будет сохраняться результат. Аргумент filter определяет ядро свертки и может принимать следующие значения:

IPL_PREWITT_3x3_V Градиентный фильтр Превитта (вертикальный)
-1  0  1
-1 0 1
-1 0 1
IPL_PREWITT_3x3_H Градиентный фильтр Превитта (горизонтальный)
 1  1  1
0 0 0
-1 -1 -1
IPL_SOBEL_3x3_V Градиентный фильтр Собеля (вертикальный)
-1  0  1
-2 0 2
-1 0 1
IPL_SOBEL_3x3_H Градиентный фильтр Собеля (горизонтальный)
 1  2  1
0 0 0
-1 -2 -1
IPL_LAPLACIAN_3x3 Фильтр высоких частот Лапласа (3X3)
-1 -1 -1
-1 8 -1
-1 -1 -1
IPL_LAPLACIAN_5x5 Фильтр высоких частот Лапласа (5X5)
-1 -3 -4 -3 -1
-3 0 6 0 -3
-4 6 20 6 -4
-3 0 6 0 -3
-1 -3 -4 -3 -1
IPL_GAUSSIAN_3x3 Фильтр низких частот Гаусса (3X3)
1  2  1
2 4 2
1 2 1
IPL_GAUSSIAN_5x5 Фильтр низких частот Гаусса (5X5)
 2  7  12  7  2
7 31 52 31 7
12 52 127 52 12
7 31 52 31 7
2 7 12 7 2
IPL_HIPASS_3x3 Фильтр высоких частот (3X3)
-1 -1 -1
-1 8 -1
-1 -1 -1
IPL_HIPASS_5x5 Фильтр высоких частот (5X5)
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
-1 -1 24 -1 -1
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
IPL_SHARPEN_3x3 Фильтр повышения резкости
-1 -1 -1
-1 16 -1
-1 -1 -1

Процедура выполнения фильтрации по месту с заранее определенным ядром может быть реализована следующим образом:

void FixedFilter(IplImage* img, IplFilter filter)
{
// Скопировать исходное изображение во временное
    IplImage* tmp = iplCloneImage(img);

// Выполнить фильтрацию
    iplFixedFilter(img, tmp, filter);

// Освободить память исходного изображения
    iplDeallocate(img, IPL_IMAGE_ALL);

// Скопировать результат в исходное изображение
    img = iplCloneImage(tmp);

// Освободить память временного изображения
    iplDeallocate(tmp, IPL_IMAGE_ALL);
}