Initial commit with project files
This commit is contained in:
56
2_Bildbearbeitung/ü3/README.md
Normal file
56
2_Bildbearbeitung/ü3/README.md
Normal 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:**
|
||||
|
||||

|
||||
|
||||
**Ausgangsbilder:**
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
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;+&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;+&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!
|
||||
34
2_Bildbearbeitung/ü3/a.py
Normal file
34
2_Bildbearbeitung/ü3/a.py
Normal 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)
|
||||
BIN
2_Bildbearbeitung/ü3/data/center-rotated.jpg
Normal file
BIN
2_Bildbearbeitung/ü3/data/center-rotated.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
2_Bildbearbeitung/ü3/data/normal.jpg
Normal file
BIN
2_Bildbearbeitung/ü3/data/normal.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
2_Bildbearbeitung/ü3/data/rotated.jpg
Normal file
BIN
2_Bildbearbeitung/ü3/data/rotated.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
BIN
2_Bildbearbeitung/ü3/data/shear.jpg
Normal file
BIN
2_Bildbearbeitung/ü3/data/shear.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
57
2_Bildbearbeitung/ü3/l_a.py
Normal file
57
2_Bildbearbeitung/ü3/l_a.py
Normal 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)
|
||||
106
2_Bildbearbeitung/ü3/l_b.py
Normal file
106
2_Bildbearbeitung/ü3/l_b.py
Normal 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)
|
||||
24
2_Bildbearbeitung/ü3/l_c.md
Normal file
24
2_Bildbearbeitung/ü3/l_c.md
Normal 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.
|
||||
Reference in New Issue
Block a user