Forum: PC-Programmierung Python OpenCV Kamera lag bei Auslesen der aktuellen Aufnahme


von Mask-Man (Gast)


Lesenswert?

Hallo,

um ein Objekt im Raum zu verfolgen, ist an dem Objekt eine LED 
angebracht und die Webcam meines PC auf das Objekt gerichtet. Die LED 
wird über einen UART-Befehl des PC über einen Atmega8 an-, bzw. 
ausgeschaltet. Das klappt via Terminal-Programm und auch per Python so 
wie es soll.
Ich will jetzt mit OpenCV immer abwechselnd ein Bild bei ausgeschalteter 
LED aufnehmen, dann eines bei eingeschalteter, etc. Dann will ich die 
jeweiligen Bilder vergleichen und dann (wie bereits bei anderen 
Projekten) aus dem Unterschied zwischen den Bildern die Position des 
Objektes berechnen.
Nur klappt das nicht richtig, denn bei den Aufnahmen ist mal die LED zu 
sehen, obwohl sie aus sein sollte, oder umgekehrt. Ich habe erst 
gedacht, dass im Hintergrund die Daten seriell noch nicht versendet 
wurden, aber auch wenn ich den uC "antworten" lasse, und vor der 
Aufnahme auf diese Antwort warte, sodass die LED sicher an sein müsste, 
tritt das Problem auf.
Meine Mutmaßung: Es wird nicht das aktuellste Bild des Videostreams 
ausgelesen, sondern eines aus einem Buffer, das schon etwas "älter" ist.
Liege ich da richtig, oder gibt es andere Ursachen? Hat jemand eine 
Idee, wie ich dem Problem auf die Spur komme?
1
import cv2
2
from skimage.metrics import structural_similarity as ssim
3
import imutils
4
import numpy as np
5
import time
6
import serial
7
8
led_an = bytearray([10])
9
led_aus = bytearray([20])
10
ser = serial.Serial("COM3", 9600)
11
cap = cv2.VideoCapture(0)
12
try:
13
    while True:
14
        ser.write(led_aus)#beim Empfangen diese Befehls schaltet der uC (noch in der ISR) die LED aus
15
        ser.write(bytearray([40]))#hiermit wird eine "Antwort" des uC angestoßen
16
        eingang = ser.read(1)#Es gibt kein Timeout, also wartet das Programm hier, bis der uC wirlich geantwortet, ergo die LED ausgeschaltet hat
17
        if eingang == bytearray([40]):
18
            ret, bild0 = cap.read()
19
        eingang = 0        
20
        ser.write(led_an)#hier das gleiche Spiel nochmal, nur dass hier die LED angeschaltet wird
21
        ser.write(bytearray([40]))
22
        eingang = ser.read(1)
23
        if eingang == bytearray([40]):
24
            ret, bild1 = cap.read()
25
        eingang = 0
26
        cv2.imshow("bild0", bild0)#hier sollte die LED nicht zu sehen sein (ist sie aber oft)
27
        cv2.imshow("bild1", bild1)#...und hier sollte sie sichtbar sein
28
        cv2.waitKey(1)
29
except KeyboardInterrupt:
30
    ser.close()
31
    exit()

von Andreas M. (amesser)


Lesenswert?

Mask-Man schrieb:
> Python OpenCV Kamera lag bei Auslesen der aktuellen Aufnahme

Wo "lag" die Kamera denn? Das deutsche Wort dafür heißt "Verzögerung"

Mask-Man schrieb:
> Meine Mutmaßung: Es wird nicht das aktuellste Bild des Videostreams
> ausgelesen, sondern eines aus einem Buffer, das schon etwas "älter" ist.

Ja natürlich. Da gibt es diverse Puffer im System. Einen in der Webcam 
selbst, einen im USB Treiber, einen im v4l Treiber dann noch welche im 
opencv und so weiter. Wenn die Webcam ihre Daten bereits als kodierten 
Videostream abliefert (Machen fast alle heute so) dann kommt da noch 
mehr Verzögerung da die Daten ja auch noch dekodiert werden müssen.

von lambda (Gast)


Lesenswert?

Lass dir doch mal in einer Schleife das aktuelle ausgelesene Bild der 
Kamera ausgeben. Dann solltest du sehen, in welchem Bereich die 
Verzögerung liegt. Mit 1-2 Sekunden würde ich da schon rechnen.

von Georg A. (georga)


Lesenswert?

lambda schrieb:
> Mit 1-2 Sekunden würde ich da schon rechnen.

Höchstens bei Web-Cams im Sinne des Wortes, also über Netzwerk 
angebunden mit h264-Streaming. Normale Cams über USB machen entweder raw 
(dann aber nur mit so 5-10fps) oder Motion-JPEG. Da sind die 
Verzögerungen deutlich kleiner. Aber wie oben beschrieben, sind da schon 
ein paar (Frame)Buffer im Weg, d.h. eine Handvoll Frames (0.1-0.2s) wird 
da immer an Latenz vorhanden sein. Die müsste aber relativ konstant 
sein. Ich mach mit einer UVC-Mikroskop-Kamera und OpenCV eine 
Feinpositionierung auf so 20um, da muss nach jedem Kalibrierungschritt 
250ms gewartet werden. Stört mich aber nicht besonders, da sind noch ein 
paar kg bewegte Masse, die sich auch erstmal beruhigen müssen ;)

von Mask-Man (Gast)


Lesenswert?

Danke soweit für die Antworten. Das Denglisch ist natürlich ziemlich 
missverständlich ;)

Ich bin tatsächlich bei weitem nicht bei zwei Sekunden Verzögerung, aber 
200ms kommt schon hin. Der Umstand, dass dieser Wert etwa konstant 
bleibt, hilft mir leider auch nicht wirklich weiter, in jedem Fall muss 
ich das Projekt jetzt etwas anders umsetzen. Spontan denke ich an 
IR-Leds mit IR-pass-filter vor der Kamera, oder an die Erkennung eines 
farbigen Balles.
Falls jemand sinnvolle Möglichkeiten kennt, die Position und Ausrichtung 
eines Objektes im Raum zu erfassen, gerne her damit! Konkret soll von 
der Schulter aus die Position des Kopfes in Relation zu ebenjener 
erfasst werden.

von Sheeva P. (sheevaplug)


Lesenswert?

Mask-Man schrieb:
> um ein Objekt im Raum zu verfolgen, ist an dem Objekt eine LED
> angebracht und die Webcam meines PC auf das Objekt gerichtet. Die LED
> wird über einen UART-Befehl des PC über einen Atmega8 an-, bzw.
> ausgeschaltet. Das klappt via Terminal-Programm und auch per Python so
> wie es soll.
> Ich will jetzt mit OpenCV immer abwechselnd ein Bild bei ausgeschalteter
> LED aufnehmen, dann eines bei eingeschalteter, etc. Dann will ich die
> jeweiligen Bilder vergleichen und dann (wie bereits bei anderen
> Projekten) aus dem Unterschied zwischen den Bildern die Position des
> Objektes berechnen.

Also im Prinzip geht es um Bewegungserkennung, korrekt? Dann schau' doch 
mal dies [1] und den Folgebeitrag an. Eine echte Bewegungserkennung habe 
ich auf der Basis mit einem RasPi4, einer Logitech C920 und Redis für 
den Datentransport auf 25 bis 30 FPS optimieren können, dann ist die CPU 
saturiert...

[1] 
https://www.pyimagesearch.com/2015/05/25/basic-motion-detection-and-tracking-with-python-and-opencv/

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.