Initial commit with project files

This commit is contained in:
2025-06-27 14:34:11 +02:00
commit 7ea3207e63
310 changed files with 9331 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
# Übung 3: Geometrische Transformationen
Geometrische Transformationen können auf Bilder angewendet werden, um den Wert eines Pixels im Eingangsbild auf eine
andere Position im Ausgangsbild abzubilden.
Geometrische Transformationen können unterschieden werden in
|Name| Freiheitsgrade| Beispiel|
|:---:|:---:|:---:|
|Translation|2||
|Rigide/Euklidische Transformation|3||
|Ähnlichkeits- Transformation|4||
|Affine Transformation|6||
|Projektive Transformation|8||
Zusätzliche Informationen über die Implementierung in OpenCV können Sie hier finden: [https://docs.opencv.org/3.4/d4/d61/tutorial_warp_affine.html](https://docs.opencv.org/3.4/d4/d61/tutorial_warp_affine.html)
## Aufgabe a)
Eine häufig verwendete Transformation ist die Skalierung, Diese sollen Sie nun implementieren. Arbeiten Sie dazu die
Fragen bzw. Teilschritte in [a.py](a.py) ab. Die entsprechende Lösung finden Sie in [l_a.py](l_a.py).
.
## Aufgabe b)
Betrachten Sie das folgende Eingangsbild sowie die daraus resultierenden Ausgangsbilder.
**Eingangsbild:**
![](./data/normal.jpg)
**Ausgangsbilder:**
![](./data/center-rotated.jpg)
![](./data/rotated.jpg)
![](./data/shear.jpg)
Gebeben sind folgende Transformationsforschriften:
<p align="center">
<img src="https://latex.codecogs.com/svg.image?T(p)&space;=&space;\begin{pmatrix}cos(-\pi&space;/&space;4)&space;&&space;&space;-sin(-\pi&space;/&space;4)\\sin(-\pi&space;/&space;4)&&space;&space;cos(-\pi&space;/&space;4)\\\end{pmatrix}&space;p" title="T(p) = \begin{pmatrix}cos(\-pi / 4) & -sin(\-pi / 4)\\sin(\-pi / 4)& cos(\-pi / 4)\\\end{pmatrix} p" />
</p>
<p align="center">
<img src="https://latex.codecogs.com/svg.image?T(p)&space;=&space;\begin{pmatrix}cos(-\pi&space;/&space;4)&space;&&space;&space;-sin(-\pi&space;/&space;4)\\sin(-\pi&space;/&space;4)&&space;&space;cos(-\pi&space;/&space;4)\\\end{pmatrix}&space;(p&space;-&space;c)&space;&plus;&space;c" title="T(p) = \begin{pmatrix}cos(\-pi / 4) & -sin(\-pi / 4)\\sin(\-pi / 4)& cos(\-pi / 4)\\\end{pmatrix} (p - c) + c" />
</p>
<p align="center">
<img src="https://latex.codecogs.com/svg.image?T(p)&space;=&space;\begin{pmatrix}1&space;&&space;&space;0.8&space;\\0&space;&&space;&space;1&space;\\\end{pmatrix}&space;(p&space;-&space;c)&space;&plus;&space;c" title="T(p) = \begin{pmatrix}1 & 0.8 \\0 & 1 \\\end{pmatrix} (p - c) + c" /></p>
Wenden Sie die Transformationen in der Datei [b.py](b.py) auf das Eingangsbild an und finden Sie so heraus, welche
Transformation zu welchem Ausgangsbild gehört. Die Lösung findet sich in der Datei [l_b.py](l_b.py).
## Aufgabe c)
Weitere Fragen:
- Wie kann man sich die verschiedenen affinen Transformationsmatrizen aus a) herleiten ?
- Diskutieren Sie Vor- und Nachteile von Forward und Backwardmapping!

View File

