Skip navigation

Affin transzformációk

Affin transzformáció

Az affin transzformáció a legbővebb lineáris geometriai transzformáció. A párhuzamosságot megtartja, de a képi egyenesek bezárt szögét változtathatja.

Az alábbi geometriai transzformációk tartoznak ide:

  • Eltolás X- és Y-tengelyek mentén.
  • Elforgatás az origó körül megadott szöggel.
  • Skálázás (méretváltás) az X- és Y-tengelyek mentén.
  • Nyírás (megdöntés) az X- és Y-tengelyek mentén.
  • Ezek tetszőleges kombinációja.

Az OpenCV ezen geometriai transzformációk képi mátrixon való végrehajtását két lépésre bontja:

  • Egy 2x3 méretű (np.float32) mátrix definiálása, ami a transzformáció hatását írja le. A mátrix definiálására közvetlen mátrix manipuláció végezhetünk, illetve konkrét definiáló függvényeket is biztosít az OpenCV.
  • Egy ilyen mátrix által leírt transzformáció végrehajtása egy képmátrixra, az eredménykép újramintavételezésével általunk megadott méretű rácson.

A következő részben ismertetjük ezeket a lehetőségeket. A mátrix reprezentáció matematikai hátterének részleteire nem térünk ki. Ez például a Számítógépes grafika kurzuson kerül részletes ismeretésre.

Affin transzformáció reprezentációja és végrehajtása (OpenCV)

Reprezentáció

Az affin transzformáció matematikailag megadható egy 2x3 méretű mátrixszal, vagyis szabadsági foka 6:

M= \left( \begin{matrix} r_{11} & r_{12} & t_{x} \\ r_{21} & r_{22} & t_{y} \end{matrix} \right)

Ezzel balról szorozva egy 3 elemű oszlopvektort, amely a transzformálandó pont (x, y) koordinátáit, valamint egy 1 értéket tartalmaz, eredményként egy kételemű oszlopvektort kapunk, a pont transzformált képét.

\left( \begin{matrix} x' \\ y' \end{matrix} \right) = M \left( \begin{matrix} x \\ y \\ 1 \end{matrix} \right)

Vagyis

x' = r_{11}\cdot x + r_{12}\cdot y + t_{x}\\ y' = r_{21}\cdot x + r_{22}\cdot y + t_{y}

Az rij értékek a forgatást, skálázást és a nyírást együttesen foglalják magukban, a tk értékek az eltolást jelentik.

Eltolás megadása mátrixszal

Az alábbi mátrix tx és ty értékeinek közvetlen megadásával dolgozhatunk. Ha csak eltolást szeretnénk, akkor r11 = r22 = 1 és r12 = r21 = 0 értékűek legyenek. De kombinálható a forgató, skálázó, nyíró résszel is, megfelelő rij értékek választásával. Ekkor az eltolás hatása érvényesül utolsóként. Ezzel itt nem foglalkozunk.

T = \left( \begin{matrix} 1 & 0 & t_x \\ 0 & 1 & t_y \end{matrix} \right)

Skálázó/tükröző mátrix

r11 az X-tengely menti skálázó érték, r22 az Y-tengely menti, amennyiben r12 = r21 = 0. Ha skála értéke 0 és 1 közötti, akkor kicsinyítő a hatás, 1 esetén nincs változás, 1-nél nagyobb értékek esetén nagyítás történik. Negatív érték esetén a skálázás mellett tengelyre való tükrözés is történik. Figyeljünk arra, hogy ekkor a koordináta-értékek negatívvá válnak, ha nem vigyázunk, a képtartományon kívül eshetnek! (Ebben az esetben használjuk az eltolási értékeket is az előző részben látottak szerint, hogy visszakerüljön az eredmény a képmátrix megfelelő helyére.)

S = \left( \begin{matrix} s_x & 0 & 0 \\ 0 & s_y & 0 \end{matrix} \right)

Megjegyezzük, hogy a skálázást egyszerűbb a cv2.resize(), a tükrözést pedig a cv2.flip() függvényekkel elvégezni. A mátrixszal való munkának akkor van szerepe, ha több geometriai transzformációs lépést egyszerre szeretnénk végrehajtani, ami a transzformációs mátrixok homogén kordinátássá alakítása után mátrixszorzásokkal megoldható, de ezzel itt nem foglalkozunk.

Forgatás mátrixa

Mind a négy rij érték szükséges. Legegyszerűbb az alábbi OpenCV függvénnyel dolgozni, ezzel lehetőségünk van a forgatási középpont (origótól különböző), és uniform (tengelyenként egyforma mértékű) skálatényező megadására is.

M = cv2.getRotationMatrix2D(center, angle, scale)

center Elforgatás középpontja, tuple objektumként megadva.
angle Elforgatás szöge (fokokban).
scale Uniform (egyenlő mértékű) skálázó érték.

Eredményül a forgatást (és skálázást) reprezentáló 2x3 méretű mátrixot kapjuk. Vegyük figyelembe, hogy ha nem az origót jelöljük meg forgatási középpontnak, akkor eltolási értékek is megjelennek a mátrixban.

Affin transzformációs mátrix végrehajtása képre

A végrehajtást megelőzően elő kell állítanunk az affin mátrixot, például a fentebb leírt módokat használva.

dst = cv2.warpAffine(src, M, dsize, dst, flags, borderMode, borderValue)

dst Célkép. Nem lehet azonos a forrással!
src Forráskép.
M Végrehajtandó transzformáció mátrixa.
dsize Célkép mérete, felsorolási objektumként megadva.
flags Opcionális: Interpolációs technika választása (mint resize esetén) + cv2.WARP_INVERSE_MAP megadása, ha M inverz transzformációs mátrix.
borderMode Opcionális: Extrapolációs módszer választása (nem definált területre). Alapértelmezés: cv2.BORDER_TRANSPARENT.
borderValue Opcionális: A transzformáció alkalmazása során értéket nem kapó intenzitások értéke. Alapértéke 0.

Megjegyezzük, hogy a transzformáció hatására előfordulhat, hogy az új képmátrix bizonyos pozícióira nem "esik" transzformált szín/intenzitásérték. Ekkor ott az alapértelmezett 0 értéket (fekete színt) fogjuk kapni.

08_03_translate.py

Képmátrix eltolása. A (100, 50) eltoló hatást manuális transzformációs mátrix létrehozással oldjuk meg.

import cv2
import numpy as np

img = cv2.imread('OpenCV-logo.png', cv2.IMREAD_UNCHANGED)
rows, cols = img.shape[:2]

M = np.float32([[1, 0, 100],
[0, 1, 50]]
)

dst = cv2.warpAffine(img, M, (cols, rows))

cv2.imshow('img', dst)
cv2.waitKey(0)

cv2.destroyAllWindows()

08_04_rotate_trackbar.py

Kép forgatása a középpontja körül. A forgatási értéket csúszkával állíthatjuk a [0, 360] fok tartományban.

import numpy as np
import cv2


def on_trackbar(tb_rot):
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), tb_rot, 1)
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('image', dst)


img = cv2.imread('OpenCV-logo.png', cv2.IMREAD_UNCHANGED)
rows, cols = img.shape[:2]
cv2.namedWindow('image')

cv2.createTrackbar('R', 'image', 0, 360, on_trackbar)
on_trackbar(0)
cv2.waitKey(0)

cv2.destroyWindow('image')