Как создать и применить фильтр Гаусса в MATLAB без использования fspecial, imfilter или conv2?

У меня есть следующий код в MATLAB:

I=imread(image);
h=fspecial('gaussian',si,sigma);
I=im2double(I);
I=imfilter(I,h,'conv');
figure,imagesc(I),impixelinfo,title('Original Image after Convolving with gaussian'),colormap('gray');

Как я могу определить и применить фильтр Гаусса к изображению без imfilter, fspecial а также conv2?

1 ответ

Решение

К сожалению, вы не можете использовать некоторые встроенные методы из панели инструментов обработки изображений, чтобы помочь вам выполнить эту задачу. Тем не менее, мы все еще можем сделать то, что вы просите, хотя это будет немного сложнее. Я все еще собираюсь использовать некоторые функции из IPT, чтобы помочь нам сделать то, что вы просите. Кроме того, я собираюсь предположить, что ваше изображение в оттенках серого. Я оставлю это вам, если вы хотите сделать это для цветных изображений.


Создать гауссовскую маску

Что вы можете сделать, это создать сетку из 2D пространственных координат, используя meshgrid это тот же размер, что и маска фильтра Гаусса, которую вы создаете. Я собираюсь предположить, что N странно сделать мою жизнь проще. Это позволит пространственным координатам быть симметричными по всей маске.

Если вы помните, 2D гауссовский может быть определен как:

Масштабный коэффициент перед экспонентой в первую очередь связан с обеспечением того, чтобы площадь под гауссовой составляла 1. Мы будем иметь дело с этой нормализацией другим способом, где мы генерируем гауссовы коэффициенты без масштабного коэффициента, а затем просто суммируем все коэффициенты в маске и разделите каждый элемент на эту сумму, чтобы обеспечить единицу площади.

Предполагая, что вы хотите создать N x N фильтр, и с заданным стандартным отклонением sigma, код будет выглядеть примерно так, с h представляя ваш фильтр Гаусса.

%// Generate horizontal and vertical co-ordinates, where
%// the origin is in the middle
ind = -floor(N/2) : floor(N/2);
[X Y] = meshgrid(ind, ind);

%// Create Gaussian Mask
h = exp(-(X.^2 + Y.^2) / (2*sigma*sigma));

%// Normalize so that total area (sum of all weights) is 1
h = h / sum(h(:));

Если вы проверите это с fspecial для нечетных значений N вы увидите, что маски совпадают.


Фильтруйте изображение

Основы фильтрации изображения - для каждого пикселя входного изображения, вы берете пиксельную окрестность, которая окружает этот пиксель того же размера, что и ваша гауссова маска. Вы выполняете поэлементное умножение с этой пиксельной окрестностью с помощью гауссовой маски и суммируете все элементы вместе. Результирующая сумма - это то, каким будет выходной пиксель в соответствующем пространственном местоположении в выходном изображении. Я собираюсь использовать im2col это займет пиксельные окрестности и превратит их в столбцы. im2col возьму каждый из этих столбцов и создам матрицу, где каждый столбец представляет одну пиксельную окрестность.

Что мы можем сделать дальше, так это взять нашу маску Гаусса и преобразовать ее в вектор-столбец. Затем мы возьмем этот вектор столбцов и скопируем его на столько столбцов, сколько у нас есть из результата im2col чтобы создать... давайте назовем это гауссовой матрицей из-за отсутствия лучшего термина. С этой гауссовой матрицей мы будем делать поэлементное умножение с этой матрицей и с выводом im2col, Как только мы это сделаем, мы можем суммировать по всем строкам для каждого столбца. Лучший способ сделать это поэлементное умножение через bsxfun, и я покажу вам, как его использовать в ближайшее время.

Результатом этого будет ваше отфильтрованное изображение, но это будет один вектор. Вам нужно изменить этот вектор обратно в матрицу col2im чтобы получить наше отфильтрованное изображение. Однако небольшая проблема с этим подходом состоит в том, что он не фильтрует пиксели, где пространственная маска выходит за пределы размеров изображения. Таким образом, вам действительно нужно заполнить границу вашего изображения нулями, чтобы мы могли правильно выполнить наш фильтр. Мы можем сделать это с padarray,

Поэтому наш код будет выглядеть примерно так, в соответствии с вашими переменными, которые вы определили выше:

N = 5; %// Define size of Gaussian mask
sigma = 2; %// Define sigma here

%// Generate Gaussian mask
ind = -floor(N/2) : floor(N/2);
[X Y] = meshgrid(ind, ind);
h = exp(-(X.^2 + Y.^2) / (2*sigma*sigma));
h = h / sum(h(:));

%// Convert filter into a column vector
h = h(:);

%// Filter our image
I = imread(image);
I = im2double(I);
I_pad = padarray(I, [floor(N/2) floor(N/2)]);
C = im2col(I_pad, [N N], 'sliding');
C_filter = sum(bsxfun(@times, C, h), 1);
out = col2im(C_filter, [N N], size(I_pad), 'sliding');

out содержит отфильтрованное изображение после применения маски фильтра Гаусса к входному изображению I, В качестве примера, скажем N = 9, sigma = 4, Давайте также использовать cameraman.tif это изображение, которое является частью системного пути MATLAB. Используя вышеприведенные параметры, а также изображение, мы получаем входное и выходное изображение:

Другие вопросы по тегам