Die Webcam - Einfache Bildnormalisierungen
Mit OpenCV ist es recht einfach die Webcam zu öffnen.
Aufgabe 1: Ein Bild von der Webcam anzeigen
Öffnen Sie einen s.g. VideoCapture, lesen Sie ein Bild von der Webcam mit der read-Methode und zeigen Sie dieses mit cv2.imshow an. Übergeben Sie dann die Kontrolle an das Betriebssystem damit es das Fenster mit dem Bild zeichnen kann indem Sie cv2.waitKey aufrufen. Rufen Sie cv2.waitKey mit dem Parameter 0 auf um unendlich lange auf einen Tastendruck zu warten
cv2.waitKey(0)
Lösung anzeigen
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
ret, frame = cap.read()
cv2.imshow("Kamerabild", frame)
cv2.waitKey(0)
Aufgabe 2: Eine sinnvolle Endloßschleife
Um immer wieder ein neues Bild von der Webcam zu lesen macht es Sinn das lesen des Bildes (read) sowie das Anzeigen in einer Endloßschleife durchzuführen. Diese können Sie recht leicht beginnen mit
while True:
Warten Sie nur 1 Millisekunde und beenden Sie das Programm, wenn der Benutzer die Taste q drückt.
Lösung anzeigen
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, frame = cap.read()
cv2.imshow("Kamerabild", frame)
if cv2.waitKey(1) == ord('q'):
break
Aufgabe 3: Grauwertbilder und Histogramme
OpenCV verwendet im Unterbau die bekannte numpy-Bibliothek, so sind z.B. die Bilder stets NumPy-Arrays.
Sie können das Bild von der Webcam leicht in ein Grauwertbild umrechnen. Verwenden Sie dazu die Methode cv2.cvtColor mit dem Parameter cv2.COLOR_BGR2GRAY.
Implementieren Sie dann eine Methode
def drawHistogram(gray):
welche das Grauwertbild erhält und ein neues Bild mit dem Histogram der Grauwerte zeichnet.
Verwenden Sie dazu zunächst np.histogram und übergeben Sie mit range(256) konkrete Grenzen für die Histogram-Bins. Sie benötigen nur den ersten der beiden Rückgabewerte, der zweite kann ignoriert werden. Wandeln Sie das Histogramm in einen np.float32 um und normieren Sie das Histogram, indem Sie durch den höchsten vorkommenden Wert teilen.
Hinweis: Diesen können Sie mit np.max relativ leicht finden.
Nun zeichen wir das Histogramm als Balkendiagramm. Erzeugen Sie dazu ein Bild der Größe (128 x 256) gefüllt mit Nullen (verwenden Sie np.zeros). Iterieren Sie über alle Einträge im Histogram und verwenden Sie cv2.line um eine vertikale Linie (den Balken) in dem Bild zu zeichen. Verwenden Sie den Index des Bins als X-Koordinate. Verwenden Sie den Wert des Histogramms als Höhe des Balkens. Rechnen Sie Anfangs- und Endkoordinate entsprechend aus und zeichen sie.
Geben Sie das Bild zurück ohne es anzuzeigen. Hinweis: Sie können ihre Hauptschleife im Programm so anpassen, das Sie zu jedem Kamerabild auch das Histogram des Grauwertbildes berechnen und dieses dann ebenfalls anzeigen.
Lösung anzeigen
def drawHistogram(gray):
hist, _ = np.histogram(gray, bins=range(256))
hist = np.float32(hist)
hist = hist / np.max(hist)
H = 128
histImage = np.zeros((H, 256))
for bin, value in enumerate(hist):
x0, y0 = bin, H
x1, y1 = bin, int(H * (1.0 - value))
cv2.line(histImage, (x0, y0), (x1, y1), bin / 256.0, 1)
return histImage
Aufgabe 4: Helligkeit und Kontrast normalisieren
Schreiben Sie eine Methode adjustBrightness mit folgender Signatur
def adjustBrightness(gray, brightness, contrast):
Berechnen Sie mit np.mean und np.std Mittelwert (\(\mu\)) und Standardabweichung (\(\sigma\)) des Grauwertbildes.
Normieren Sie dann die Grauwerte des Bildes derart, das diese den mit brightness übergeben Mittelwert und die mittels contrast übergebene Standardabweichung haben. Diese Normalisierung erreichen Sie, indem Sie setzen
Verwenden Sie np.clip um die Werte im Bereich zwischen 0.0 und 1.0 zu begrenzen (abzuschneiden) und wandeln Sie das Bild in in np.uint8-Bild um. Multiplizieren Sie vorher mit 255.0 um dem neuen Datenbereich gerecht zu werden.
Lösung anzeigen
def adjustBrightness(gray, brightness, contrast):
mean, std = np.mean(gray), np.std(gray)
norm = brightness + contrast * (gray - mean) / std
return np.uint8(np.clip(norm, 0.0, 1.0) * 255.0)
Aufgabe 5 - Interaktion
Passen Sie ihre Hauptschleife so an, dass Sie zu jedem Bild das Grauwertbild berechnen und dieses mit der Methode adjustBrightness normalisieren (\(\mu = 0.5, \sigma = 0.5\)). Zeigen Sie dann beide Bilder inklusive dem dazugehörige Grauwerthistogram an. Machen Sie die gewünschte Brightness sowie den gewünschten Kontrast Variabel und verändern Sie die Zielgröße basierend auf der vom Benutzer gedrückten Taste. Sie können z.B. mit + und - den Kontrast erhöhen bzw. verringer sowie mit 1 und 2 die Helligkeit.
Lösung anzeigen
brightness = 0.5
contrast = 0.1
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
exit()
cv2.imshow("Kamerabild", frame)
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
cv2.imshow("Graubild", gray)
cv2.imshow("Graubild - Histogramm", drawHistogram(gray))
norm = adjustBrightness(gray, brightness, contrast)
cv2.imshow("Normalisiert", norm)
cv2.imshow("Normalisiert - Histogramm", drawHistogram(norm))
key = cv2.waitKey(1)
if key == ord("+"):
contrast = np.clip(contrast + 0.01, 0.0, 1.0)
if key == ord("-"):
contrast = np.clip(contrast - 0.01, 0.0, 1.0)
if key == ord("1"):
brightness = np.clip(brightness - 0.05, 0.0, 1.0)
if key == ord("2"):
brightness = np.clip(brightness + 0.05, 0.0, 1.0)
if key == ord("q"):
break