Kształt filtru wywodzi się z funkcji na rozkład normalny:
$f(x)=e^{\displaystyle -\alpha x^2}$
Dla x dążącego do nieskończoności wartość filtru dąży do zera. W naszym przypadku wartość filtra poza promieniem powinna wynosić zera i najlepiej dla eliminacji oscylacji jak x dąży do granicy promienia wartość filtra powinna dążyć do zera. Najprościej możemy to zrobić przesuwając odpowiednio wartości filtru:
$f(x)=e^{\displaystyle -\alpha x^2} - e^{\displaystyle -\alpha r^2}$
Ważną jego cechą jest to, że jest on transformatą Fouriera samego siebie - kształt jest taki sam w czasie jak i w częstotliwości.
Kod w Matlabie potrzebny do generacji wykresów:
function [] = plot_gaussian()
x = linspace(-3, 3, 1000);
ym1 = gaussian(x, 0.5, 2);
ym2 = gaussian(x, 1/sqrt(2), 2);
ym3 = gaussian(x, 1, 2);
ym4 = gaussian(x, 0.5, 4);
trapz(x, ym1)
trapz(x, ym2)
trapz(x, ym3)
trapz(x, ym4)
figure(fig_index);
fig_index = fig_index + 1;
hold on;
title('gaussian - time');
plot(x, ym1, 'r');
plot(x, ym2, 'g');
plot(x, ym3, 'b');
plot(x, ym4, 'c');
legend('alpha = 0.5, ray = 2', 'alpha = 0.7, ray = 2', ...
'alpha = 1, ray = 2', 'alpha = 0.5, ray = 4');
YM1 = fft(ym1, 100000);
YM1 = [YM1(1:1:1000),YM1(end-1000:1:end)];
YM2 = fft(ym2, 100000);
YM2 = [YM2(1:1:1000),YM2(end-1000:1:end)];
YM3 = fft(ym3, 100000);
YM3 = [YM3(1:1:1000),YM3(end-1000:1:end)];
YM4 = fft(ym4, 100000);
YM4 = [YM4(1:1:1000),YM4(end-1000:1:end)];
figure(fig_index);
fig_index = fig_index + 1;
hold on;
title('gaussian - freq');
plot(fftshift(abs(YM1)), 'r');
plot(fftshift(abs(YM2)), 'g');
plot(fftshift(abs(YM3)), 'b');
plot(fftshift(abs(YM4)), 'c');
legend('alpha = 0.5, ray = 2', 'alpha = 0.7, ray = 2', ...
'alpha = 1, ray = 2', 'alpha = 0.5, ray = 4');
end
function [y] = gaussian(x, alpha, ray)
y = zeros(1, size(x, 2));
for i=1:size(y, 2)
if (abs(x(i)) > ray)
y(i) = 0;
else
y(i) = exp(-alpha * x(i) * x(i)) - exp(-alpha * ray * ray);
end
end
end
Przykładowy kod filtra w C#:
public class GaussianFilter : Filter { private double m_exp; private double m_alpha = 0.5; [YAXNode] public double Alpha { get { return m_alpha; } set { m_alpha = value; m_exp = Math.Exp(-m_alpha * Ray * Ray); } } public override double Ray { get { return 2; } } public override double Evaluate(double a_value) { if (a_value >= 2) return 0; if (a_value < -2) return 0; return Math.Exp(-m_alpha * a_value * a_value) - m_exp; } }
Dla naszych zastosowań używanie innego większego promienia nie ma sensu. Filtr taki tylko coraz bardziej rozmywa obraz.
Brak komentarzy:
Prześlij komentarz