Bild als Stream in Canvas darstellen

  • Guten Abend,


    ich nehme eine Bild mit der Pi Kamera auf und möchte es als stream (wenn Bild in Datei geschrieben wird, funktioniert es) in einem Canvas (TKinter) darstellen:




    Es erscheint immer eine Fehlermeldung wie folgt:


    [font="Courier New"]Exception in Tkinter callback
    Traceback (most recent call last):
    File "/usr/lib/python3.4/tkinter/__init__.py", line 1536, in __call__
    return self.func(*args)
    File "/home/pi/python/kamera/konfiguration_11_01.pyw", line 142, in takepicture
    picshow()
    File "/home/pi/python/kamera/konfiguration_11_01.pyw", line 150, in picshow
    pic=PhotoImage(file=stream, format="gif")
    File "/usr/lib/python3.4/tkinter/__init__.py", line 3419, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
    File "/usr/lib/python3.4/tkinter/__init__.py", line 3375, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)
    _tkinter.TclError: couldn't open "<_io.BytesIO object at 0x7466f538>": no such file or directory[/font]


    Kann mir jemand weiterhelfen?


    Vielen Dank.


    whitechristmas

  • Guten Abend meigrafd,


    erst einmal vielen Dank für Deine Hilfe. Leider verstehe ich nicht, wie ich das für meine Zwecke nutzen kann. Kannst Du mir vielleicht noch den ein oder anderen Tipp geben?


    Vielen Dank.


    whitechristmas

  • Da ich keine Ahnung habe was genau du eigentlich vor hast oder wie deine GUI aussieht, wird das sehr schwer.


    Grob umschrieben wird durch PiVideoStream() sehr viele Einzelbilder bereitgestellt -> PiRGBArray die ständig im Hintergrund aktualisiert werden.
    GUI() liest alle 70ms ein neues Einzelbild/Frame aus und stellt es im stream_label über ImageTk.PhotoImage dar. Das sind quasi Momentaufnahmen wobei 70ms völlig ausreicht damit es flüssig ist.

  • Guten Morgen meigrafd,


    ich möchte ein Bild von der Kamera nicht zuerst in eine Datei (z.B. gif) abspeichern und dann in Canvas laden, sondern den stream im Canvas darstellen. Mit einem Bild in Dateiform funktioniert es super, nur halt nicht mit dem stream. Die Zeit spielt hier keine Rolle.


    Vielen Dank.


    whitechristmas

  • Hallo meigrafd,


    ich habe Dein Script getestet. Bei mir erscheint immer einer Fehlermeldung:


    [font="Courier New"]Traceback (most recent call last):
    File "/home/pi/python/stream_meigrafd.py", line 12, in <module>
    from PIL import Image, ImageTk
    ImportError: cannot import name ImageTk
    [/font]
    Würde Dein Script auch unter Pyhton3 laufen?


    Da die Kamera alle paar Sekunden ein Bild machen soll, wollte ich mit dem stream vermeiden, dass die SD-Karte stark belastet wird und möglicherweise nach ein paar Monaten den Geist aufgibt. Ansonsten funktioniert mein Script wunderbar.


    Vielen dank.


    whitechristmas

  • Wie gesagt, mein Script nutzt einen Stream.


    Google halt mal nach einer Möglichkeit ImageTk mit python3 zu verwenden... Direkt der zweite Treffer (über "python3 ImageTk") zeigt schnell eine Lösung. Du brauchst dann nur noch 2 andere Zeilen minimal anpassen.

  • Guten Morgen meigrafd,


    hab jetzt Dein Script am laufen. Funktioniert super. Habe auch einen Verwendungszweck dafür. Ist aber leider nicht das was ich haben wollte.
    Anstelle eines einzelnen Bildes aus einer Datei in einem Canvas darzustellen, wollte ich das aufgenommenen Bild direkt aus dem Speicher in Canvas darstellen und nicht den Umweg über eine Datei im GIF-Format. Ich wollte das über die Bibliothek BytesIO machen.


    Vielen Dank.


    whitechristmas


  • Anstelle eines einzelnen Bildes aus einer Datei in einem Canvas darzustellen, wollte ich das aufgenommenen Bild direkt aus dem Speicher in Canvas darstellen und nicht den Umweg über eine Datei im GIF-Format.


    In welcher Zeile meines Codes liest du irgend etwas von wegen GIF oder sogar Canvas?


    Wie oft soll ich das noch schreiben?
    Mein Script erstellt kein einzelnes Bild aus/in einer Datei... Es wird direkt der unveränderte Datenstrom von der RaspiCam gestreamt! Auch kein GIF oder sonst was, sondern wirklich ein STREAM.


    Es gibt gewisse Unterschiede zwischen BytesIO und PiRGBArray. Das was du meinem Script vorwirfst zu tun erreichst du erst über den von dir gewählten Weg über BytesIO (mjpg Verfahren).


    Aber hey, google doch einfach selber mal nach: picamera PiRGBArray stream
    und glaub dann hoffentlich dem was du da nachlesen kannst

  • Hallo meigrafd,


    vielen Dank für Deine Unterstützung. Ich werde mir mir Deinen Vorschlag mit "picamera PiRGBArray stream" ansehen.


    Nochmals vielen Dank und sonnige Grüße.


    whitechristmas

  • whitechristmas


    Das eigentliche Problem ist, dass ``picamera`` kein echtes gültigs gif erstellt. Wenn du anstelle ein png lieferst, dann geht es. Abgesehen von deinen kleinen Fehlern. Hier mal ein minimales Beispiel. Ich hab auf die Schnelle alles auf Modulebene geschrieben, was dann am Ende eines lauffähigen Programm nicht gemacht werden soll... ;)


    Edit:
    ok, dass mit dem ungültigen gif ist nicht wahr. ``picamera`` setzt auch ein GIF89a als Header in die erste Zeile der Datei. Und das gemachte Bild wird mit

    Code
    import Tkinter as tk
    
    
    root = tk.Tk()
    canvas = tk.Canvas(root)
    photo = tk.PhotoImage(file='foo.gif')
    x = tk.Label(image=photo)
    x.grid(row=0, column=0)
    root.mainloop()


    auch problemlos angezeigt. Das Problem scheint wo anders zu liegen bzw. bei PIL.

  • Hallo bootsmann,


    hab Deine Lösung in meinem Script übernommen. Funktioniert prima. Vielen Dank für Deine Hilfe.


    whitechristmas


    P.S. Das sind ja tolle Projekte, die man, wenn man Deinem Link folgt, zu sehen bekommt. :thumbs1: