Pygame und opencv class

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
nsession
User
Beiträge: 3
Registriert: Montag 5. Oktober 2015, 11:28

Guten Tag liebe python freunde,

ich beschäftige mich schon ne weile mit python und pygame auf meinem Raspberry Pi
nun hab ich ein kleines Problem bei dem ich nicht weiter komme.

Ich habe ein inzwischen recht Großes Pygame Script das ich für meinen Touchscreen gebastelt habe.
Wetter informationen, Ip Adresse, KameraBilder und GPIOs steuere auf anderen PI's

nun zum Problem.

Ein zweites Script (ein fund aus dem Netzt nicht von mir) zeigt mir einen sehr guten mjpg Stream meiner Kameras an nun würde ich gerne dieses Script in mein Pygame integrieren anstelle der momentanen 1sekunden reloads der Kamerabilder.

nur leider weiß ich nicht wie.

Das Kamerascript:
camcv.py

Code: Alles auswählen

import numpy as np
import cv2
import time
import requests
import threading
from threading import Thread, Event, ThreadError

class Cam():

  def __init__(self, url):
    
    self.stream = requests.get(url, stream=True)
    self.thread_cancelled = False
    self.thread = Thread(target=self.run)
    print "camera initialised"

    
  def start(self):
    self.thread.start()
    print "camera stream started"
    
  def run(self):
    bytes=''
    while not self.thread_cancelled:
      try:
        bytes+=self.stream.raw.read(1024)
        a = bytes.find('\xff\xd8')
        b = bytes.find('\xff\xd9')
        if a!=-1 and b!=-1:
          jpg = bytes[a:b+2]
          bytes= bytes[b+2:]
          img = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.IMREAD_COLOR)
          cv2.imshow('cam',img)
          if cv2.waitKey(1) ==27:
            exit(0)
      except ThreadError:
        self.thread_cancelled = True
        
        
  def is_running(self):
    return self.thread.isAlive()
      
    
  def shut_down(self):
    self.thread_cancelled = True
    #block while waiting for thread to terminate
    while self.thread.isAlive():
      time.sleep(1)
    return True

  
    
if __name__ == "__main__":
  #url = 'http://admin:meinsm@192.168.6.10/cgi-bin/faststream.jpg'
  url = 'http://192.168.6.127/cam_pic_new.php'
  cam = Cam(url)
  cam.start()
macht ein Fenster auf in welchem die Kamera super läuft.

Dies hätt ich gerne inerhalb meines Pygame surface nur leider weiß ich nicht wie ich das am Besten mache.

ImGui-Script hab ich das obere wie folgt eingebunden.

Code: Alles auswählen

...
from camcv import *
...
...

         url = 'http://192.168.6.127/cam_pic_new.php'
	cam = Cam(url)
	camimag = pygame.image.load(cam)
	DISPLAYSURF.blit(camimag,(0,0))
So wird das aber leider nicht.

Für eure hilfe wäre ich sehr dankbar.
Zusätzlich würde ich gerne den URL beim Aufruf übergeben, um alle 4 cameras damit abzufragen natürlich imme rnur eine zur selben zeit.

Solltet ihr noch was brauchen kann ich das gerne Liefern.

Grüße Nsession
BlackJack

@nsession: So funktioniert das nicht. `pygame.imgage.load()` erwartet ein Dateiobjekt oder einen Dateinamen aber kein Thread-Objekt. Wie sollte das denn auch als Bild ”geladen” werden.

Man kann zwar ein wenig aus dem `camcv`-Modul lernen, aber verwenden kann man es so nicht um die Bilder in die Pygame-Anzeige einzubauen. Das Modul verwendet ja `cv2` um das Bild zu dekodieren und anzuzeigen, Du müsstest aber Pygame zum dekodieren und anzeigen verwenden.

