How to update Tkinter window every time image is processed - python

I'm trying to create a GUI that will display an image that is taken every 10 seconds and it's processed counter part. I'm having trouble getting the GUI window to update the two images when they get overridden in the file system.
Here's the code I have so far
import cv2
import threading
from imageai.Detection import ObjectDetection
import os
from tkinter import *
import os
from PIL import ImageTk,Image
root = Tk()
canvas = Canvas(root, width = 2000, height = 2000)
canvas.pack()
execution_path = os.getcwd()
inimg = ImageTk.PhotoImage(Image.open(os.path.join(execution_path , "test.jpg")))
outimg = ImageTk.PhotoImage(Image.open(os.path.join(execution_path , "testnew.jpg")))
def capture():
print("Capturing...")
videoCaptureObject = cv2.VideoCapture(0)
ret,frame = videoCaptureObject.read()
cv2.imwrite("test.jpg",frame)
print("Done capturing.")
print("Finding")
totalPersons = 0
detections = detector.detectObjectsFromImage(input_image=os.path.join(execution_path , "test.jpg"), output_image_path=os.path.join(execution_path , "testnew.jpg"))
for eachObject in detections:
if(eachObject["name"] == "person"):
totalPersons += 1
print("Total persons " + str(totalPersons))
detector = ObjectDetection()
detector.setModelTypeAsRetinaNet()
execution_path = os.getcwd()
detector.setModelPath(os.path.join(execution_path , "resnet50_coco_best_v2.0.1.h5"))
detector.loadModel("fastest")
def run():
threading.Timer(10.0, run).start()
canvas.create_image(20, 20, anchor=NW, image=inimg)
canvas.create_image(750, 500, anchor=SW, image=outimg)
root.mainloop()
capture()
run()

try to use
root.update_idletasks()
to update tkinter GUI window.

Related

How to display videos on tkinter using sequence of images

I am trying to build a GUI that displays sequence of images as videos. The images are numpy arrays.
The code is working when I try to display one image at a time but it crashes when I try to run them as a sequence.
The code:
from tkinter import *
from scipy.io import loadmat
from PIL import ImageTk, Image
import time
data = loadmat('DepthFrames.mat')['DepthFrames'].squeeze(axis=0)
print(data.shape)
counter = 0
root = Tk()
image = ImageTk.PhotoImage(image = Image.fromarray(data[counter]))
root.title("WUDU VIDEOS LABEL TOOL")
myLabel = Label(root, image = image)
myLabel.grid(row = 0)
def changeImg():
global counter
counter +=1
print(counter)
image = ImageTk.PhotoImage(image = Image.fromarray(data[counter]))
myLabel.configure(image = image)
myLabel.image = image
def playVideo():
for i in range(10):
image = ImageTk.PhotoImage(image = Image.fromarray(data[i]))
myLabel.configure(image = image)
myLabel.image = image
time.sleep(0.03333)
my_Button = Button(text = "Play video",command = playVideo)
my_Button.grid(row = 1)
root.mainloop()
time.sleep blocks the main thread of tkinter. Your code will freeze the GUI until the for loop is completed and the image will be shown as the last image. For more details, see this post.
You need to use the after method. Something like this:
def playVideo(frame=0):
try:
image = ImageTk.PhotoImage(image = Image.fromarray(data[frame]))
except IndexError:
return
myLabel.configure(image = image)
myLabel.image = image
root.after(33, playVideo, frame+1)

pictures not showing up

I made a code with multiprocessing and it does not work. Here's the code
from tkinter import *
from PIL import ImageTk , Image
import multiprocessing
root = Tk()
def imgs(img):
img1 = "C:/Users/ASUS/pixel/"+img+".png"
global img2
img2 = ImageTk.PhotoImage(Image.open(img1))
l = Label(image = img2)
l.pack()
q1 = input("what is your favorite color?")
print("wow " + q1 + " , also is mine's!")
imgs("f_i")
p = multiprocessing.Process(target=imgs)
p.start()
#more prints , inputs , etc
An image was supposed to show up but it does not. How can I fix that?

Resize PIL image: ValueError: Unknown resampling filter

So I am trying to make a desktop-like interface in python with Tkinter, and I am trying to set the wallpaper but I have no idea how to resize it. Here is the code:
from tkinter import *
import tkinter.messagebox as box
import webbrowser
from PIL import Image, ImageTk
window=Tk()
window.title('Label Example')
window.configure(background = 'gray44')
#---=Main_Frame=---#
main_frame = Frame(window)
main_frame.pack(padx = 600, pady=350)
#---=Wallpaper=---#
img_wallpaper = ImageTk.PhotoImage(Image.open('minecraft main picture.gif').resize(10, 10)) # the one-liner I used in my app
label_w = Label(window, image=img_wallpaper)
label_w.image = img_wallpaper # this feels redundant but the image didn't show up without it in my app
label_w.pack()
##wallpaper_image = PhotoImage(file = 'minecraft main picture.gif')
##wallpaper = Label(window, image= wallpaper_image, width=400, height = 400)
##wallpaper_image_big = PhotoImage.subsample(wallpaper_image, x=1, y=1)
##can_wallpaper = \
##Canvas(window, width = 1200, height = 700)
##can_wallpaper.create_image((100, 100), image = wallpaper_image)
##can_wallpaper.place(x=0, y =0)
window.mainloop() #Main loop
I have tried used someone else's code to resize it with PIL pillow but it does not work.
Here is the error:
Traceback (most recent call last):
File "/Users/edwardandreilucaciu/Desktop/Desktop Interface Project/Desktop Interface.py", line 16, in <module>
img_wallpaper = ImageTk.PhotoImage(Image.open('minecraft main picture.gif').resize(10, 10)) # the one-liner I used in my app
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PIL/Image.py", line 1865, in resize
message + " Use " + ", ".join(filters[:-1]) + " or " + filters[-1]
ValueError: Unknown resampling filter (10). Use Image.NEAREST (0), Image.LANCZOS (1), Image.BILINEAR (2), Image.BICUBIC (3), Image.BOX (4) or Image.HAMMING (5)
Question: how to resize images in Tkinter
import kinter as tk
from PIL import Image, ImageTk
class ImageLabel(tk.Label):
def __init__(self, parent, **kwargs):
path = kwargs.pop('path', None)
if path is not None:
image = Image.open(path)
resize = kwargs.pop('resize', None)
if resize is not None:
image = image.resize(resize, Image.LANCZOS)
# Keep a reference to prevent garbage collection
self.photo = ImageTk.PhotoImage(image)
kwargs['image'] = self.photo
super().__init__(parent, **kwargs)
Usage:
class App(tk.Tk):
def __init__(self):
super().__init__()
lab=ImageLabel(self,
path="minecraft main picture.gif",
resize=(400, 400))
lab.grid()
if __name__ == '__main__':
App().mainloop()
It's actually quite easy
img_wallpaper = ImageTk.PhotoImage(Image.open('minecraft main picture.gif').resize(10, 10))
you see .resize is not availble for ImageTk image object also .resize takes a tuple of width and height
Try this
img_wallpaper = Image.open('minecraft main picture.gif').resize((10,10))
img_wallpaper = ImageTk.PhotoImage(img_wallpaper)

Play mp4 video in python with GUI

