Transzformációk és interpoláció

2D Transzformációk

Vektor és mátrix szorzatából új vektor keletkezik. Egy mátrix és egy kép pixeleinek kordinátáit összeszorozva minden pixel új koordinátára kerül, azaz a kép transzformálva lett. A forgatás, skálázás, eltolás vagy tükrözés kétdimenziós transzformációk. Minden művelethez adottak a hozzá tartozó mátrix elemei.

Forgatás (CW):

$ \begin{bmatrix} cos(\theta) & -sin(\theta) \\ sin(\theta) & \hfill cos(\theta) \end{bmatrix} ⋅ \begin{bmatrix} I_x \\ I_y \end{bmatrix} = \begin{bmatrix} I_x' \\ I_y' \end{bmatrix} $

Skálázás:

$ \begin{bmatrix} S_x & 0 \\ 0 & S_y \end{bmatrix} ⋅ \begin{bmatrix} I_x \\ I_y \end{bmatrix} = \begin{bmatrix} I_x' \\ I_y' \end{bmatrix} $

Eltolás:

$ \begin{bmatrix} 1 & 0 & T_x \\ 0 & 1 & T_y \\ 0 & 0 & 1 \end{bmatrix} ⋅ \begin{bmatrix} I_x \\ I_y \\ 1 \end{bmatrix} = \begin{bmatrix} I_x' \\ I_y' \\ 1 \end{bmatrix} $

Tükrözés (Y):

$ \begin{bmatrix} -1 & 0 \\ 0 & 1 \end{bmatrix} ⋅ \begin{bmatrix} I_x \\ I_y \end{bmatrix} = \begin{bmatrix} I_x' \\ I_y' \end{bmatrix} $

3D Transzformációk

Az X és Y tengelyek körüli elforgatás is megvalósítható, ezek háromdimenziós transzformációk. Az eredmény továbbra is kétdimenziós kép, a művelet során minden pixel egy síkra van vetítve. További 3D transzformáció a perspektíva megváltoztatása, ekkor elég az eredeti kép 4 pontjának megadni az új koordinátáit.

Perspektív transzformáció:

Meg kell találni azt a 3x3 mátrixot, amely a kép 4 kiválasztott pontját a 4 kívánt új pozícióba transzformálja, így módosítva a perspektívát. A szorzásokat elvégezve nyolcismeretlenes egyenletrendszer alakítható ki, amit bármilyen ismert módszerrel aztán meg lehet oldani. A h33 az egyszerűség kedvéért 1, értéke nem számít.

$ \begin{bmatrix} h_{11} & h_{12} & h_{13} \\ h_{21} & h_{22} & h_{23} \\ h_{31} & h_{32} & h_{33} \end{bmatrix} ⋅ \begin{bmatrix} x_1 \\ y_1 \\ 1 \end{bmatrix} = \begin{bmatrix} u_1 \\ v_1 \\ w_1 \end{bmatrix} $

$ \begin{bmatrix} h_{11} & h_{12} & h_{13} \\ h_{21} & h_{22} & h_{23} \\ h_{31} & h_{32} & h_{33} \end{bmatrix} ⋅ \begin{bmatrix} x_2 \\ y_2 \\ 1 \end{bmatrix} = \begin{bmatrix} u_2 \\ v_2 \\ w_2 \end{bmatrix} $

$ \begin{bmatrix} h_{11} & h_{12} & h_{13} \\ h_{21} & h_{22} & h_{23} \\ h_{31} & h_{32} & h_{33} \end{bmatrix} ⋅ \begin{bmatrix} x_3 \\ y_3 \\ 1 \end{bmatrix} = \begin{bmatrix} u_3 \\ v_3 \\ w_3 \end{bmatrix} $

$ \begin{bmatrix} h_{11} & h_{12} & h_{13} \\ h_{21} & h_{22} & h_{23} \\ h_{31} & h_{32} & h_{33} \end{bmatrix} ⋅ \begin{bmatrix} x_4 \\ y_4 \\ 1 \end{bmatrix} = \begin{bmatrix} u_4 \\ v_4 \\ w_4 \end{bmatrix} $

