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,9 @@
# Einführung in die Bildbearbeitung
In diesem Kapitel werden Ihnen verschiedene Klassen von Operationen und Methoden erläutert und mit Beispielen
exemplarisch dargestellt. Die Übungen zeigen Beispiele zu den Themen
- **Punktoperationen (Intensitätstransformationen)**
- **Lokale Operationen (Filterung)**
- **Globale Operationen**
- **Geometrische Transformationen**

View File

@@ -0,0 +1,19 @@
# Übung 1: Helligkeitsausgleich
In dieser Übung wird ein Helligkeitsausgleich durchgeführt. Gegeben sind drei Bilder von Texten wie exemplarisch unten
dargestellt. Zu sehen ist, dass die mittlere Beleuchtung des Bildes lokal stark variiert. Auf Algorithmen, die beispielweise
Schwellwerte auf Gurndlage der Helligkeit nutzen, können diese Unterschiede störend wirken. Im folgenden soll daher ein
Helligkeitsausgleich durchgeführt werden, nachdem die mittlere lokale Helligkeit in jedem Bildsegment gleich ist.
![alt text](../../data/text_3.jpg)
## Aufgabe a)
In der Datei [a.py](a.py) werden drei Bilder geladen. Führen Sie den Helligkeitsausgleich auf allen Bildern durch und zeigen
Sie sie an.

View File

@@ -0,0 +1,13 @@
import numpy as np
import cv2
KERNEL_SIZE = 20
# Einlesen des Bildes
filepath = "../../data/text_%s.jpg"
images = list()
for i in [1, 2, 3]:
img = cv2.imread(filepath % i)
img = cv2.resize(img, (500, 500))
images.append(img)

View File

@@ -0,0 +1,34 @@
import numpy as np
import cv2
KERNEL_SIZE = 20
# Einlesen des Bildes
filepath = "../../data/text_%s.jpg"
images = list()
for i in [1, 2, 3]:
img = cv2.imread(filepath % i)
img = cv2.resize(img, (500, 500))
images.append(img)
def balance(img):
kernel = np.ones((KERNEL_SIZE, KERNEL_SIZE)) / (KERNEL_SIZE * KERNEL_SIZE)
blurred = cv2.filter2D(img, -1, kernel=kernel)
img = img / blurred
img = 255 * (img - np.min(img)) / (np.max(img) - np.min(img)) # Normieren auf Wertebereich {0, ..., 255}
img = img.astype(np.uint8)
print(np.max(img), np.min(img))
return img
balanced_images = list()
for img in images:
balanced_image = balance(img)
balanced_images.append(balanced_image)
for i, (image, balaced_image) in enumerate(zip(images, balanced_images)):
cv2.imshow("Text%s" % (i + 1), image)
cv2.imshow("AusgeglichenerText%s" % (i + 1), balaced_image)
cv2.waitKey(0)

View File

@@ -0,0 +1,22 @@
# Übung 10: (Contrast Limited) Adaptive Histogramm Equalization
In dieser Übung soll die Adaptive Histogramm Equalization und die Contrast Limited Adaptive Histogramm Equalization
verwendet werden, um den Kontrast in einem Bild zu erhöhen.
## a) Adaptive Histogramm Equalization
Wenden Sie die adaptive Histogramm Equalization auf das Bild an, welches in dem Skript [a.py](a.py)
geladen wird. Adaptieren Sie für eine Region von 50x50 Pixel. Die Lösung ist in der Datei [l_a.py](l_a.py) zu finden!
## b) Contrast Limited Adaptive Histogramm Equalization
Wenden Sie die Kontrast-limitierte adaptive Histogramm Equalization auf das Bild an, welches in dem Skript [b.py](b.py)
geladen wird. Sie können ein selbst definiertes Clip-Limit definieren.
Adaptieren Sie für eine Region von 50x50 Pixel. Die Lösung ist in der Datei [l_b.py](l_b.py) zu finden!

View File

@@ -0,0 +1,15 @@
import cv2
import numpy as np
img = cv2.imread("../../data/car.png", cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (500, 500))
# Do some preprocessing
img = img.astype(float)
img = 50 + (105 * img / 255)
cv2.imshow("Original", img.astype(np.uint8))
# Implement AHE
cv2.waitKey(0)

