Automatische Videoaufzeichnung mit Personenerkennung · Gegebenheiten vor Ort • Vortragsfolien...

Preview:

Citation preview

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

Recommended