@@ -0,0 +1,34 @@
import numpy as np
import cv2
''' Einlesen des Bildes '''
img = cv2.imread("data/normal.jpg")
'''
Schritt 1: Geben Sie eine Transformationvorschrift T an, die das Eingangsbild
- mit dem Faktor s_x ungleich 0 in x-Richtung skaliert
- mit dem Faktor s_y ungleich 0 in y-Richtung skaliert
'''
s_x = 2
s_y = 2
'''
Schritt 2: Geben Sie geben sie die Inverse T_inv zu T an
'''
'''
Schritt 3: Implementieren Sie eine Funktion scale(img, sx, sy), welche das Bild nach der Skalierung wiedergibt.
Verwenden Sie für die Transformation das Backward-Mapping und für die Interpolation Nearest-Neighbour Interpolation.
'''
def scale(img, s_x, s_y):
return new_img
''' Ausgabe des Bildes '''
new_img = scale(img, 2, 2)
cv2.imshow('img', new_img)
cv2.waitKey(0)

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,57 @@
import numpy as np
import cv2
''' Einlesen des Bildes '''
img = cv2.imread("data/normal.jpg")
'''
Schritt 1: Geben Sie eine Transformationvorschrift T an, die das Eingangsbild
- mit dem Faktor s_x ungleich 0 in x-Richtung skaliert
- mit dem Faktor s_y ungleich 0 in y-Richtung skaliert
'''
s_x = 2
s_y = 2
T = np.asarray(
[
[s_x, 0],
[0, s_y]
]
)
'''
Schritt 2: Geben Sie geben sie die Inverse T_inv zu T an
'''
T_inv = np.linalg.inv(T)
'''
Schritt 3: Implementieren Sie eine Funktion scale(img, sx, sy), welche das Bild nach der Skalierung wiedergibt.
Verwenden Sie für die Transformation das Backward-Mapping und für die Interpolation Nearest-Neighbour Interpolation.
'''
def scale(img, s_x, s_y):
rows, cols, channels = img.shape
new_rows, new_cols = int(rows * s_y), int(cols * s_x)
T = np.asarray([[s_x, 0], [0, s_y]])
T_inv = np.linalg.inv(T)
new_img = np.zeros((new_rows, new_cols, channels))
for x in range(new_cols):
for y in range(new_rows):
position = np.asarray([x, y])
old_position = np.matmul(position, T_inv)
old_position = np.round(old_position).astype(int)
old_x, old_y = old_position[0], old_position[1]
# Überstpringen, wenn ausserhalb des Bildes
if not 0 <= old_x < cols or not 0 <= old_y < rows:
continue
new_img[y, x] = img[old_y, old_x]
return new_img.astype(np.uint8)
''' Ausgabe des Bildes '''
new_img = scale(img, 2, 2)
cv2.imshow('new_img', new_img)
cv2.imshow('img', img)
cv2.waitKey(0)

View File