View File

@@ -0,0 +1,15 @@
import cv2
import numpy as np
img = cv2.imread("../../data/car.png", cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (500, 500))
# Do some preprocessing
img = img.astype(float)
img = 50 + (105 * img / 255)
cv2.imshow("Original", img.astype(np.uint8))
# Implement CLAHE
cv2.waitKey(0)

View File

@@ -0,0 +1,25 @@
import cv2
import numpy as np
img = cv2.imread("../../data/car.png", cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (500, 500))
# Do some preprocessing
img = img.astype(float)
img = 50 + (105 * img / 255)
cv2.imshow("Original", img.astype(np.uint8))
# Implement AHE
new_image = np.zeros_like(img)
height, width = img.shape
for x in range(width):
for y in range(height):
x1, x2 = np.maximum(0, x - 25), np.minimum(x + 25, height)
y1, y2 = np.maximum(0, y - 25), np.minimum(y + 25, height)
hist, values = np.histogram(img[y1:y2, x1:x2], bins=256, range=(0, 256))
cum_hist = np.cumsum(hist)
v = round(img[y, x])
new_image[y, x] = 255 * cum_hist[v] / cum_hist[255]
cv2.imshow("AHE", new_image.astype(np.uint8))
cv2.waitKey(0)

View File

@@ -0,0 +1,31 @@
import cv2
import numpy as np
img = cv2.imread("../../data/car.png", cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, (500, 500))
# Do some preprocessing
img = img.astype(float)
img = 50 + (105 * img / 255)
cv2.imshow("Original", img.astype(np.uint8))
# Implement CLAHE
new_image = np.zeros_like(img)
height, width = img.shape
for x in range(width):
for y in range(height):
x1, x2 = np.maximum(0, x - 25), np.minimum(x + 25, height)
y1, y2 = np.maximum(0, y - 25), np.minimum(y + 25, height)
hist, values = np.histogram(img[y1:y2, x1:x2], bins=256, range=(0, 256))
clip_limit = 0.6 * round(np.max(hist))
higher_values = hist >= clip_limit
sum_of_higher_values = np.sum(hist[higher_values] - clip_limit)
hist = np.minimum(hist, clip_limit)
hist = hist + round(sum_of_higher_values / 256)
cum_hist = np.cumsum(hist)
v = round(img[y, x])
new_image[y, x] = 255 * cum_hist[v] / cum_hist[255]
cv2.imshow("CLAHE", new_image.astype(np.uint8))
cv2.waitKey(0)

View File

@@ -0,0 +1,109 @@
# Übung 2: Lokale Bildoperationen
Lokale Bildoperationen berechnen den Pixelwert des Ausgangspixels aus der lokalen Umgebung des Eingangspixels. Die
Berechnungsvorschrift ist dabei für jedes Pixel gleich.
In dieser Übung werden einige Beispiele für lokale Bildoperationen behandelt. Dabei werden unter anderem
- Faltung
- Gradienten
- Rangfolgefilter
- Hochpass, Tiefpass, Bandpass
verwendet.
## Aufgabe a)
Das Bild zeigt ***I_in*** zwei sich schneidende Linien (eine horizontalen und eine vertikale) auf hellem
Hintergrund (außerhalb des eingezeichneten Rasters sind die Flächen wie angedeutet störungsfrei
fortgeführt). Es soll nun die Horizontale extrahiert und in binärer Form dargestellt werden, so dass
sich das Binärbild ***I_out*** ergibt. Im folgenden sind
die Bilder visualisiert und als Matrix dargestellt.
<p align="center">
<img src="./data/cross1.png" />
</p>
```python
I_in = [
[200, 200, 100, 200, 200],
[200, 200, 100, 200, 200],
[100, 100, 100, 100, 100],
[200, 200, 100, 200, 200],
[200, 200, 100, 200, 200],
]
```
<p align="center">
<img src="./data/cross2.png" />
</p>
```python
I_out = [
[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0],
[255, 255, 255, 255, 255],
[ 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0],
]
```
Für die Aufgabe stehen die folgenden Operationen zur Verfügung:
- Hochpassfilter mit 3x3 Faltungskern
```python
[
[ -1, -1, -1 ],
[ -1, 8, -1 ],
[ -1, -1, -1 ]
]
```
- Kantenfilter mit 3x3 Faltungskern
```python
[
[ 1, 0, -1 ],
[ 1, 0, -1 ],
[ 1, 0, -1 ]
]
```
- Kantenfilter mit 3x3 Faltungskern
```python
[
[ -1, -1, -1 ],
[ 0, 0, 0 ],
[ 1, 1, 1 ]
]
```
- Punktoperation: Betragsbildung
- Punktoperation: Schwellwertoperation, Punkte mit einer Intensität *I_xy* < 128 werden auf *I_xy* = 0 gesetzt, ansonsten zu 255
- Median-Filter der Größe 3x3
Wählen Sie 4 der 6 Operationen und wenden Sie sie auf die das Bild an. Jede Operation darf dabei nur einmal verwendet werden.
Visualisieren Sie jeden Zwischenschritt.
Die Aufgabe soll in der Datei [a.py](a.py) bearbeitet werden! Die entsprechende Lösung finden Sie in [l_a.py](l_a.py).
**Hinweis:** Mehrere Lösungswege sind möglich!
## Aufgabe b)
Gegeben ist das Bild [edge_01.png](data/edge_01.png). Es zeigt zwei aneinander grenzende graue Flächen die mit Rauschen
versetzt sind. Ziel ist es, das Bild so zu filtern, dass die Kante als weichgezeichnete Linie auf
schwarzem Untergrund resultiert, wie in Bild [edge_02.png](data/edge_02.png) beispielhaft dargestellt ist.
*edge_01.png*:
<p align="center">
<img src="./data/edge_01.png" />
</p>
*edge_02.png*:
<p align="center">
<img src="./data/edge_02.png" />
</p>
Für die Bearbeitung können Sie sich verschiedener Filter bedienen. Beispiele dafür können sein
- Hochpass, Tiefpass, Bandpass
- Diverse Richtungsfilter
- Rangfolgefilter wie Minimum, Maximum, Median
Die Aufgabe soll in der Datei [b.py](b.py) bearbeitet werden! Die entsprechende Lösung finden Sie in [l_b.py](l_b.py).

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

View File

@@ -0,0 +1,50 @@
import numpy as np
import cv2
''' Einlesen des Bildes '''
I_in = [
[200, 200, 100, 200, 200],
[200, 200, 100, 200, 200],
[100, 100, 100, 100, 100],
[200, 200, 100, 200, 200],
[200, 200, 100, 200, 200],
]
I_in = np.asarray(I_in, dtype="uint8")
print("Bild vor der Bearbeitung:")
print(I_in)
print()
print(I_in.dtype)
''' Operation 1: Kantenfilter '''
edge = [
[-1, -1, -1],
[ 0, 0, 0],
[ 1, 1, 1]
]
edge = np.asarray(edge)
edge_conv = np.flip(edge)
I_in = cv2.filter2D(I_in, cv2.CV_64F, edge_conv, borderType=cv2.BORDER_REPLICATE)
print("Operation 1: Kantenfilter")
print(I_in)
print()
''' Operation 2: Absolutwertbildung '''
I_in = np.abs(I_in)
print("Operation 2: Absolutwertbildung")
print(I_in)
print()
''' Operation 3: Medianfilter'''
I_in = cv2.medianBlur(I_in.astype("float32"), 3)
print("Operation 3: Medianfilter")
print(I_in)
print()
''' Operation 4: Schwellwert '''
I_in = np.copy(I_in)
ret, I_out = cv2.threshold(I_in, 127, 255, cv2.THRESH_BINARY)
print("Operation 4: Schwellwert")
print(I_out)
print()

View File

