[ create a new paste ] login | about

Link: http://codepad.org/15JWzxkV    [ raw code | fork ]

meigrafd - Python, pasted on Apr 11:
#!/usr/bin/python3

import socket
import struct
import pickle
import tkinter as tk
from sys import exit, stdout
from time import sleep, strftime
from PIL import Image, ImageTk
from threading import Thread


DEBUG=False


def printD(message):
    if DEBUG:
        print('[{}]  {}'.format(strftime('%H:%M:%S'), message))
        stdout.flush()


class PiVideoStream(object):
    def __init__(self, gui, host='127.0.0.1', port=8000):
        self.gui = gui
        self.host = host
        self.port = port
        self.running = False
    
    def start(self):
        self.client_socket = socket.socket()
        self.client_socket.settimeout(10)
        try:
            self.client_socket.connect((self.host, self.port))
        except (socket.timeout, ConnectionRefusedError) as Error:
            print(Error)
            self.stop()
            return
        self.client_socket.settimeout(None)
        # Make a file-like object out of the connection
        self.connection = self.client_socket.makefile('rb')
        self.running = True
        
        self.t = Thread(target=self.update, args=())
        self.t.setDaemon(1)
        self.t.start()
        #self.gui.master.after(70, self.update_2)
        
        sleep(0.2) #give videostream some time to start befor frames can be read
    
    def update(self):
        while self.running:
            # Read the length of the image as a 32-bit unsigned int.
            data_len = struct.unpack('<L', self.connection.read(struct.calcsize('<L')))[0]
            if data_len:
                printD('Updating...')
                printD('data_len: %s' % data_len)
                data = self.connection.read(data_len)
                deserialized_data = pickle.loads(data)
                printD('Frame received')
                #print(deserialized_data)
                img = Image.fromarray(deserialized_data)
                newImage = ImageTk.PhotoImage(img)
                self.gui.stream_label.configure(image=newImage)
                self.gui.stream_label.image = newImage
                printD("image updated")
            else:
                time.sleep(0.1)
    
    def update_2(self):
        if self.running == False:
            return
        # Read the length of the image as a 32-bit unsigned int.
        data_len = struct.unpack('<L', self.connection.read(struct.calcsize('<L')))[0]
        if data_len:
            printD('Updating...')
            printD('data_len: %s' % data_len)
            data = self.connection.read(data_len)
            deserialized_data = pickle.loads(data)
            printD('Frame received')
            #print(deserialized_data)
            stdout.flush()
            img = Image.fromarray(deserialized_data)
            newImage = ImageTk.PhotoImage(img)
            self.master.stream_label.configure(image=newImage)
            self.master.stream_label.image = newImage
        self.gui.master.after(70, self.update_2)
    
    def quit(self):
        try: self.stop()
        except: pass
    
    def stop(self):
        # indicate that the thread should be stopped
        self.running = False
        try: self.connection.close()
        except: pass
        try: self.client_socket.close()
        except: pass
        self.client_socket = None


class GUI(object):
    def __init__(self, resolution="640x480", stream_resolution=(320, 240), host='127.0.0.1', port=8000):
        self.host = host
        self.port = port
        self.gui_resolution = resolution
        self.stream_resolution = stream_resolution
        self.running = False
        self.master = tk.Tk()
        self.master.protocol("WM_DELETE_WINDOW", self.quit)
        self.main()
    
    def main(self):
        self.videostream = PiVideoStream(gui=self, host=self.host, port=self.port)
        self.master.geometry(self.gui_resolution)
        self.master.title("picamera network stream to tkinter")
        self.startstop_button = tk.Button(master=self.master, text="Start", bg="green", command=self.startstop_stream)
        self.startstop_button.place(x=10, y=10, height=50, width=50)
        self.stream_label = tk.Label(master=self.master)
        self.stream_label.place(x=60, y=10)
        self.exit_button = tk.Button(master=self.master, bg="#229", fg="white", text="Exit", command=self.quit)
        self.exit_button.place(x=10, y=200, height=50, width=50)
    
    def startstop_stream(self):
        # start
        if self.running == False:
            printD("Start")
            self.startstop_button.config(bg="red", text="Stop")
            self.running = True
            self.videostream.start()
        # stop
        else:
            printD("Stop")
            self.startstop_button.config(bg="green", text="Start")
            self.running = False
            self.videostream.stop()
    
    def run(self):
        self.master.mainloop()
    
    def quit(self):
        self.running = False
        self.videostream.quit()
        self.master.destroy()
        print('\nQuit\n')


def main(DEBUG=True):
    screen_width  = 400
    screen_height = 300
    stream_resolution = (320, 240)
    
    try:
    
        tkinter_app = GUI(host='192.168.0.12', port=8000, resolution="{0}x{1}".format(screen_width, screen_height), stream_resolution=stream_resolution)
        tkinter_app.run()
    
    except (KeyboardInterrupt, SystemExit):
        print('Quit')
        tkinter_app.quit()
    except Exception as error:
        print('Error: ' + str(error))
        exit()


if __name__ == '__main__':
    main()


#EOF


Create a new paste based on this one


Comments: