Neugierig und etwas gelangweilt kam ich heute auf die Idee, auszuprobieren, was wohl passieren würde, wenn man die beiden Supersampling-Verfahren Fliptri und Flipquad als Filter eines bestehenden Bildes interpretiert. Resultat des Abends: Wir reden nicht darüber.
Grundlage
Beiden Verfahren liegt zugrunde, dass zur Erzeugung eines Pixels mehrere umgebende (Sub-)Pixel ausgewertet werden, wobei das Muster der Auswertung für anliegende Bildpunkte horizontal und/oder vertikal gespiegelt — geflippt — wird. Die beiden Verfahren unterscheiden sich dabei lediglich hinsichtlich der Anzahl der Samplingpunkte.
Anschaulicher in der Grafik: Jeweils drei Samplingpunkte (rot) ergeben einen Bildpunkt (blau) bei Fliptri; Bei Flipquad sind es vier Samplingpunkte pro Bildpunkt.
Der resultierende Bildpunkt B ist dabei schlichtweg die gewichtete Summe aller Samplingpunkte S:
\begin{align}
B = \frac{1}{N} \sum \limits_{i=1}^N S_i
\end{align}
Implementierung in Matlab
Fliptri
Zu jedem Punkt müssen drei umgebende Pixel aufgenommen werden. Im ungespiegelten Fall liegen diese an den Koordinaten (x-1, y-1)
, (x, y+1)
und (x+1, y)
. Wie aus der Abbildung zu erkennen ist, müssen die X- und Y-Koordinaten (genauer: Deren Offsets -1
, 0
und +1
) für jede gerade Zeile gespiegelt werden, was man durch folgenden Kunstgriff erreicht:
x_sample = x_offset*(-1)^x + x; y_sample = y_offset*(-1)^y + y;
Der Rest ist schnell erledigt:
function pixel = fliptri(x, y, rgb) % 1 2 3 % +---+---+---+ % | X | | | % +---+---+---+ % | | | X | % +---+---+---+ % | | X | | % +---+---+---+ coords = [ -1 0 +1; % X -1 +1 0]; % Y N = length(coords); % Flip sgn_x = (-1)^x; sgn_y = (-1)^y; % Sample for s=1:N sample(s, 1:3) = rgb( ... x+coords(1,s)*sgn_x, ... y+coords(2,s)*sgn_y, ... 1:3); end % Combine pixel = sum(sample) / N; end
Zuletzt muss das Bild noch geladen und gefiltert werden. (Da die Größe des gedachten Filterkernels der Größe drei entspricht, müssen die Start- und Endindizes jeweils um den Wert 1 reduziert werden.)
% Load the image rgb = imread('aliased.png'); % Sample the image imagesize = size(rgb); width = imagesize(1); height = imagesize(2); rgb_sampled = uint8(zeros(imagesize)); for y=2:height-1 for x=2:width-1 rgb_sampled(x, y, 1:3) = fliptri(x, y, rgb); end end
Flipquad
Analog zum Fliptri funktioniert der Flipquad-Algorithmus, allerdings ist die Offsetkorrektur hier vom Wert zwei, und es werden vier, statt drei Werten verarbeitet:
function pixel = flipquad(x, y, rgb) % 1 2 3 4 5 % +---+---+---+---+---+ % | | X | | | | % +---+---+---+---+---+ % | | | | | X | % +---+---+---+---+---+ % | | | | | | % +---+---+---+---+---+ % | X | | | | | % +---+---+---+---+---+ % | | | | X | | % +---+---+---+---+---+ coords = [ -2 -1 +1 +2; % X -1 +2 -2 +1]; % Y N = length(coords); % Flip sgn_x = (-1)^x; sgn_y = (-1)^y; % Sample sample = zeros(3,3); for s=1:N sample(s, 1:3) = rgb( x+coords(1,s)*sgn_x, ... y+coords(2,s)*sgn_y, ... 1:3); end % Combine pixel = sum(sample) / N; end
Der Rest funktioniert wie gehabt.
Das Ergebnis
Ernüchternd scheiße.
Originalbild
Fliptri-gefiltertes Bild
Flipquad-gefiltertes Bild
Und das war das.
Wie ich eingangs bereits erwähnte: … — aber wenigstens war man dabei. Prost.