@@ -0,0 +1,36 @@
import numpy as np
import cv2
''' Einlesen des Bildes '''
I_in = cv2.imread("data/edge_01.png")
I_in = cv2.cvtColor(I_in, cv2.COLOR_BGR2GRAY)
cv2.imshow("Bild Schritt 0", I_in)
''' Operation 1: Median-Filter'''
I_in = cv2.medianBlur(I_in, 9)
cv2.imshow("Bild Schritt 1", I_in)
''' Operation 2: Kantenfilter'''
edge = [
[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]
]
edge = np.asarray(edge)
I_in = cv2.filter2D(I_in, cv2.CV_64F, edge, borderType=cv2.BORDER_REPLICATE)
cv2.imshow("Bild Schritt 2", I_in)
''' Operation 3: Glättung / Tiefpass mit Boxfilter'''
edge = [
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]
]
edge = np.asarray(edge) / 9
I_in = cv2.filter2D(I_in, cv2.CV_64F, edge, borderType=cv2.BORDER_REPLICATE)
I_in = I_in / np.max(I_in)
cv2.imshow("Bild Schritt 3", I_in)
''' Bilder anzeigen, Bis Taste gedrückt wird '''
cv2.waitKey(0)

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.

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

View File

@@ -0,0 +1,24 @@
# Übung 5: Nichtlineare Filter
In dieser Übung wird der nichtlineare Median-Filter behandelt. Der Median-Filter ist ein Sonderfall des Rangfolge-Filters.
Bei einem Rangfolge-Filter werden die Werte des zu untersuchenden Bildausschnitts aufsteigend sortiert.
Je nach Filter-Definition wird dann der n-te Wert der Folge als neuer Pixelwert definiert. Sonderfälle des Rangfolge-Filters sind:
- Maximum-Filter: Letzter Wert der Folge
- Minimum-Filter: Erster Wert der Folge
- Median-Filter: Wert der mittleren Position der Folge
## Aufgabe a)
Gegeben ist folgender Bildausschnitt:
<p align="center">
<img src="https://latex.codecogs.com/svg.image?I&space;=&space;\begin{bmatrix}1&space;&4&space;&space;&6&space;&space;\\&space;3&&space;2&space;&&space;1&space;\\&space;6&&space;&space;8&&space;&space;2\end{bmatrix}&space;" title="I = \begin{bmatrix}1 &4 &6 \\ 3& 2 & 1 \\ 6& 8& 2\end{bmatrix} " />
</p>
Geben Sie den Mittelwert und Median des Ausschnitts an!
Die Lösung finden Sie in der Datei [l_a.py](l_a.py).
## Aufgabe b)
Starten Sie das Program [b.py](b.py) um ein verrauschtes Bild zu erhalten und filtern Sie es
mit der OpenCV-Filterfunktion *cv2.medianBlur()*. Führen Sie die Filterung mit den Filtergrößen: 3x3, 5x5,
9x9. Vergleichen Sie die Ergebnisse durch Visualisierung des Ergebnisses mit *cv2.imshow()*.
Die Lösung finden Sie in der Datei [l_b.py](l_b.py).

View File

@@ -0,0 +1,18 @@
import cv2
import numpy as np
img = cv2.imread("../../data/lena.png")
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
''' Rauschen hinzufügen '''
h, w = img.shape
saltpepper_noise = np.zeros((h, w), dtype=np.uint8)
saltpepper_noise = cv2.randu(saltpepper_noise, 0, 255)
black = saltpepper_noise < 15
white = saltpepper_noise > 240
img[white] = 255
img[black] = 0
''' Bild anzeigen '''
cv2.imshow("img", img)
cv2. waitKey()

View File

@@ -0,0 +1,12 @@
import numpy as np
I = [
[1, 4, 6],
[3, 2, 1],
[6, 8, 2],
]
I = np.asarray(I)
print("Median", np.median(I))
print("Mittelwert", np.average(I))

View File

@@ -0,0 +1,24 @@
import cv2
import numpy as np
img = cv2.imread("../../data/lena.png")
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
''' Rauschen hinzufügen '''
h, w = img.shape
saltpepper_noise = np.zeros((h, w), dtype=np.uint8)
saltpepper_noise = cv2.randu(saltpepper_noise, 0, 255)
black = saltpepper_noise < 15
white = saltpepper_noise > 240
img[white] = 255
img[black] = 0
cv2.imshow("img", img)
''' Median Filter anwenden '''
sizes = [3, 5, 9]
for kernel_size in sizes:
img_filtered = cv2.medianBlur(img, kernel_size)
cv2.imshow("img_filtered_" + str(kernel_size), img_filtered)
cv2. waitKey()