Wie immer bei Problemen die man mit einem Programm lösen möchte sollte man das Problem auf Teilprobleme herunterbrechen, solange bis man ein Teilproblem mit ein paar Zeilen Code lösen kann. Hier könnte man beispielsweise eine Generatorfunktion schreiben welche die Bilddaten aus einer liest Datei liefert. Der könnte man dann das entsprechende Dateobjekt von einem `requests.Response`-Objekt übergeben. Dann braucht man einen Thread der zum Beispiel jedes dieser Datenpakete mit einem benutzerdefinierten `pygame.event.Event` in die Ereigniswarteschlange von Pygame steckt. Und in der Schleife mit der Du die Pygame-Ereignisse abarbeitest kannst Du die Daten dann nehmen, über den Umweg über ein `io.BytesIO`-Objekt mit `pygame.image.load()` laden und dann „blitten“.
nsession
User
Beiträge: 3
Registriert: Montag 5. Oktober 2015, 11:28

Hallo BlackJack,

danke für deine Antwort.

Das heißt ich habe keine Möglichkeit cv2 und pygame zu Kombinieren?

In meinem pygame script hab ich die Kameras laufen nur eben auf Pygame ebene.

siehe hier:

Code: Alles auswählen

def showCAM(cam):
        #print(cam)
        if (cam == 1):
            camtext = HEADLINEFONT.render("cam1", 1, (TEXTCOLOR))
            try:
                f1 = StringIO.StringIO(urllib.urlopen('http://user:password@192.168.2.10/cgi-bin/image.jpg?size=640x480').read())
            except:
                f1 = 0
        elif (cam == 2):
            camtext = HEADLINEFONT.render("cam2", 1, (TEXTCOLOR))
            sensor = readsensor(cam)
            try:
                f1 = StringIO.StringIO(urllib.urlopen('http://10.0.0.191/cam.jpg').read())
            except:
                f1 = 0
            
        elif (cam == 3):
            camtext = HEADLINEFONT.render("cam3", 1, (TEXTCOLOR))
            #sensor = readsensor(cam)
            try:
                f1 = StringIO.StringIO(urllib.urlopen('http://10.0.0.21/jpg/image.jpg').read())
            except:
                f1 = 0
        elif (cam == 4):
            camtext = HEADLINEFONT.render("cam4", 1, (TEXTCOLOR))
            try:
                f1 = StringIO.StringIO(urllib.urlopen('http://user:passwort@192.168.6.10/cgi-bin/image.jpg?size=640x480').read())

            except:
                f1 = 0



        try:
            img1 = pygame.image.load(f1, "image.jpg")
        except:
            img1 = pygame.image.load("offlinecam.jpg")


# Zeige Kamerabild

        DISPLAYSURF.blit(img1,(0,0))
das funktioniert aber halt leider mehr als Diashow und nicht soschön flüssig wie mit dem cv2.

Ich hatte gehoft es gibt eine möglichkeit eine art frame zu nutzen der wie einen iframe in html als beispiel.
BlackJack

@nsession: Ich wüsste nicht warum man das kombinieren sollte‽ Wenn das mit `cv2` flüssig geht, dann sollte das mit Pygame auch flüssig gehen. Du machst da ja auch etwas anderes in Pygame: Einzelbilder laden statt einen Datenstrom kontinuierlich auslesen und verarbeiten. Wie flüssig das läuft hängt auch davon ab wie häufig die Funktion aufgerufen wird.

Die Funktion ist übrigens mehr als gruselig. Erst die ganzen Codewiederholungen, dann die Fehlerbehandlung mit einem nackten ``except:`` bei dem ein Name an einen falschen Dummywert gebunden wird mit der Absicht das der später dann wieder zu einer Ausnahme führt die wieder mit einem nackten ``except:`` behandelt wird. Schlechter kann man Fehlerbehandlung kaum machen.
nsession
User
Beiträge: 3
Registriert: Montag 5. Oktober 2015, 11:28

Hallo zusammen,

ich will zu meiner verteidigung aufführen das ich bis vor 3 Monaten noch nie mit python in berührung gekommen bin :oops:

hat mir jemand einen Ansatz an Codeschnipsel wie ich das mit dem mjpeg stream flüßiger hinbekommen kann?
Ich mach später mal ein Bild von meiner Gui.

Grüße Nsession
Antworten