2012-01-18

Filtr Mitchell

Autorami pracy, która opisuje filtr są Mitchell i Netravali. Filtr zwyczajowo jednak określa się mianem filtru Mitchell-a. Równania filtru:

$ F(x) = \frac{1}{6} \begin{cases} \ (12-9B-6C)|x|^3 + (12B+6C-18)x^2 + (6-2B) & | x | < 1 \\ (-B-6C)|x|^3 + (6B+30C)x^2 + (-12B-48C)|x| + (8B+24C) & 1 \le |x|<2 \\ 0 & |x|>2 \end{cases}$

Filtr jest parametryzowny poprzez B i C. Zaleca się by B i C spełniało równanie: $B+2C=1$. Typowe wartości powszechnie używane to $B=^1/_3$ i $C=^1/_3$. Stanowią one dobry kompromis pomiędzy rozmyciem, a oscylacjami (ringing). Poniżej rysunek z oryginalnej pracy na której zaznaczono eksperymentalne wyniki subiektywnych odczuć grupy badanej.


Punktem wyjścia do genezy filtru było wyjście od generalnej postaci filtru bicubicznego, czyli złożenia dwóch wielomianów trzeciego stopnia dla zakresów wartości jak w definicji filtru. Każdy taki wielomian ma cztery współczynniki. Następnie zakładając, że w punkcie x=1 filtr powinien być ciągły, pochodna powinna być ciągła, pole powierzchni pod filtrem powinno być równe jeden $\int_{-2}^2F(x)d x=1$. Po nałożeniu tych warunków liczba parametrów redukuje się do dwóch: B i C.

Filtr ten obszar o ujemnych wartościach. Czyli posiada właściwości wyostrzające. W specyficznych warunkach wartość odfiltrowanego punktu może być ujemna.

Wygląd filtru dla kilku typowych wartości B i C:


Pole pod wykresem filtrów to 1. Dzięki czemu filtr ten nie zmienia energii sygnału.

Kod użyty do generacji tego wykresu:

x = linspace(-2, 2, 1000);

ym1 = mitchell(1/3, 1/3);
ym2 = mitchell(1, 0);
ym3 = mitchell(0, 0.5);
ym4 = mitchell(3/2, 1/3);

trapz(x, ym1)
trapz(x, ym2)
trapz(x, ym3)
trapz(x, ym4)

figure(3);
hold on;
title('mitchell - spatial');
plot(x, ym1, 'r');
plot(x, ym2, 'g');
plot(x, ym3, 'b');
plot(x, ym4, 'c');
legend('B=1/3, C = 1/3', 'B=1, C=0', 'B=0, C=0.5', 'A=3/2, B=1/3');

function [y] = mitchell(B, C)

    y = zeros(1, size(x, 2));

    for i=1:size(y, 2)

        xx = abs(x(i));
        x2 = xx * xx;

        if (xx < 1)

            y(i)= (12 - 9 * B - 6 * C) * x2 * xx + ...
                (12 * B + 6 * C - 18) * x2 + ...
                (6 - 2 * B);

        elseif (xx <= 2)

            y(i)= (-B - 6 * C) * x2 * xx + ...
                (6 * B + 30 * C) * x2 + ...
                (-12 * B - 48 * C) * xx + ...
                (8 * B + 24 * C);
        end

        y(i) = y(i) / 6;
    end
end

Przykładowy kod w C#:

public class MitchellFilter : Filter
{
    public double B = 1.0 / 3.0;
    public double C = 1.0 / 3.0;

    public override double Ray
    {
        get
        {
            return 2;
        }
    }

    public override double Evaluate(double a_value)
    {
        double v = Math.Abs(a_value);

        if (a_value >= 2)
            return 0;
        if (a_value < -2)
            return 0;

        double v2 = v * v;

        if (v > 1)
        {
            return (1.0 / 6.0) * (
                (-B - 6 * C) * v2 * v +
                (6 * B + 30 * C) * v2 +
                (-12 * B - 48 * C) * v +
                8 * B + 24 * C);
        }
        else
        {
            return (1.0 / 6.0) * (
                (12 - 9 * B - 6 * C) * v2 * v +
                (12 * B + 6 * C - 18) * v2 +
                6 - 2 * B);
        }
    }
}

Brak komentarzy:

Prześlij komentarz