Initial commit with project files
This commit is contained in:
42
2_Bildbearbeitung/ü4/README.md
Normal file
42
2_Bildbearbeitung/ü4/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Übung 4: Filterkern
|
||||
|
||||
Ein Filterkern ist eine n-dimensionale Matrix, mit der üblicherweise eine lokale und lineare Operation auf Pixel im
|
||||
Eingangsbild angewendet wird. In dieser Übung sollen Aufgaben mit Filterkernen manuell und mit Python gelößt werden.
|
||||
|
||||
## Aufgabe a) Separierung
|
||||
Unter Umständen ist ein 2-dimensionaler Filterkern separierbar, d.h. er durch zwei 1-dimensonale Filterkerne dargestellt
|
||||
werden.
|
||||
|
||||
Nehmen Sie die bereits separierten Filterkerne
|
||||
<p align="center">
|
||||
<img src="https://latex.codecogs.com/svg.image?\bg_white&space;F_a&space;=&space;\begin{bmatrix}1&space;&&space;4&space;&&space;1&space;\\\end{bmatrix}&space;\quad&space;\text{und}\quad&space;F_b&space;=&space;\begin{bmatrix}&space;-1\\&space;0\\1\end{bmatrix}&space;" title="\bg_white F_a = \begin{bmatrix}1 & 4 & 1 \\\end{bmatrix} \quad \text{und} F_b = \begin{bmatrix} -1\\ 0\\1\end{bmatrix} " />
|
||||
</p>
|
||||
und erstellen den ursprünglichen Filterken, sowohl "von Hand" als auch in einem Python Skript.
|
||||
|
||||
|
||||
Betrachten und separieren Sie zusätzlich den Filterkern
|
||||
<p align="center">
|
||||
<img src="https://latex.codecogs.com/svg.image?\bg_white&space;\inline&space;F_C&space;=&space;\begin{bmatrix}-2&space;&&space;-3&space;&&space;-2&space;\\0&space;&&space;0&space;&&space;0&space;\\2&space;&&space;3&space;&&space;2&space;\\\end{bmatrix}&space;&space;" title="\bg_white \inline F_C = \begin{bmatrix}-2 & -3 & -2 \\0 & 0 & 0 \\2 & 3 & 2 \\\end{bmatrix} " />
|
||||
</p>
|
||||
|
||||
wenn möglich (manuell und in Python)! Die Lösung findet sich in der Datei [l_a.py](l_a.py).
|
||||
|
||||
## Aufgabe b)
|
||||
Stellen Sie sich vor, Sie wenden die separierten oder nicht separierten Filterkerne auf ein durchschnittliches Bild an.
|
||||
Wie viele Rechenoperationen pro Pixel führen Sie im Durchschnitt pro Pixel aus, wenn sie
|
||||
|
||||
- einen separierten 3x3 Filterkern
|
||||
- einen nicht separierten 3x3 Filterkern
|
||||
|
||||
verwenden. Die Musterlösung befindet sich in der Datei [l_b.md](l_b.md).
|
||||
|
||||
## Aufgabe c)
|
||||
Laden Sie ein beliebiges Bild ein und verwenden Sie die OpenCV-Methode *cv2.filter2D()* um Schärfefilter, Mittelwert-Filter und
|
||||
Kantenfilter auf das Bild anzuwenden. Die Musterlösung befindet sich in der Datei [l_c.py](l_c.py).
|
||||
|
||||
## Aufgabe d)
|
||||
Modifizieren Sie die Aufgabe c), indem Sie nur den Mittelwert-Filter verwenden und diesen vergrößern. Verwenden Sie
|
||||
verschiedene Boundary Optionen durch das Argument *borderType* in der Funktion *cv2.filter2D()* und betrachten Sie das
|
||||
Ergebnis. Vergleichen Sie die verschiedenen Optionen *cv2.BORDER_REFLECT*, *cv2.BORDER_REPLICATE* und *cv2.BORDER_CONSTANT*.
|
||||
Visualisieren Sie weiterhin die Optionen, indem Sie einen Rand mit der Funktion *cv2.copyMakeBorder()* zu dem Bild
|
||||
hinzufügen. Die Musterlösung befindet sich in der Datei [l_d.py](l_d.py).
|
||||
82
2_Bildbearbeitung/ü4/l_a.py
Normal file
82
2_Bildbearbeitung/ü4/l_a.py
Normal file
@@ -0,0 +1,82 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
""" Erstellen des Ursprünglichen Filterkerns"""
|
||||
f_a = np.expand_dims(np.asarray([1, 4, 1]), 0)
|
||||
f_b = np.expand_dims(np.asarray([-1, 0, 1]), 1)
|
||||
f_orig = np.matmul(f_b, f_a)
|
||||
print("TEIL 1")
|
||||
print(f_a)
|
||||
print(f_b)
|
||||
print(f_orig)
|
||||
|
||||
""" Separieren des Filterkerns
|
||||
|
||||
Wir können das Problem als
|
||||
|
||||
f_a * f_b = f_C
|
||||
|
||||
mit
|
||||
|
||||
f_a = [a, b, c]^T
|
||||
f_b = [d, e, f]
|
||||
|
||||
f_C = [
|
||||
[ ad, ae, af ],
|
||||
[ bd, be, bf ],
|
||||
[ cd, ce, cf ],
|
||||
]
|
||||
|
||||
modellieren. Wenn wir a=1 setzten, ergibt sich d=-2 e=-3 f=-2 (erste Zeile der Matrix) sodass sich ein linear
|
||||
unabhängiges Gleichungssystem
|
||||
f_C = [
|
||||
[ -2a, -3a, -2a ],
|
||||
[ -2b, -3b, -2b ],
|
||||
[ -2c, -3c, -2c ],
|
||||
] =
|
||||
[
|
||||
[-2, -3, -2],
|
||||
[0, 0, 0],
|
||||
[2, 3, 2],
|
||||
]
|
||||
|
||||
=> -2a=-2, -2b=0, -2c=2
|
||||
|
||||
=> A * x = B
|
||||
A = [
|
||||
[-2, 0, 0],
|
||||
[ 0, -2, 0],
|
||||
[ 0, 0, -2],
|
||||
]
|
||||
x = [a, b, c]^T
|
||||
B = [-2, 0, 2]^T
|
||||
|
||||
|
||||
erstellen lässt. Dieses lässt sich leicht "von Hand" oder mit Numpy lösen.
|
||||
=>
|
||||
f_a = [1, 0, -1]^T
|
||||
f_b = [-2, -3, -2]
|
||||
Hinweis: Es gibt unendlich viele Lösungen (wenn separierbar)!
|
||||
"""
|
||||
f_C = np.asarray(
|
||||
[
|
||||
[-2, -3, -2],
|
||||
[0, 0, 0],
|
||||
[2, 3, 2],
|
||||
]
|
||||
)
|
||||
|
||||
A = np.array([
|
||||
[-2, 0, 0],
|
||||
[ 0,-2, 0],
|
||||
[ 0, 0,-2],
|
||||
])
|
||||
B = np.array([-2, 0, 2])
|
||||
x = np.linalg.solve(A, B)
|
||||
|
||||
f_a = np.expand_dims(x, axis=1)
|
||||
f_b = np.expand_dims(np.asarray([-2, -3, -2]), axis=0)
|
||||
f_C_new = np.matmul(f_a, f_b)
|
||||
print("TEIL 2")
|
||||
print(f_C)
|
||||
print(f_C_new)
|
||||
32
2_Bildbearbeitung/ü4/l_b.md
Normal file
32
2_Bildbearbeitung/ü4/l_b.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Lösung zu Aufgabe b)
|
||||
Zuerst soll der Rechenaufwand für einen Pixel betrachtet werden:
|
||||
|
||||
**Filterkern mit 3x3-Matrix für einen Pixel:**
|
||||
- 9 x Multiplikation
|
||||
- 8 x Addition
|
||||
- Insgesamt 17 x Rechenoperationen
|
||||
|
||||
|
||||
**Filterkern mit separierten 3x1- bzw. 1x3-Vektoren für einen Pixel:**
|
||||
- 12 x Multiplikation
|
||||
- 8 x Addition Insgesamt
|
||||
- 20 x Rechenoperationen
|
||||
|
||||
Berechnet man lediglich den Pixelwert in der Mitte, so ergibt sich kein Geschwindigkeitsvorteil.
|
||||
Für das gesamte Bild ergibt sich jedoch ein Geschwindigkeitsvorteil pro Pixel, da die Zwischenergebnisse
|
||||
aus der Filterung mit dem ersten Filterkern nicht neu berechnet werden müssen. Anstatt
|
||||
9 Multiplikationen und 8 Additionen mit dem 3x3-Filterkern ergeben sich mit den separierten
|
||||
Filterkomponenten durchschnittlich 6 Multiplikationen und 4 Additionen pro Pixel.
|
||||
|
||||
Gemittelte Anzahl Rechenoperationen pro Pixel für das gesamte Bild:
|
||||
|
||||
**Filterkern mit 3x3-Matrix für einen Pixel:**
|
||||
- 9 x Multiplikation
|
||||
- 8 x Addition
|
||||
- Insgesamt 17 x Rechenoperationen
|
||||
|
||||
|
||||
**Filterkern mit separierten 3x1- bzw. 1x3-Vektoren für einen Pixel:**
|
||||
- 6 x Multiplikation
|
||||
- 4 x Addition Insgesamt
|
||||
- 10 x Rechenoperationen
|
||||
37
2_Bildbearbeitung/ü4/l_c.py
Normal file
37
2_Bildbearbeitung/ü4/l_c.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
img = cv2.imread("../../data/cameraman.png")
|
||||
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
k1 = (1 / 25) * np.asarray([
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1]
|
||||
], dtype=np.uint8)
|
||||
|
||||
k2 = np.asarray([
|
||||
[1, 0, -1],
|
||||
[1, 0, -1],
|
||||
[1, 0, -1],
|
||||
], dtype=np.float32)
|
||||
|
||||
k3 = np.asarray([
|
||||
[-1, -1, -1],
|
||||
[-1, 9, -1],
|
||||
[-1, -1, -1],
|
||||
], dtype=np.float32)
|
||||
|
||||
img_k1 = cv2.filter2D(img, -1, k1)
|
||||
img_k2 = cv2.filter2D(img.astype(np.float32), -1, k2)
|
||||
img_k2 = np.maximum(img_k2, 0).astype(np.uint8)
|
||||
img_k3 = cv2.filter2D(img.astype(np.float32), -1, k3)
|
||||
img_k3 = np.maximum(img_k3, 0).astype(np.uint8)
|
||||
|
||||
cv2.imshow("img", img)
|
||||
cv2.imshow("img_k1", img_k1)
|
||||
cv2.imshow("img_k2", img_k2)
|
||||
cv2.imshow("img_k3", img_k3)
|
||||
cv2. waitKey()
|
||||
25
2_Bildbearbeitung/ü4/l_d.py
Normal file
25
2_Bildbearbeitung/ü4/l_d.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
img = cv2.imread("../../data/cameraman.png")
|
||||
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
k1 = (1 / (33 * 33)) * np.ones((33, 33), dtype=np.uint8)
|
||||
|
||||
border_types = [
|
||||
("cv2.BORDER_REFLECT", cv2.BORDER_REFLECT, 255),
|
||||
("cv2.BORDER_REPLICATE", cv2.BORDER_REPLICATE, 255),
|
||||
("cv2.BORDER_CONSTANT", cv2.BORDER_CONSTANT, 0),
|
||||
("cv2.BORDER_CONSTANT", cv2.BORDER_CONSTANT, 255),
|
||||
|
||||
]
|
||||
|
||||
cv2.imshow("img", img)
|
||||
|
||||
for name, border, value in border_types:
|
||||
img_border = cv2.copyMakeBorder(img, 50, 50, 50, 50, borderType=border, value=value)
|
||||
img_k1 = cv2.filter2D(img, -1, k1, borderType=border)
|
||||
cv2.imshow("img_k1_" + name + str(value), img_k1)
|
||||
cv2.imshow("img_border_" + name + str(value), img_border)
|
||||
|
||||
cv2. waitKey()
|
||||
Reference in New Issue
Block a user