@@ -0,0 +1,106 @@
import numpy as np
import cv2
''' Einlesen des Bildes '''
img = cv2.imread("data/normal.jpg")
rows, cols, channels = img.shape
''' Transformation t1: Implementierung mit OpenCV '''
t_1 = np.float32(
[
[ np.cos(np.pi / 4), np.sin(np.pi / 4), 0],
[-np.sin(np.pi / 4), np.cos(np.pi / 4), 0]]
)
dst = cv2.warpAffine(img, t_1, (cols, rows))
cv2.imshow('img',dst)
cv2.waitKey(0)
''' Transformation t2: Implementierung ohne CV2 '''
c1, c2, c3, c4 = np.cos(np.pi / 4), np.sin(np.pi / 4), -np.sin(np.pi / 4), np.cos(np.pi / 4)
c_y, c_x = rows / 2, cols / 2
def new_pos(x, y):
new_x = round(c1 * (x - c_x) + c2 * (y - c_y) + c_x)
new_y = round(c3 * (x - c_x) + c4 * (y - c_y) + c_y)
return new_x, new_y
def old_pos(new_x, new_y):
x = (new_x/c1) - (c_x / c1) + c_x - c3 * c2 * c_x / (c4 * c1) - (c2 * new_y / (c1 * c4)) + (c_y * c2 / (c1 * c4))
x = x / (1 - c3*c2/(c4*c1))
y = c_y + (new_y - (c3 * (x - c_x)) - c_y) / c4
x = round(x)
y = round(y)
return x, y
# Forwardmapping
new_img = np.zeros_like(img)
for x in range(cols):
for y in range(rows):
new_x, new_y = new_pos(x, y)
# Überstpringen, wenn ausserhalb des Bildes
if not 0 <= new_x < cols or not 0 <= new_y < rows:
continue
new_img[new_y, new_x] = img[y, x]
cv2.imshow('img', new_img)
cv2.waitKey(0)
# Backwardmapping
new_img = np.zeros_like(img)
for x in range(cols):
for y in range(rows):
old_x, old_y = old_pos(x, y)
# Überstpringen, wenn ausserhalb des Bildes
if not 0 <= old_x < cols or not 0 <= old_y < rows:
continue
new_img[y, x] = img[old_y, old_x]
cv2.imshow('img', new_img)
cv2.waitKey(0)
''' Transformation t3: Implementierung ohne CV2 '''
c1, c2, c3, c4 = 1, 0.8, 0, 1
c_y, c_x = rows / 2, cols / 2
def new_pos(x, y):
new_x = round(c1 * (x - c_x) + c2 * (y - c_y) + c_x)
new_y = round(c3 * (x - c_x) + c4 * (y - c_y) + c_y)
return new_x, new_y
def old_pos(new_x, new_y):
x = (new_x/c1) - (c_x / c1) + c_x - c3 * c2 * c_x / (c4 * c1) - (c2 * new_y / (c1 * c4)) + (c_y * c2 / (c1 * c4))
x = x / (1 - c3*c2/(c4*c1))
y = c_y + (new_y - (c3 * (x - c_x)) - c_y) / c4
x = round(x)
y = round(y)
return x, y
# Forwardmapping
new_img = np.zeros_like(img)
for x in range(cols):
for y in range(rows):
new_x, new_y = new_pos(x, y)
# Überstpringen, wenn ausserhalb des Bildes
if not 0 <= new_x < cols or not 0 <= new_y < rows:
continue
new_img[new_y, new_x] = img[y, x]
cv2.imshow('img', new_img)
cv2.waitKey(0)
# Backwardmapping
new_img = np.zeros_like(img)
for x in range(cols):
for y in range(rows):
old_x, old_y = old_pos(x, y)
# Überstpringen, wenn ausserhalb des Bildes
if not 0 <= old_x < cols or not 0 <= old_y < rows:
continue
new_img[y, x] = img[old_y, old_x]
cv2.imshow('img', new_img)
cv2.waitKey(0)

View File

@@ -0,0 +1,24 @@
# Lösung Aufgabe c)
## Wie kann man sich die verschiedenen affnen Transformationsmatrizen herleiten?
Für den Fall das die Abbildung linear ist, muss die Abbildung lediglich auf den Basisbildern
bestimmt werden. Zum Beispiel für die Basis `(1, 0)` und `(0, 1)` berechnet man die transformierten
Vektoren v1 und v2. Dann ist die Transformationsmatrix gegeben durch `T(p) = (v1, v2) p`. Bei
affinen Abbildungen kommt ensprechend noch eine Translation dazu. Wichtig für die Herleitung
der Transformationen sind daher Basiswechsel aus der linearen Algebra.
## Diskutieren Sie Vor- und Nachteile von Forward und Backwardmapping
Vorteile Backwardmapping:
- Geschwindigkeitsvorteil wenn lediglich ein bestimmter Bereich von Interesse ist. Dieser kann
direkt berechnet werden.
- Keine Löcher, keine Überlappungen im Ergebnisbild.
Vorteile Forwardmapping:
- Eventueller Vorteil da die Inverse der Transformation nicht bestimmt werden muss.
Nachteile:
- Es kann zu ÜUberlappung kommen. Mehrere Eingangspixel landen teilweise im gleichen Ergebnispixel.
(Hier muss aus diesen Werten ein finaler Wert interpoliert werden) Interpolation
erst nach kompletter Transformation möglich. Beim Backward-Mapping wird für jede Position
direkt eine Interpolation berechnet.