I want to create a photo booth with a simple sequence. I used mp4 files as animations.
Everything has to start in GUI with a button "start" that will run a loop for users. Exit to GUI will be by pressing the esc key.
In the "user" loop there will be a start animation as mp4 video -in omx player, working over and over until the user touches the touch screen. I already did this with listener move_mouse to kill the process.
I then have another animation with a countdown after which the camera takes a picture and then displays the photo on the screen in a window with two buttons repeat or print.
The problem with the listener is it freezes the application after capturing the photo
How can I solve this problem?
try:
from Tkinter import * # Python2
except ImportError:
import tkinter as Tk # Python3import Tkinter as tk
import sys
from time import sleep
from PIL import Image, ImageTk
from datetime import datetime
from sh import gphoto2 as gp
import signal, os, subprocess, glob
from pynput import mouse
from pynput import keyboard
shot_date = datetime.now() .strftime("%Y-%m-%d")
shot_time = datetime.now() .strftime("%Y-%m-%d %H:%M:%S")
picID = "PIShots"
folder_name = shot_date + picID
save_location = "/home/pi/Desktop/gphoto/images/" + folder_name
# listener
def on_move(x,y):
print("mouse move")
playerOff()
#pynput.mouse.Listener.stop
playerOn()
capturePhoto()
# press key listener
#def on_release(key):
# print('{0} released'.format(
# key))
# if key == keyboard.Key.esc:
# Stop listener
# return False
#StartAnmation and listener
def Start():
omxc= subprocess.Popen(['omxplayer','-b','--loop','--no-osd',"/home/pi/Desktop/START.mp4"])
with mouse.Listener(
on_move=on_move) as listener:
listener.join()
# get the latest file
def get_latest_file(path, *paths):
"""Returns the name of the latest (most recent) file
of the joined path(s)"""
fullpath = os.path.join(path, *paths)
files = glob.glob(fullpath) # You may use iglob in Python3
if not files: # I prefer using the negation
return None # because it behaves like a shortcut
latest_file = max(files, key=os.path.getctime)
_, filename = os.path.split(latest_file)
return filename
#start_animation in OMX player
def playerOn():
omxc= subprocess.Popen(['omxplayer','-b',"/home/pi/Desktop/animacja.mp4"])
#Player Off
def playerOff():
os.system('killall omxplayer.bin')
#CreateSaveFolder
def createSaveFolder():
try:
os.makedirs(save_location)
except:
print("Failed to create the new directory")
os.chdir(save_location)
def quit(root):
root.destroy()
def capturePhoto():
status = 0
createSaveFolder()
sleep(6)
os.system('fswebcam -r 1920x1080 -s brightness=70% -s gain=50% -S 10 --set lights=off --no-banner %H%M%S.jpg')
print save_location
location=get_latest_file(save_location,'*.jpg')
#print location
sciezkaZdj= save_location + "/" + location
print sciezkaZdj
im = Image.open(sciezkaZdj)
width, height =im.size
LEFT_HALF = 200, 0, width-400 ,height
im = im.crop(LEFT_HALF)
im = im.transpose(Image.ROTATE_270)
ramka = Image.open("/home/pi/Desktop/ramka1.jpg")
text_img = Image.new('RGBA', (1200,2000), (0, 0, 0, 0))
text_img.paste(ramka, (0,0))
text_img.paste(im, (50,30))
text_img.save("ramka.png", format="png")
path = save_location + "/ramka.png"
top2 = Toplevel(window)
top2.geometry("1600x720")
top2.overrideredirect(1)
top2.title("fotobudka")
top2.configure(background='black')
img = ImageTk.PhotoImage(Image.open(path))
panel = Label(top2, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
playerOff()
#close gui
window.after(5000, lambda: top2.destroy())
#************MAIN
if __name__ == "__main__":
try:
#Gui main*********************************
window = Tk()
top1 = Toplevel(window)
top1.geometry("1600x720")
# top1.wm_attributes('-topmost',1) #zawsze na wierzchu
top1.configure(background='black')
button_start = Button(window, text='start',command=Start)
button_start.pack()
window.mainloop()
#Gui main end******************************
except KeyboardInterrupt:
print "koniec"

Run Images in Loop Tkinter

I am creating an app that will allow users to scan a ticket and a message will be displayed. I have created a short GIF animation to play when the app starts to show users where to scan their ticket.
I am having trouble understanding how to play a GIF image using tkinter in Python 3. I have tried many solutions and I came across a piece of code where you select the folder and the images in that folder will play in a loop but it's not working.
I think I'm not understanding the code. Here is my code for my app:
from tkinter import *
from tkinter import messagebox
import tkinter.filedialog
from tkinter.filedialog import askdirectory
import requests
import simplejson as json
import os
#from json import JSONEncoder
#class MyEncoder(JSONEncoder):
#def default(self, o):
#return o.__dict__
#Connect to API function
def apiconnect(statusvar):
ticektid = e1.get()
def to_serializable(ticketid):
return str(ticketid)
url = "https://staging3.activitar.com/ticket_api/tickets"
data = {'ticket_id':e1.get(),'direction': 'up'}
headers = {'Content-Type': 'application/json','Authorization' :'J0XDvDqVRy9hMF9Fo7j5'}
r = requests.post(url,data=json.dumps(data), headers=headers)
requestpost = requests.post(url, headers=headers, json=data)
response_data = requestpost.json()
statusvar = (response_data["status"])
messagevar = (response_data["message"])
json.dumps(url,data)
# MyEncoder().encode(ticketid)
#'{"ticekt_id": "/foo/bar"}'
#19 February 2018
#def from_json(json_object):
# if 'ticket_id' in json_object:
# return FileItem(json_object['ticket_id'])
# ticketid = JSONDecoder(object_hook = from_json).decode('{"ticket_id": "/foo/bar"}')
#Including GPIO config
if statusvar == "failed":
messagebox.showinfo("Cape Point", messagevar)
else: statusvar == "successful"
#Run at full screen automatically:
#---------------Function & Class--------------------------------#
class FullScreenApp(object):
def __init__(self, master, **kwargs):
self.master=master
pad=3
self._geom='200x200+0+0'
master.geometry("{0}x{1}+0+0".format(
master.winfo_screenwidth()-pad, master.winfo_screenheight()-pad))
master.bind('<Escape>',self.toggle_geom)
def toggle_geom(self,event):
geom=self.master.winfo_geometry()
print(geom,self._geom)
self.master.geometry(self._geom)
self._geom=geom
#--------------------------------------------------------------------#
def next_img():
img_label.img = PhotoImage(file=next(imgs))
img_label.config(image=img_label.img)
#create a textbox on a form
root = Tk()
#-----Full Screen-------#
app = FullScreenApp(root)
root.title("Cape Point")
root.configure(background = 'White')
#________ this code below was the original that displayed a static image _____#
#titlepic = PhotoImage(file = "ScanPlease.gif")
#shownpic = titlepic
#filename = shownpic
#Label(root, image = filename).grid(row=0, sticky=W)
img_dir = askdirectory(parent=root, initialdir= "C:/Users/Nickitaes/Desktop", title='Where To Scan')
os.chdir(img_dir)
imgs = iter(os.listdir(img_dir))
img_label = Label(root)
img_label.bind("<Return>",next_img())
next_img()
e1 = Entry(root)
e1.grid(row=1, column=0)
e1.focus_set() #set cursor focus to textbox
e1.bind("<Return>", apiconnect) #Return function
root.mainloop( )
Thanks for the help!
Well..., it was not hard to find other questions about this on StackOverflow. Here are some: Play Animations in GIF with Tkinter and Play an Animated GIF in python with tkinter.
I have combined the answers to take care of different number of subpictures an also commented the code a bit more.
from tkinter import *
import time
root = Tk()
framelist = [] # List to hold all the frames
for ix in range(1000): # range > frames in largest GIF
part = 'gif -index {}'.format(ix)
try: frame = PhotoImage(file='giphy.gif', format=part)
except:
last = len(framelist) - 1 # Save index for last frame
break # Will break when GIF index is reached
framelist.append(frame)
def update(ix):
if ix > last: ix = 0 # Reset frame counter if too big
label.configure(image=framelist[ix]) # Display frame on label
ix += 1 # Increase framecounter
root.after(100, update, ix) # Run again after 100 ms.
label = Label(root)
label.pack()
root.after(0, update, 0) # Start update(0) after 0 ms.
root.mainloop()
Adjust the for-loop for the GIF size you use, or rewrite as a while-loop.
I don't know how to read the frame delay from the GIF. You'll have to try different values in after() until it looks good.

Categories