Grundlagen der Videotechnik Python Video/Image

Transcription

Grundlagen der Videotechnik Python Video/Image
Grundlagen der Videotechnik
Python Video/Image Einführung
Zunaechst: Gängige Linux Konsolen Befehle:
Befehl : Erklaerung
man Befehl : manual pages (Erklaerung) fuer „Befehl“. Beispiel: man cd
cd : change directory, "/" : root directory, "." :
current directory, „..“ : eine directory hoeher. Beispiel: cd ..
pwd : print working directory ps : print running processes ps ­ef | more print all processes page by page ps ­ef | grep prozessname : prozesse mit diesem Namen werden ausgegeben.
kill Nummer: Beendet Programm oder Prozess mit Process ID "Nummer", die vorher mit ps gesehen wurde. df : disk free du : disk usage, shows usage for directories whoami : print username finger username : print information about username
date : show date and time time : measures time of a command, e.g. time ls who : shows who is logged in uptime: Shows time since last boot top : shows processes sorted by cpu suage mv : move, mv source destination rm : remove mkdir : make directory cat : "concatenate", outputs the contents of a file more : shows an input or file one page at a time, more filename, or from input e.g.: ls | more xterm : start x­terminal which befehl : shows path to befehl shutdown now : shuts down computer now vi : vidual editor: terminal based editor. Befehle: esc: commmand mode, in command mode: :w write, :q quit, x delete character, i insert in write mode (enter text) ssh : secure shell, e.g. ssh servername man : manual pages, e.g. man ssh cp : copy a file or directory, e.g. cp filename directory, original is kept, unlike with „mv“.
scp : secure copy, between networked machines, e.g. scp . user@remotemachine.edu:dir chmod : change mode: change access rights for files or directories. To make a file executable: chmod ug+x file. User and group get the right to execute the file.
ifconfig : show network data like ip address sox : audio tools, e.g. command "play" wget : copy entire website trees
Im Konsolen-Fenster installiere nun pythonopencv (falls nicht schon geschehen). Dies ist
die sog. Open Computer Vision Library:
sudo apt­get install python­opencv
Dann starte ipython:
ipython –pylab
import cv2
Interessante Befehle in ipython --pylab:
help(funktionsname) oder ?funktionsname:
hilfefunktion fuer den Befehl
Beispiel:
help(sin)
Nuetzliche Befehle:
cv2.imread, zum Einlesen von JPEG Bildern aus
einer Datei,
cv2.imwrite, zum Schreiben von JPEG Bildern
in eine Datei,
cv2.imshow, zum Darstellen von Bildern aus
arrays,
imshow, (aus der Library matplotlib.pyplot, die
duch –pylab schon geladen wurde)
Beispiel:
Nehme ein Foto auf mit unserm Python Skript
„imagerecdisp.py“ mit der Komandozeile:
python imagerecdisp.py
Dann lesen wir in python das Photo ein mit:
photo=cv2.imread('pycolorphoto.jpg');
Wir zeigen sehen dann die Groesse des Bildes
mit „shape“:
print("Photo dimensions:",photo.shape)
('Photo dimensions:', (480, 640, 3))
Hier ist 480 und 640 die Anzahl der Pixel im
Bild, vertikal und horizontal. Die „3“ stammt
von den 3 Grundfarben Rot, Grün, Blau (RGB).
Beachte dass Python sie in der Reihenfolge
BGR speichert. D.h. die Farbkomponenten sind
der letzte Index eines Pixels, und Index 0
entspricht Blau, 1 entspricht Gruen, und Index
2 entspricht Rot.
Wir haben hier Zugang zu den einzelnen Pixeln,
z.B. Pixel an der Position 0,0, von der
Grundfarbe Blau, ist:
photo[0,0,0]
88
Die „88“ sind ein Intensitaetswert, der sich
zwischen 0 und 255 bei Bildern befindet (entspr.
8 bit pro Grundfarbe).
Darstellen koennen wir das Bild in der Matrix
„photo“ mit dem Befehl:
cv2.imshow('Photo',photo)
Anzeigen nur der Blau-Komponente als
Graustufen-Bild (cmap bedeutet color map):
cv2.imshow('Blau­Komponente',photo[:,:,0])
Videoverarbeitung
Die OpenCV Library gibt uns auch die
Möglichkeit, Daten direkt von einer Webcam
am Rechner, wie dem Raspberry Pi, zu
streamen!
Dazu gibt es den Befehl:
cap = cv2.VideoCapture(0)
Dieser greift auf die Default Kamera 0 zu,
welches z.B. die angesteckte USB-Webcam ist.
„cap“ enthaelt einen Pointer mit der Adresse
dieser Kamera.
Einen Frame dieses Streams koennen wir
auslesen mit:
[retval, frame] = cap.read() wobei „retval“ ein return value ist (der sagt ob
alles in Ordnung ist), und „frame“ enthaelt den
so gewonnenen Frame.
Mit
cv2.imshow('frame',frame)
Koennen wir diesen Frame dann in einem
Fenster anzeigen. Wenn wir dies in einer
unendlichen Schleife tun, bekommen wir das
live Vider Kamera im Fenster angezeigt. Ein
Beispielprogramm dazu ist:
import cv2 #Program to capture a video from the default camera (0) and display it live on the screen cap = cv2.VideoCapture(0) while(True): # Capture frame­by­frame [retval, frame] = cap.read() # Display the resulting frame cv2.imshow('frame',frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # When everything done, release the capture cap.release() cv2.destroyAllWindows()
Speicher dies als „videorecdisp.py“, und rufe es
dann vom Konsolenfenser auf mit:
python videorecdisp.py
und man erhaelt das live Video. Man beendet
die Anzeige mit tippen von „q“.
Eine praktische Anwendung ist z.B. eine „Rohr
Kamera“ mit Schwanenhals zum Inspizieren
von Rohren.
Ein weiteres Beispiel ist unsere Aufnahme und
das Abspeichern eines Fotos von dieser
Webcam:
import cv2 #Program to capture an image from a camera and display it live on the screen cap = cv2.VideoCapture(0) # Capture frame ret, frame = cap.read() # Display the resulting frame cv2.imshow('frame',frame) cv2.imwrite('pycolorphoto.jpg', frame) while(True): if cv2.waitKey(1) & 0xFF == ord('q'): break # When everything done, release the capture cap.release() cv2.destroyAllWindows()
Abspeichern mit dem Namen
„imagerecdisp.py“, und start mit:
python imagerecdisp.py
gleich nach dem Start wird das Foto
geschossen und angezeigt. Die Anzeige wird
wieder mit tippen von „q“ beendet.
Das folgende Beispiel zeigt den Inhalt des
obersten linken Pixels des Videos bei Start des
Programms:
import cv2 #Program to capture an image from a camera and display the pixel value on the screen cap = cv2.VideoCapture(0) # Capture one frame [ret, frame] = cap.read() print("image format: ", frame.shape) print("pixel 0,0: ",frame[0,0,:])
Speichere es unter „pyimageshowpixel.py“ und
starte es mit:
python pyimageshowpixel.py
mit Output:
('image format: ', (480, 640, 3))
('pixel 0,0: ', array([ 35, 167, 146],
dtype=uint8))
Beachte dass wir nur das Pixel addressiert
hatten, daher nur 2 Indizes: frame[0,0,:].
Der Doppelpunkt „:“ bedeutet, dass alle
Indizes dieser Dimension angesprochen
werden.
Auf diese Weise koennten wir auch einen Index
Bereich ansprechen, durch Anfang:Ende, z.B.:
0:3 spricht die Indizes 0,1,2 an (beachte: nicht
den Endwert, die 3). In unserm Fall ist die obige
Schreibweise also identisch mit:
frame[0,0,0:3]
Als Ausgabe bekommen wir daher nicht nur
einen Wert, sonder ein Array mit den Werten
der 3 Grundfarben, in der Reihenfolge BGR.
„Rot“ hat hier also den Wert 146, Gruen 167,
und Blau 35.
Man sieht auch dass die Zahlendarstellung
dazu „uint8“ ist, das heisst: unsigned integer
mit 8 bit, also eine Zahl zwische 0 und 255 (=
8
2 −1 ).
Mit folgendem Programm könne wir die zu R, G,
und B gehoerenden Komponenten als Video
betrachten:
import numpy as np import cv2 #Program to capture a video from a camera and display Original and R,G,B, compinents live on the screen cap = cv2.VideoCapture(0) cv2.namedWindow('Original') cv2.namedWindow('B Komponente') cv2.namedWindow('G Komponente') cv2.namedWindow('R Komponente') while(True): # Capture frame­by­frame ret, frame = cap.read() # Display the resulting frame cv2.imshow('Original',frame) cv2.imshow('B Komponente',frame[:,:,0]) cv2.imshow('G Komponente',frame[:,:,1]) cv2.imshow('R Komponente',frame[:,:,2]) if cv2.waitKey(1) & 0xFF == ord('q'): break # When everything done, release the capture cap.release() cv2.destroyAllWindows()
Nenne es videorecdispRGB.py und starte es
im Konsolenfenster mit: python videorecdispRGB.py
Beachte: Die zu der jeweiligen Komponente
(R,G,B) gehoerenden Farben erscheinen im
zugehoerigen Video heller.
Hier sieht man auch: Jedes Pixel benötigt einen
Informationsgehalt von 3 Byte (Byte=8bit). Wir
haben 480x640 Pixel, also 307200 Pixel pro
Frames. Wenn wir 25 Frames pro Sekunde
haben, kommen wir so auf 307200 x 25 x 3
bits pro sekunde (b/s), also 23040000 b/s, ca.
23 Mb/s! Das ist deutlich mehr als die meisten
Internet Anschluesse bieten, geschweige denn
fuer drahtlose Übertragung.
Wir muessen uns fuer eine (drahtlose)
Uebertragung also ueberlegen, wie wir die
noetige Bitrate reduzieren.
Eine simple Methode, die schon mal einen
Faktor 3 bringt, ist ein schwarz-weiss Video
statt Farbe zu uebertragen. Dies benoetigt nur
1 Byte pro pixel fuer die Helligkeit.
Um den richtigen Helligkeitseindruck zu
erzeugen, muessen wir die relative,
unterschiedliche empfindlichkeit des
menschlichen Auges fuer die 3 Grundfarben
beruecksichtigen. Durch empirische
untersuchung der subjektiven
Helligkeitsempfindung wurde folgendes
Verhaeltnis fuer die Grundfarben R,G,B
gefunden:
0.299; 0.587; 0.114
Wir sehen: Das Auge ist am empfindlichsten
fuer die Grundfarbe Gruen, gefolgt von Rot,
und deutlich geringer fuer Blau.
Wenn wir also die Grundfarben-Werte unseres
Videos entsprechend gewichten, bekommen wir
ein passendes Schwarz-Weiss Bild. Dessen
Helligkeitswert bezeichnen wir mit Y:
Y=0.299*R+ 0.587*G+ 0.114*B
Beachte: Da die Summe der 3 Faktoren gleich 1
ist, hat Y den gleichen Wertebereich wie R,G,B.
Python Beispiel zu Berechnung der so.
„Luminanz“ Komponente Y, der Helligkeit, oder
der Schwarz/Weiss Version des Bildes. Zum
Vergleich wird noch die „Gruen“ Komponente
wiedergegeben:
python videorecprocy.py
Beachte: Y gibt am besten den menschlichen
Helligkeitseindruck wieder, die Gruen
Komponente ist eine gewisse Approximation
davon.
Allerdings ist eine Schwarz/Weiss Ubertragung
nicht sehr zufriedenstellend. Wie koennen wir
also Farbe mit relativ geringer Bitrate
uebertragen? Wieviele Pixel benoetigen wir
ueberhaupt fuer eine qualitativ gute
Darstellung?
Fuer die Beantwortung dieser Fragen muessen
wir uns die Eigenschaften des Auges
ansehen.