View File

@@ -0,0 +1,22 @@
# Übung 6: Forward-Mapping / Backward-Mapping
In dieser Übung wird das *Forward-Mapping* und das *Backward-Mapping* bei geometrischen Transformationen betrachtet.
Sie interessieren Sich für den Wert des Pixels an der Stelle **(x=12, y=38)** des Bildes
![](../../data/car.png)
nach der Transformation mit der Transformationsvorschrift
<p align="center">
<img src="https://latex.codecogs.com/svg.image?\begin{pmatrix}&space;x'\\y'\end{pmatrix}&space;=\begin{pmatrix}&space;0.5&space;&&space;0\\0&space;&&space;0.5\end{pmatrix}\cdot\begin{pmatrix}&space;x\\y\end{pmatrix}.&space;" title="\begin{pmatrix} x'\\y'\end{pmatrix} =\begin{pmatrix} 0.5 & 0\\0 & 0.5\end{pmatrix}\cdot\begin{pmatrix} x\\y\end{pmatrix} ." />
</p>
Berechnen Sie den Wert des Pixels an der Stelle **(x=12, y=38)** nach der Transformation unter Anwendung des Backward- und Forward-Mappings!
Schreiben Sie Ihr Skript in die Datei [a.py](a.py). Die Lösung ist in der Datei [l_a.py](l_a.py) zu finden!
Vergleichen Sie Die Methoden: Wie unterscheiden Sie sich? Welche Vor- und Nachteile haben die Methoden?

View File

@@ -0,0 +1,13 @@
import cv2
import numpy as np
img = cv2.imread("../../data/car.png")
cv2.imshow("Car", img)
print("Image Shape:", img.shape)
print("\nForward-Mapping")
print("\nBackward-Mapping")
cv2.waitKey(0)

View File

@@ -0,0 +1,29 @@
import cv2
import numpy as np
img = cv2.imread("../../data/car.png")
cv2.imshow("Car", img)
print("Image Shape:", img.shape)
print("\nForward-Mapping")
new_image = np.zeros((int(img.shape[0] / 2), int(img.shape[1] / 2), img.shape[2]), dtype=np.uint8)
for x in range(img.shape[1]):
for y in range(img.shape[0]):
new_image[int(y/2), int(x/2)] = img[y, x]
cv2.imshow("Forward-Mapping", new_image)
print("Pixel at position x=12, y=38", new_image[38, 12])
print("\nBackward-Mapping")
# Inverse Transformation:
# (x, y)^T = ([2, 0] * (x', y')^T
# [0, 2])
p_12_38 = img[38*2, 12*2]
print("Pixel at position x=12, y=38", p_12_38)
cv2.waitKey(0)

View File

@@ -0,0 +1,42 @@
# Übung 7: Interpolation
In dieser Übung wird die *Nächste Nachbar (Nearest Neighbour) Interpolation* und die *Bilineare Interpolation*
bei geometrischen Transformationen betrachtet.
Für diese Aufgabe haben Sie ein Bild bestehend aus vier Pixelwerten I_xy:
- I_00 = 1
- I_10 = 2
- I_01 = 3
- I_11 = 4
## a) Interpolation beim Backward Mapping
Sie transformieren das Bild mithilfe der Transformationsvorschrift **T** beziehungsweise der dazugehörigen inversen
Transformationsvorschrift mithilfe des Backward-Mappings. Die ursprüngliche Position I_xy auf dem Eingangsbild des Pixels I'_00 auf dem Ausgangsbild wird durch die die Inverse
Transformation gegeben. Berechnen Sie den Wert des Pixels I'_00 mithilfe der *Nächste Nachbar (Nearest Neighbour) Interpolation* und der *Bilineare Interpolation*, wenn die ursprüngliche Postition I_xy an den Koordinaten
- (x=0.3 | y=0.8)
- (x=0 | y=1)
- (x=0.5 | y=0.5)
liegt.
Sie können die Aufgabe handschriftlich oder mithilfe eines Skripts lösen. Die Lösung ist in der Datei [l_a.py](l_a.py) zu finden!
## b) Interpolation beim Forward Mapping
Sie transformieren das Bild mithilfe der Transformationsvorschrift **T** und des Forward-Mappings. Nach der Transformation ist die neue Position der gegeben
Pixel wie folgt:
- I_00 = 1: (x=0.5 | y=0.5)
- I_10 = 2: (x=1.5 | y=0.5)
- I_01 = 3: (x=0.5 | y=1.5)
- I_11 = 4: (x=1.5 | y=1.5)
Interpolieren Sie die Werte auf dem Zielbild mithilfe der *Nächste Nachbar (Nearest Neighbour) Interpolation* und der *Bilineare Interpolation* für die folgenden Pixel:
- I'_11
- I'_00
Sie können die Aufgabe handschriftlich oder mithilfe eines Skripts lösen. Die Lösung ist in der Datei [l_b.py](l_b.py) zu finden!