Interpoláció

Az eredeti kép minden képpontjának új pozíciója meghatározható az adott mátrix segítségével. A probléma azonban az, hogy az új kép tele lesz lyukakkal, mivel nem minden helyre fog kerülni képpont a transzformáció után. Ehelyett visszafelé haladva meg kell találni az új kép összes képpontjához a megfelelő képpontot az eredeti képen, így nem maradnak lyukak. A képpontok koordinátái egész számok, de a kiszámolt értékek valószínűleg nem egész számok. Ilyenkor a leggyorsabb módszer a legközelebbi szomszédos pixel értékének lemásolása. A transzformált képen ezzel a módszerrel azonban az élek rossz minőségűek. Jobb minőséget adhat a 4 szomszédos pixel súlyozott átlagát (Bilinear) vagy 16 szomszédos pixelre illesztett spline-okkal való kalkulációt használó módszer (Bicubic). Videójátékoknál az Anti-Aliasing (AA) ugyan ezt a célt szolgálja.

GPU előnyei

A grafikus feldolgozó egység (GPU) feladata átvenni a processzortól (CPU) a 2D és 3D grafikák létrehozásához és megjelenítéséhez kapcsolódó feladatokat. Egyszerűen jellemezve olyan processzor, aminek sokszor több ezer magja van, gyorsan képes elvégezni egyszerre nagyon sok primitív számítást. Erősen optimalizáltak mátrixok és vektorok szorzásának elvégzésére, ezáltal válnak hasznossá grafikai műveletek mellett egyéb felhasználási területeken, mint a neurális hálók tanítása, szimulációk és kriptográfia.

Segédlet

Boglárka fénykép: Letöltés

Jegyzetfüzet fénykép: Letöltés

Forráskód: Forgatás

        
from PIL import Image
import matplotlib.pyplot as plt

# Open the image using PIL
image = Image.open("path-to-resources/boglarka.jpg")

# Resampling filter options are: 'NEAREST', 'BILINEAR', 'BICUBIC' and more
# Press 'Go to Definition' for more info about the function
rotated_image = image.rotate(angle = 20, resample = Image.Resampling.NEAREST)

# Display the image
plt.imshow(rotated_image)
plt.axis('off')
plt.show()
          
        

Forráskód: Perspektíva

        
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

# Open the image using PIL
image = Image.open("path-to-resources/notebook.JPG")

# Define input and output points (top-left, top-right, bottom-left, bottom-right)
input_points = np.float32([[452, 239], [1072, 304], [260, 583], [1052, 696]])
output_points = np.float32([[50, 50], [1438, 50], [50, 942], [1438, 942]])

def compute_perspective_matrix(inp_pts, out_pts):
    A = []
    b = []
    # Populate the two lists (arrays) with values
    for i in range(4):
        x, y = out_pts[i][0], out_pts[i][1]
        u, v = inp_pts[i][0], inp_pts[i][1]
        A.append([x, y, 1, 0, 0, 0, -u * x, -u * y])
        A.append([0, 0, 0, x, y, 1, -v * x, -v * y])
        b.append(u)
        b.append(v)
    # Solve the system of equations
    h = np.linalg.solve(A, b)
    # Add 1 as the last element and reshape into a 3x3 matrix
    # (Reshape is unneccessary in this exact application, because it is flattened in the next step)
    H = np.append(h, 1).reshape(3, 3)
    return H

perspective_matrix = compute_perspective_matrix(input_points, output_points)

# PIL expects a flattened 8-element matrix
# Flatten the matrix and extract the first 8 elements
matrix_for_pil = perspective_matrix.flatten()[:8]

# Apply the transform to the original image
transformed_image = image.transform(
    image.size, 
    Image.Transform.PERSPECTIVE, 
    matrix_for_pil, 
    resample = Image.Resampling.BICUBIC)

# Display images
fig, ax = plt.subplots(1, 2, figsize=(12, 6))
ax[0].imshow(image)
ax[0].set_title("Original Image")
ax[0].axis("off")
ax[1].imshow(transformed_image)
ax[1].set_title("Transformed Image")
ax[1].axis("off")
plt.show()