Display image based on a output in one window (Python) - python-3.x

I have an implementation of k-NN algorithm in Python, that returns the class label of an input. What I need is to show an image assigned to the class label in one window while output is coming (by refreshing the window). Problem is, I am not very experienced in GUI programming, thus I need some resources and assistance to start with. What libraries, books and tutorials could you recommend? Pieces of code would be appreciated too.

There are many libraries allow you add images to your program such as Turtle, PIL.ImagTk and Canvas and you can even use Pygame to a best performance.
PIL.ImagTk and Canvas:
from Tkinter import *
from PIL import ImageTk
backgroundImage = PhotoImage("image path (gif/PPM)")
canvas = Canvas(width = 200, height = 200, bg = 'blue')
canvas.pack(expand = YES, fill = BOTH)
image = ImageTk.PhotoImage(file = "C:/Python27/programas/zimages/gato.png")
canvas.create_image(10, 10, image = image, anchor = NW)
mainloop()
Turtle:
import turtle
screen = turtle.Screen()
# click the image icon in the top right of the code window to see
# which images are available in this trinket
image = "rocketship.png"
# add the shape first then set the turtle shape
screen.addshape(image)
turtle.shape(image)
screen.bgcolor("lightblue")
move_speed = 10
turn_speed = 10
# these defs control the movement of our "turtle"
def forward():
turtle.forward(move_speed)
def backward():
turtle.backward(move_speed)
def left():
turtle.left(turn_speed)
def right():
turtle.right(turn_speed)
turtle.penup()
turtle.speed(0)
turtle.home()
# now associate the defs from above with certain keyboard events
screen.onkey(forward, "Up")
screen.onkey(backward, "Down")
screen.onkey(left, "Left")
screen.onkey(right, "Right")
screen.listen()
Now let’s change the background
import turtle
screen = turtle.Screen()
# this assures that the size of the screen will always be 400x400 ...
screen.setup(400, 400)
# ... which is the same size as our image
# now set the background to our space image
screen.bgpic("space.jpg")
# Or, set the shape of a turtle
screen.addshape("rocketship.png")
turtle.shape("rocketship.png")
move_speed = 10
turn_speed = 10
# these defs control the movement of our "turtle"
def forward():
turtle.forward(move_speed)
def backward():
turtle.backward(move_speed)
def left():
turtle.left(turn_speed)
def right():
turtle.right(turn_speed)
turtle.penup()
turtle.speed(0)
turtle.home()
# now associate the defs from above with certain keyboard events
screen.onkey(forward, "Up")
screen.onkey(backward, "Down")
screen.onkey(left, "Left")
screen.onkey(right, "Right")
screen.listen()
for Turtle:
http://blog.trinket.io/using-images-in-turtle-programs/

Related

display video camera on two different windows tkinter python

i have a GUI python application that contain two different function windows and i'am trying to display video camera in the second window of tkinter application.
But, the video frame always be showing on the first windows!! i don't know if it is a problem of threads, or camera librairy. is there any fault in my code?
thanks in advance.
# add the necessairy librairy
import tkinter as tk
import threading
import time
import subprocess
from imutils.video import VideoStream
import time
import imutils
import cv2
import argparse
from PIL import Image
from PIL import ImageTk
class PhotoBoothApp:
def __init__(self,vs):
# store the video stream object and output path, then initialize
# the most recently read frame, thread for reading frames, and
# the thread stop event
self.vs = vs
self.frame = None
self.thread = None
self.stopEvent_2 = None
# initialize the root window and image panel
self.root = tk.Tk()
self.panel = None
self.user_input = tk.StringVar(self.root)
self.but_frame = tk.Frame(self.root)
w = 800 # width for the Tk root
h = 500 # height for the Tk root
# get screen width and height
ws = self.root.winfo_screenwidth() # width of the screen
hs = self.root.winfo_screenheight() # height of the screen
# calculate x and y coordinates for the Tk master window
x = (ws/3) - (w/3)
y = (hs/3) - (h/3)
# set the dimensions of the screen
# and where it is placed
self.root.geometry('%dx%d+%d+%d' % (w, h, x, y))
# when open the second window i want it to be on toplevel; it means when i click outside the frame it won't get hide
self.root.title("Test thread")
# create a button, that when pressed, will take the current
# frame and save it to file
btn = tk.Button(self.but_frame, bd = '5',text=" photo ")
self.but_frame.pack(side="left")
# start a thread that constantly pools the video sensor for
# the most recently read frame
self.stopEvent_2 = threading.Event()
self.thread = threading.Thread(target=self.videoLoop, args=())
self.thread.start()
# set a callback to handle when the window is closed
self.root.wm_protocol("WM_DELETE_WINDOW", self.onClose)
def videoLoop(self):
# DISCLAIMER:
# I'm not a GUI developer, nor do I even pretend to be. This
# try/except statement is a pretty ugly hack to get around
# a RunTime error that Tkinter throws due to threading
try:
# keep looping over frames until we are instructed to stop
while not self.stopEvent_2.is_set():
# grab the frame from the video stream and resize it to
# have a maximum width of 300 pixels
self.frame = self.vs.read()
self.frame = imutils.resize(self.frame, width=300)
#cv2.imshow('video player', self.frame)
# OpenCV represents images in BGR order; however PIL
# represents images in RGB order, so we need to swap
# the channels, then convert to PIL and ImageTk format
image = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
image = Image.fromarray(image)
image = ImageTk.PhotoImage(image)
# if the panel is not None, we need to initialize it
if self.panel is None:
self.panel = tk.Label(image=image)
self.panel.image = image
self.panel.pack(side="left", padx=10, pady=10)
# otherwise, simply update the panel
else:
self.panel.configure(image=image)
self.panel.image = image
except RuntimeError :
print("[INFO] caught a RuntimeError_________________________________________")
def onClose(self):
# set the stop event, cleanup the camera, and allow the rest of
# the quit process to continue
print("[INFO] closing...")
self.stopEvent_2.set()
self.vs.stop()
self.root.quit()
# here's the main window
Mafenetre = tk.Tk()
#set main window title
Mafenetre.title("GUI")
Mafenetre['bg']='white' # couleur de fond
# get screen width and height
wf1= Mafenetre.winfo_screenwidth()
hf1= Mafenetre.winfo_screenheight()
A = str(wf1)
B = str(hf1)
# set the dimensions of the screen
# and where it is placed
w = 500 # width for the Tk root
h = 500 # height for the Tk root
# get screen width and height
ws = Mafenetre.winfo_screenwidth() # width of the screen
hs = Mafenetre.winfo_screenheight() # height of the screen
# calculate x and y coordinates for the Tk master window
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
# set the dimensions of the screen
# and where it is placed
Mafenetre.geometry('%dx%d+%d+%d' % (w, h, x, y))
# add test button to the main window
reglage = tk.Button(Mafenetre, bd = '5',text=" PARAM ", bg='#c42034', fg='white',font= "Helvetica", 12))
reglage.pack(side=tk.TOP, padx=6,pady=35)
camera = VideoStream(0).start()
pba = PhotoBoothApp(camera)
Mafenetre.mainloop()

How to enhance window size selection on a tkinter project including button-image as label?

