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,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).

View 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)

View 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

View 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()

View 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()