Threading - Kivy GUI updaten
Verfasst: Donnerstag 4. November 2021, 19:40
Guten Abend, ich bin ziemlich neu in Sachen Python und versuche schon seit längerer Zeit mein Problem zu lösen. Ich habe eine Benutzeroberfläche in Kivy und möchte gerne ein Bild von meiner IP-Kamera empfangen und dieses in der Benutzeroberfläche anzeigen lassen. Das sollte 30 mal pro Sekunde passieren, um ein Video mit etwa 30 fps zu erzeugen. Mein Problem ist, dass die Benutzeroberfläche einfriert. Man kann jedoch feststellen, dass der Code im Hintergrund richtig arbeitet: Wenn ich manuell auf das Fenster klicke und die Größe anpasse, wird in diesem Moment das momentane Bild der Kamera in der Benutzeroberfläche aktualisiert. Ich habe probiert, das ganze durch Threading zu lösen, aber mache hier wohl etwas falsch:
Ich bitte um Hilfe. Vielen Dank vorab!
Code: Alles auswählen
#Das ist die Hauptfunktion
def main(self, *args):
global adjustment_stop_threading
global adjustment_lock
global adjustment_frame
#Hier starte ich in einem Thread die andere Funktion, die das aktuelle Bild der IP-Kamera abgreift
threading.Thread(target=self.getimage_livestream).start()
#"my_frame" sollte zu Beginn leer sein
my_frame = None
while True:
#grab lock
with adjustment_lock:
#fortfahren, wenn da ein Bild in "adjustment_frame" ist
if not adjustment_frame is None:
#we copy here to dump the lock as fast as possible
my_frame = np.copy(adjustment_frame)
if my_frame is not None:
try:
#etwas Bildbearbeitung folgt, um das Bild als KIVY-Textur anzeigen lassen zu können
buf1 = cv2.flip(my_frame, 0)
buf = buf1.tobytes()
image_texture = Texture.create(size=(my_frame.shape[1], my_frame.shape[0]), colorfmt='rgb')
image_texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')
#Hier wird die KIVY-Textur "liveimageadjustment.texture" durch das neue Bild "image_texture" ersetzt
self.root.ids.liveimageadjustment.texture = image_texture
#sleep, um der Benutzeroberfläche zu erlauben, sich zu aktualisieren...das funktioniert jedoch nicht!
time.sleep(0.03)
except Exception as e:
print(e)
#hier wird keine Exception ausgegeben, da der Code im großen und Ganzen im Hintergrund funktioniert, lediglich die GUI aktualisiert sich nicht
if cv2.waitKey(1) == ord('q'):
break
#Diese Funktion verbindet sich mit der IP-Kamera, empfängt und dreht das aktuelle Bild. Dieses wird dann in der globalen Variablen "adjustment_frame" gespeichert
def getimage_livestream(self, *args):
global adjustment_stop_threading
global adjustment_lock
global adjustment_frame
stream = urlopen('http://192.168.4.1:81/stream')
bytes = b''
while not adjustment_stop_threading:
try:
bytes += stream.read(1024)
a = bytes.find(b'\xff\xd8')
b = bytes.find(b'\xff\xd9')
if a != -1 and b != -1:
jpg = bytes[a:b+2]
bytes = bytes[b+2:]
getliveimage = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR)
livestreamrotated1 = cv2.rotate(getliveimage, cv2.ROTATE_90_CLOCKWISE) #here I am rotating the image
with adjustment_lock:
adjustment_frame = livestreamrotated1
time.sleep(0.03)
except Exception as e:
#Auch hier wird keine Exception ausgegeben, alles funktioniert wie es soll
print(e)
print("failed at this point")