I'm currently working on a little project on python-3.x including some tkinter ressources. My program is made to display on a screen a list of pictures included in a directory, each picture is put on a button that is a sixth of the original image, and if we click on it, it display the image on his original size on a new window. The original window is set by the amount of pictures i put in the columns (i can choose in the code) and i ve made a scrollbar because i have to work with a lot of pictures.
But here is my problem, it's works fine except that if i change the window size, like reduce it for example, the buttons don't follow, they just vanish behind the window, and with the scrollbar.
I'm not particularly good in python so i was wondering that maybe by doing like a threading we could get the window size in live and then if the window size is inferior/superior of our columns of buttons, we could resize it and change the amount of columns then reload the page, but i will have to work with multiple image so it will take a lot of time.
from tkinter import *
from tkinter.filedialog import *
from tkinter.messagebox import *
from PIL import Image, ImageTk
import tkinter as tk
import glob
import os
import cv2
import copy
import _thread
import time
folder = 'X:/users/Robin/data/dataset-valid/visu/*.jpg'
a=glob.glob(folder)
fic = "../data/list.txt"
fichObj=open(fic,"w")
p = []
for f in a:
fichObj.write(f+"\n")
fichObj.close()
class SuperPhoto(object):
def __init__(self, photo , image):
self.photo = photo
temp = cv2.resize(image, (int((self.photo.width())/6) , int((self.photo.height())/6)))
red = temp[:,:,2].copy()
blue = temp[:,:,0].copy()
temp[:,:,0] = red
temp[:,:,2] = blue
temp = Image.fromarray(temp)
self.miniature = ImageTk.PhotoImage(temp)
def agrandir(self):
Newfen=Toplevel()
Newfen.geometry("+60+60")
#self.photo.resize((500,500))
print(type(self.photo))
label = Label(Newfen, image=self.photo, width=self.photo.width(), height=self.photo.height())
label.image = self.photo # keep a reference!
label.pack()
if os.path.exists (fic): #os.path utile
count = len(open(fic).readlines())
print(count)
#lin = open(fic).readlines()
#print(lin)
class ScrollableCanvas(Frame):
def __init__(self, parent, *args, **kw):
Frame.__init__(self, parent, *args, **kw)
canvas=Canvas(self,bg='#FFFFFF',width=300,height=300,scrollregion=(0,0,500,500))
canvas.update_idletasks()
vbar=Scrollbar(self,orient=VERTICAL)
vbar.pack(side=RIGHT, fill=Y)
vbar.config(command=canvas.yview)
canvas.config(width=1200,height=700)
canvas.config(yscrollcommand=vbar.set)
canvas.pack(side=LEFT,expand=True,fill=BOTH)
# create a frame inside the canvas which will be scrolled with it
self.interior = interior = Frame(canvas)
interior_id = canvas.create_window(0, 0, window=interior, anchor=NW )
# track changes to the canvas and frame width and sync them,
# also updating the scrollbar
def _configure_interior(event):
# update the scrollbars to match the size of the inner frame
size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
canvas.config(scrollregion="0 0 %s %s" % size)
if interior.winfo_reqwidth() != canvas.winfo_width():
# update the canvas's width to fit the inner frame
canvas.config(width=interior.winfo_reqwidth())
interior.bind('<Configure>', _configure_interior)
def _configure_canvas(event):
if interior.winfo_reqwidth() != canvas.winfo_width():
# update the inner frame's width to fill the canvas
canvas.itemconfigure(interior_id, width=canvas.winfo_width())
canvas.bind('<Configure>', _configure_canvas)
class Main_frame(Frame):
# Init
def __init__(self, fenetre_principale=None):
Frame.__init__(self, fenetre_principale)
self.grid()
self.scrollable_canvas = ScrollableCanvas(self)
self.scrollable_canvas.grid(row=1,column=1)
nbCol = 4
for file in a:
image = Image.open(file)
photo = ImageTk.PhotoImage(image)
w = photo.width()
L.append(int(w/6))
#print(L)
sumL = int(sum(L)/nbCol)
print(sumL)
p.append(SuperPhoto(photo, cv2.imread(file)))
for ligne in range(int(count/nbCol)):
for colonne in range(nbCol):
photo = p[ligne * nbCol + colonne]
button = Button(self.scrollable_canvas.interior, image=photo.miniature, command=photo.agrandir)
button.grid(row=ligne, column=colonne)
if __name__ == "__main__":
root = Tk()
root.title("VISU")
root.geometry("+0+0")
L= []
interface = Main_frame(fenetre_principale=root)
root.update_idletasks()
print(root.winfo_width())
print(root.geometry())
interface.mainloop()
So, I except this program to work like a classic directory display, with the columns that change automatically when we resize the window and with the scrollbar that follow it.
If you have any solutions it will really help me ..
You can try it, just put some jpeg pictures in a directory and change the folder variable with the link of your directory.
Thanks in advance for your help, if you have any questions to understand more clearly what i've said don't hesitate.
Each time the root window is resized, a <Configure> event is triggered. Catch it as follows:
def resize(event):
root.update_idletasks()
#update all image sizes here if needed
#all widgets can be 're-grided' here based on new width and height of root window
root.bind('<Configure>', resize)
If you want to ensure that your window cannot be resized, use the following:
root.resizable(False, False)

Removing background from a label in Tkinter

from tkinter import *
from tkinter import messagebox
import tkinter
import hashlib
from PIL import Image, ImageTk
from win32api import GetSystemMetrics
#===========================================================================================
#functions to center windows
def center_window_x(width):
x_coordinate = (GetSystemMetrics(0)/2) - (width/2)
return x_coordinate
def center_window_y(height):
y_coordinate = (GetSystemMetrics(1)/2) - (height/2)
return y_coordinate
#===========================================================================================
#function to create setup page
def first_time_setup(width, height):
setup_window = Tk()
#===========================================================================================
#remove window border and position in center
setup_window.overrideredirect(1)
setup_frame = Frame(setup_window)
setup_frame.pack_propagate(False)
setup_window.geometry('%dx%d+%d+%d' % (width, height, center_window_x(width), center_window_y(height)))
#===========================================================================================
#background image for setup window
canvas = Canvas(setup_window, width=width, height=height)
canvas.grid(columnspan=2)
image = Image.open("setup_background.jpg")
canvas.image = ImageTk.PhotoImage(image)
canvas.create_image(0, 0, image=canvas.image, anchor="nw")
#===================================================================================================
#add username label
start_title = Label(setup_window, text="Username")
start_title.place(x=430,y=225)
#===================================================================================================
#add admin user entry box
admin_user_ent = Entry(setup_window)
admin_user_ent.place(x=500,y=225)
first_time_setup(650, 300)
Is there a way to remove the white background behind the username label? I know how to change the colour of it, but how do I remove it all together.
Is there a way to remove the white background behind the username label? I know how to change the colour of it, but how do I remove it all together.
sorry for posting twice, apparently there wasn't enough text and too much code.
It sounds like you are asking how to make your Label have a transparent background. From my understanding at the moment tkinter does not have this feature for widgets like labels and buttons. However it is still possible to create your own see-through label with Canvas
Here is an example of using Canvas to achieve something similar to what you are looking to do.
import tkinter as tk
root = tk.Tk()
mycanvas = tk.Canvas(root, width = 200, height = 25)
mycanvas.create_rectangle(0, 0, 100, 40, fill = "green")
mycanvas.pack(side = "top", fill = "both", expand = True)
text_canvas = mycanvas.create_text(10, 10, anchor = "nw")
mycanvas.itemconfig(text_canvas, text="Look no background! Thats new!")
root.mainloop()

Rotating a pixmap in pyqt4 gives undesired translation

I'm trying to write a simple application that rotates a png image when a button is pressed. I have it all working fine except that as the image rotates it deviates from it's centre in a south-east direction. I would have thought it wasn't rotating around its centre, but it returns to the origin every 45 degrees of rotation, which is strange.
On a key event I'm simply calling:
pixmap = pixmap.transformed(QtGui.QTransform().rotate(-self.rot), QtCore.Qt.SmoothTransformation)
Is there a way to set the origin of the transformation to stop the image moving around?
A simple solution, if you are using a QLabel to draw the QPixmap, is to set the alignment of the QLabel to AlignCenter. Moreover, to avoid an initial resizing of the QLabel during the first 45 degrees of the image rotation, the minimum size of the QLabel can be set to the value of the pixmap's diagonal. The image should then properly rotate around its centre without any unwanted back-and-forth translation.
Below I demonstrate how this can be done in a simple application:
import sys
from PyQt4 import QtGui, QtCore
import urllib
class myApplication(QtGui.QWidget):
def __init__(self, parent=None):
super(myApplication, self).__init__(parent)
#---- Prepare a Pixmap ----
url = ('http://sstatic.net/stackexchange/img/logos/' +
'careers/careers-icon.png?v=0288ba302bf6')
self.img = QtGui.QImage()
self.img.loadFromData(urllib.urlopen(url).read())
pixmap = QtGui.QPixmap(self.img)
#---- Embed Pixmap in a QLabel ----
diag = (pixmap.width()**2 + pixmap.height()**2)**0.5
self.label = QtGui.QLabel()
self.label.setMinimumSize(diag, diag)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setPixmap(pixmap)
#---- Prepare a Layout ----
grid = QtGui.QGridLayout()
button = QtGui.QPushButton('Rotate 15 degrees')
button.clicked.connect(self.rotate_pixmap)
grid.addWidget(self.label, 0, 0)
grid.addWidget(button, 1, 0)
self.setLayout(grid)
self.rotation = 0
def rotate_pixmap(self):
#---- rotate ----
# Rotate from initial image to avoid cumulative deformation from
# transformation
pixmap = QtGui.QPixmap(self.img)
self.rotation += 15
transform = QtGui.QTransform().rotate(self.rotation)
pixmap = pixmap.transformed(transform, QtCore.Qt.SmoothTransformation)
#---- update label ----
self.label.setPixmap(pixmap)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
instance = myApplication()
instance.show()
sys.exit(app.exec_())
Which results in:
Alternatively, this post : can't get the image to rotate in center in Qt, seems to address your issue if you are painting the QPixmap directly with QPainter.

How do I get my program to update this tkinter label in my nested loop so that it shows the grayscale process?

So I made a program that converts an image to grayscale. I first used graphics.py from a Zelle's Python Programming An Introduction To Computer Science book. I believe this is based on tkinter. I finished the program using a nested loop to iterate through a .gif picture and grab each individual pixel, replacing it with a grayscale algorithm. I had the change happen in a loop and it gave it an effect that shows the grayscale happening across the window. This was slow but it looked neat, but I realized I wanted to be able to use more file types. I found PIL for Python 3.3 and tkinter, using PIL to open the images, turning them into a tkinter PhotoImage, than displaying them in a tkinter window. Now my program will show the image before being processed and after, I would simply like to see the program update the image in the loop so that it shows the grayscale process. Any help would be great appreciated.
Here is my code:
from PIL import Image, ImageTk
from graphics import GraphWin
import tkinter
window = tkinter.Tk()
window.title('# Grayscale')
def GrayScaleConvertor():
#Opens image, creates window and draws image
picToConvert = 'sea.jpg'
pic = Image.open(picToConvert)
picWidth, picHeight = pic.size
# Treats the image as a 2d array, iterates through changing the
#values of each pixel with the algorithm for gray
tkPic = ImageTk.PhotoImage(pic, master = window)
label1 = tkinter.Label(window, image = tkPic)
rgbList = pic.load() #Get a 2d array of the pixels
for row in range(picWidth):
for column in range(picHeight):
rgb = rgbList[row,column]
r,g,b = rgb # Unpacks the RGB value tuple per pixel
grayAlgorithm1 = (r+g+b) // 3
rgbList[row,column] = (grayAlgorithm1, grayAlgorithm1, grayAlgorithm1)
# Converting to a tkinter PhotoImage
tkPic1 = ImageTk.PhotoImage(pic, master = window)
label2 = tkinter.Label(window, image = tkPic1)
# Draws the images to the window
label1.pack() # The image before grayscale
label2.pack() # The image after being grayscaled
window.mainloop()
GrayScaleConvertor()
You could use after(time, function_name) to call function (for example) every 10ms and change one (or more) pixel.
pseudocode:
tkinter.after(10, change_one_pixel)
def change_one_pixel():
change_next_pixel() # if you change more pixels you get faster animation
create_new_image()
update_label()
if any_pixel_left:
tkinter.after(10, change_one_pixel)
EDIT:
Full working code
#import Tkinter as tk # Python 2.7.x
import tkinter as tk # Python 3.x
from PIL import Image, ImageTk
class GrayScaleConvertor():
def __init__(self):
self.window = tk.Tk()
self.window.title('# Grayscale')
#Opens image, creates window and draws image
picToConvert = 'sea.jpg'
#picToConvert = 'background.jpg'
self.pic = Image.open(picToConvert)
# Treats the image as a 2d array, iterates through changing the
#values of each pixel with the algorithm for gray
self.tkPic1 = ImageTk.PhotoImage(self.pic, master = self.window)
self.label1 = tk.Label(self.window, image = self.tkPic1)
# Converting to a tkinter PhotoImage
self.tkPic2 = ImageTk.PhotoImage(self.pic, master = self.window)
self.label2 = tk.Label(self.window, image = self.tkPic2)
# Draws the images to the window
self.label1.pack() # The image before grayscale
self.label2.pack() # The image after being grayscaled
self.column = 0 # start column
self.step = 10 # number columns in one step
self.window.after(1, self.change_pixel) # 1ms
def run(self):
self.window.mainloop()
def change_pixel(self):
rgbList = self.pic.load() #Get a 2d array of the pixels
picWidth, picHeight = self.pic.size
# not to leave image
if self.column + self.step > picWidth:
self.step = picWidth - self.column
# change columns
for column in range(self.column, self.column+self.step):
for row in range(picHeight):
rgb = rgbList[column,row]
r,g,b = rgb # Unpacks the RGB value tuple per pixel
grayAlgorithm1 = (r+g+b) // 3
rgbList[column,row] = (grayAlgorithm1, grayAlgorithm1, grayAlgorithm1)
# change image in label
if self.tkPic2:
del self.tkPic2
self.tkPic2 = ImageTk.PhotoImage(self.pic, master = self.window)
self.label2.config(image = self.tkPic2)
# move start column
self.column += self.step
# if still are columns - call again
if self.column < picWidth:
print "change image"
self.window.after(1, self.change_pixel)
else:
print "the end"
GrayScaleConvertor().run()

Resources