View File

@@ -0,0 +1,20 @@
i_00 = 1
i_10 = 2
i_01 = 3
i_11 = 4
# 1)
i_new_bilinear = 0.2 * (0.7 * 1 + 0.3 * 2) + 0.8 * (0.7 * 3 + 0.3 * 4)
i_new_nn = 3
print(i_new_bilinear, i_new_nn)
# 2)
i_new_bilinear = 0 * (1 * 1 + 0 * 2) + 1 * (1 * 3 + 0 * 4)
i_new_nn = 3
print(i_new_bilinear, i_new_nn)
# 3)
i_new_bilinear = 0.5 * (0.5 * 1 + 0.5 * 2) + 0.5 * (0.5 * 3 + 0.5 * 4)
i_new_nn = 4 # Multiple solutions! Here: Ceil
print(i_new_bilinear, i_new_nn)

View File

@@ -0,0 +1,16 @@
i_00 = 1 # New position: (x=0.5, y=0.5)
i_10 = 2 # New position: (x=1.5, y=0.5)
i_01 = 3 # New position: (x=0.5, y=1.5)
i_11 = 4 # New position: (x=1.5, y=1.5)
# 1)
i_new_bilinear = 0.5 * (0.5 * 1 + 0.5 * 2) + 0.5 * (0.5 * 3 + 0.5 * 4)
i_new_nn = 4 # Multiple solutions! Here: Ceil
print(i_new_bilinear, i_new_nn)
# 2)
# This solution is depending on the border behaviour! If no border behaviour is defined, there is not bilinear solution!
i_new_bilinear = ...
i_new_nn = 1
print(i_new_nn)

View File

@@ -0,0 +1,22 @@
# Übung 8: Geometrische Transformation
In dieser Übung soll die Transformationsforschrift
<p align="center">
<img src="https://latex.codecogs.com/svg.image?\begin{pmatrix}&space;x'\\y'\end{pmatrix}&space;=\begin{pmatrix}&space;a&space;&&space;b\\c&space;&&space;d\end{pmatrix}\cdot\begin{pmatrix}&space;x\\y\end{pmatrix}+&space;\begin{pmatrix}&space;e\\f\end{pmatrix}.&space;" title="\begin{pmatrix} x'\\y'\end{pmatrix} =\begin{pmatrix} 0.5 & 0\\0 & 0.5\end{pmatrix}\cdot\begin{pmatrix} x\\y\end{pmatrix} ." />
</p>
für die Transformation des Bildes I1 zu I2 hergeleitet werden.
| I1 | I2 |
| --- | --- |
| ![](./data/original.jpg) | ![](./data/new.jpg) |
Leiten Sie die Transformationsvorschrift her und testen Sie die Vorschrift, indem Sie ein Skript in die Datei [a.py](a.py)
programmieren. Die Lösung ist in der Datei [l_a.py](l_a.py) zu finden!

View File

