Automatische Videoaufzeichnung mit Personenerkennung · Gegebenheiten vor Ort • Vortragsfolien...
Transcript of Automatische Videoaufzeichnung mit Personenerkennung · Gegebenheiten vor Ort • Vortragsfolien...
Automatische Videoaufzeichnung mit Personenerkennung
Daniel Schreiber26.06.2018
Chemnitzer Linux-Tage
$ whoami
• Admin und Entwickler• URZ seit 2014• seit 2000 Chemnitzer Linux-Tage• kein Experte für Bild- und Videoverarbeitung, KI
1
Vorbetrachtungen
Gegebenheiten vor Ort
• Vortragsfolien per HDMI Grabber aufgezeichnet• Mitschnitt über Audioanlage• teilweise Kameraufzeichnung mit Kamerapersonal• 6 Vorträge parallel
2
Die Idee
Die Idee
Kann man nicht alle Vorträge mit Vortragenden aufzeichnen, ohne extra Personal?
→ hochauflösende Kamera fest montieren→ Vortragende per Software tracken und in Beamerbild hineinschneiden
3
Der Versuch
• hochwertige 4K Kamera an Decke montiert• Daten per HDMI Grabber und auf SD-Karte aufgezeichnet• Hakeleien bei Hardware
• HDMI Grabber kann nur HD• Kamera kann nur 4K aufzeichnen, wenn HDMI Output aus ist→ alles in HD machen
4
Die Bausteine
• FFmpeg• OpenCV• irgendetwas, was Gesichter oder Personen erkennen kann• Python
6
Umsetzung
Video aufzeichnen
• Hardware PoolPC• AMD A10–6800K• Nvidia GT640• Festplatte• GBit Netz
• HDMI Grabber über USB3 angeschlossen→ für Software encoding zu langsam• FFmpeg kann Offloading an GPU → FFmpeg neu kompilieren
1 ffmpeg -y -f video4linux2 -framerate 25 -video_size 1920x1080 \2 -i /dev/video0 -pix_fmt yuv420p -c:v h264_nvenc \3 -preset:v llhq -rc:v vbr_minqp -qmin:v 19 -b:v 3500k \4 -f segment -segment_list /tmp/recording/segments.csv \5 -segment_time 10 /tmp/recording/output -%03d.mp4
7
OpenCV: Video laden
1 f o r video_file i n video_files:2 video = cv2.VideoCapture(video_file)3 frame_no = 04 ok, frame = video.read()5 i f not ok:6 p r i n t ('Cannot␣read␣video␣file␣{}'. format(video_file))7 continue8 regions = detect_persons(net, frame, 520)9 regions = group_regions(regions)
10 whi le True:11 frame_no += 112 ok, frame = video.read()
8
OpenCV: Video darstellen
1 f o r x,y,w,h i n regions:2 cv2.rectangle(frame, (x,y), (x+w, y+h), (0,255,0), 2)3
4 cv2.imshow("Tracking", frame)
9
OpenCV: Ausschnitte extrahieren
1 def detect_persons(net, image, y_offset):2 edge=3003 result = []4 f o r i, offset i n enumerate( range(0, 1920-edge, 162)):5 # Korrektur fuer schiefe Kamera6 y_offset2 = y_offset - 2*i7 img_slice = np.copy(image[y_offset2:y_offset2+edge, offset:offset
+edge])8 regions = detect_persons_from_square(net, img_slice)
10
OpenCV: Gesichter finden
• Haar Cascade Classifier• LBP Classifier→ viele false positives→ mäßige Zuverlässigkeit
11
OpenCV: Tracking
• Algorithmen zur Objektverfolgung• Genauigkeit mäßig• Problem: Startkoordinaten
1 tracker = cv2.TrackerBoosting_create()2 tracker.init(frame, bbox)3
4 ok, bbox = tracker.update(frame)
12
OpenCV: Personen finden
• keine fertigen Algorithmen implementiert• Schnittstelle zu Caffee vorhanden• Caffee hat umfangreichen Model Zoo
13
Exkurs: Neuronale Netze
Was macht ein neuronales Netz?
• komplexe nichtlineare Funktion• Training mit Eingabedaten und erwartetem Ergebnis
Input #1
Input #2
Input #3
Input #4
Output
Hiddenlayer
Inputlayer
Outputlayer
14
Warum der ganze Hype?
• vielseitig einsetzbar• bei visuellen Problemstellungen praktisch verwendbare Ergebnisse• Durchbruch 2012 mit Deep Convolutional Networks (AlexNet)• seitdem weitere drastische Fortschritte• vortrainierte Netze verfügbar• genug Rechenleistung durch GPUs verfügbar
15
Wie nutzen?
Zur Erinnerung: Wir wollen Personen oder Gesichter finden
✓ Person ist als Klasse in Standardbenchmark verfügbar• Problem: Lokalisierung
• sliding Window• alternative Netzarchitektur RCNN → Netz liefert Koordinaten✓ noch besser: SSD (Single Shot Detector)✓ MobileNetSSD: Eingabe: 300×300 Pixel, Ausgabe: Klassen + Bounding Boxes
16
Wie kann man es nutzen?
• sliding Window, 300×300, überlappend• Bereich in Höhe begrenzt• überlappende Bereiche vereinigen• mehrere Personen möglich• Vortragenden finden• Bewegung glätten
17
Daten vorverarbeiten
• RGB ↔ BGR Swapping• Normalisierung:
• Skalierung• Konstante (z.B. Mittelwert) abziehen
• abhängig vom Netz• bei Inferenz und Training gleich
1 blob = cv2.dnn.blobFromImage(2 image=frame,3 scalefactor=1/127.5,4 size=(300, 300),5 mean=127.5,6 swapRB=False,7 )
18
Netz laden
1 modelstate = "MobileNetSSD_deploy.caffemodel"2 modeldescription = "MobileNetSSD_deploy.prototxt"3 net = cv2.dnn.readNetFromCaffe(modeldescription , modelstate)
19
Personen erkennen
1 def detect_persons_from_square(net, image):2 (h, w) = image.shape[:2]3 #print(h,w)4 blob = cv2.dnn.blobFromImage(image, 0.007843, (300, 300), 127.5)5 net.setInput(blob)6 detections = net.forward()7 results = []8 f o r i i n np.arange(0, detections.shape[2]):9 confidence = detections[0, 0, i, 2]
10 i f confidence > args["confidence"]:11 idx = i n t (detections[0, 0, i, 1])12 i f idx == 15:13 box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])14 results.append(box.astype("int"))15 return results
20
Nachverarbeitung
Verbesserungen
• nicht jeden Frame auswerten• Vortragenden finden
• aus mehreren Boundingboxen diejenige mit Vortragenden finden• von Mitte aus vorwärts und rückwärts suchen• Box mit geringstem Abstand folgen
• Bewegungen glätten→ Kamera zieht nach• maximale Größe der Boundingbox finden
21
Video schreiben
1 fourcc = cv2.VideoWriter_fourcc(*b'FFV1')2 out = cv2.VideoWriter(args['cropped_video '],fourcc, 25.0, (480, 360))3 videoframe = numpy.zeros(shape=(360,480,3), dtype=numpy.dtype('uint8'))4 for filename in file_list:5 video = cv2.VideoCapture(filename)6 while True:7 ok, frame = video.read()8 if not ok:9 break
10 #11 # ... y1:y2 und x1:x2 interpolieren12 #13 crop_img = numpy.copy(frame[y1:y2, x1:x2])14 videoframe[0:max_height , 0:max_width] = crop_img15 out.write(videoframe)
22
Zusammenschneiden
1 ffmpeg -y -ss 00:05:50 -i /data/schrd/clt/raum5.stream -2018-03-10_12-56-37.ts \
2 -r 25 -ss 00:01:10.5 -i /data/schrd/clt/video13.avi \3 -filter_complex "[1:v]crop=382:238:0:0[ckout];[0:v][ckout]overlay=
main_w-overlay_w -10:main_h-overlay_h -10[out]" \4 -map "[out]" -map "0:a" -t 2797 /data/schrd/clt/schreiber.mp4
23
Fazit
Lessons learned
• Konzept funktioniert• alle nötigen Komponenten frei verfügbar• bei neuronalen Netzen Daten vorverarbeiten!• CLT 2019:
• Audio mit Kamerabild zusammen aufnehmen• Konzept in Breite ausrollen• nochmal mit GPUs versuchen
24
Referenzen
• https://docs.opencv.org/• man 1 ffmpeg-devices• man 1 ffmpeg-filters• Patrick Winston: Machine Learning Course vom MIT (bei Youtube)• Andrej Kaparthy: Vorlesung von Stanford: CS231N-2016 (bei Youtube)• A hackers guide to neural networks http://karpathy.github.io/neuralnets/
25