@@ -0,0 +1,42 @@
import cv2
import numpy as np
img = cv2.imread("../../data/car.png")
img = cv2.resize(img, (500, 500))
cv2.imshow("Car", img)
print("Image Shape:", img.shape)
def T(pos, rotation, translation):
""" Transformation Matrix """
new_pos = np.matmul(rotation, pos) + translation
return new_pos
new_image = np.zeros_like(img)
rotation = [
[..., ...],
[..., ...]
]
translation = [
...,
...
]
for x in range(img.shape[1]):
for y in range(img.shape[0]):
old_pos = np.asarray([[x], [y]])
new_pos = T(old_pos, rotation, translation)
new_pos = new_pos.astype(int)
if 0 <= new_pos[0] < img.shape[1] and 0 <= new_pos[1] < img.shape[0]:
new_image[new_pos[1], new_pos[0]] = img[y, x]
print(new_image.shape)
cv2.imshow("After Transformation", new_image)
cv2.waitKey(0)

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View File

@@ -0,0 +1,88 @@
import cv2
import numpy as np
img = cv2.imread("../../data/car.png")
img = cv2.resize(img, (500, 500))
cv2.imshow("Car", img)
print("Image Shape:", img.shape)
def T(pos, rotation, translation):
""" Transformation Matrix """
new_pos = np.matmul(rotation, pos) + translation
return new_pos
new_image = np.zeros_like(img)
alpha = -0.5 * np.pi
rotation = [
[np.cos(alpha), -np.sin(alpha)],
[np.sin(alpha), np.cos(alpha)]
]
translation = [
[0],
[img.shape[1]]
]
for x in range(img.shape[1]):
for y in range(img.shape[0]):
old_pos = np.asarray([[x], [y]])
new_pos = T(old_pos, rotation, translation)
new_pos = new_pos.astype(int)
if 0 <= new_pos[0] < img.shape[1] and 0 <= new_pos[1] < img.shape[0]:
new_image[new_pos[1], new_pos[0]] = img[y, x]
print(new_image.shape)
cv2.imshow("After Transformation", new_image)
"""
Naive Solution
1. Rotate the image with 90° -> alpha=90°
2. Translate in y axis with image length -> [ [0], [height] ]
"""
"""
Mathematical solution
1. Find correspondences
x,y --> x',y'
0,0 --> 0,1
1,0 --> 0,0
0,1 --> 1,1
1,1 --> 1,0
0.5,0.5 --> 0.5,0.5
2. Solve system:
[a, b] * [x, y]^T + [e, f]^T = [x', y']^T
[c, d]
ax + by + e = x'
cx + dy + f = y'
Translation (0,0 --> 0,1):
0 + 0 + e = 0 --> e = 0
0 + 0 + f = 1 --> f = 1
Rotation (1,0 --> 0,0):
a + 0 + 0 = 0 --> a = 0
c + 0 + 1 = 0 --> c = -1
Rotation (0,1 --> 1,1):
0 + b + 0 = 1 --> b = 1
0 + d + 1 = 1 --> d = 0
"""
cv2.waitKey(0)

View File

@@ -0,0 +1,18 @@
# Übung 9: Gamma-Korrektur
In dieser Übung soll die Gamma-Korrektur
<p align="center">
<img src="https://latex.codecogs.com/svg.image?g'(x,y)=\frac{255}{255^\gamma}\cdot&space;g(x,y)^\gamma" title="" />
</p>
für die bessere Sichtbarkeit des Bilder
![](../../data/car.png)
verwendet werden.
Wenden Sie die Gamma Korrektur mit den Gamma-Werte 0.5,1 und 2 auf das Bild an, indem Sie ein Skript in die Datei [a.py](a.py)
programmieren. Die Lösung ist in der Datei [l_a.py](l_a.py) zu finden!

View File

@@ -0,0 +1,11 @@
import cv2
import numpy as np
img = cv2.imread("../../data/car.png")
img = cv2.resize(img, (500, 500))
cv2.imshow("Original", img)
cv2.waitKey(0)

View File

@@ -0,0 +1,21 @@
import cv2
import numpy as np
img = cv2.imread("../../data/car.png")
img = cv2.resize(img, (500, 500))
cv2.imshow("Original", img)
def gamma_correction(img, gamma):
img = img.astype(np.float)
img = 255 * np.power(img, gamma) / np.power(255, gamma)
print(np.max(img))
img = img.astype(np.uint8)
return img
for gamma in [0.5, 1, 2]:
cv2.imshow("%s" % gamma, gamma_correction(img, gamma))
cv2.waitKey(0)