Dashdamirov
Dashdamirov

Reputation: 7

Displaying multiple images side by side with tkinter

I wrote a program for facial recognition and now I have to make a GUI for it. What I need to do is to display 5 images of recognized person. But I can only display one of them. The others are shown empty. Here is the code:

root = Tk()
root.title("Test state")

def train_button():
    os.system('python3 extract_embeddings.py --dataset dataset --embeddings output/embeddings.pickle --detector face_detection_model --embedding-model openface_nn4.small2.v1.t7')
    os.system('python3 train_model.py --embeddings output/embeddings.pickle --recognizer output/recognizer.pickle --le output/le.pickle')
    messagebox.showinfo("INFO","Training completed")

def select_photo():
    global my_image
    root.filename = filedialog.askopenfilename(initialdir="test",title ="Select a photo",filetypes=(("all files","*.*"),("png files","*.png"),("jpeg files","*.jpeg")))
    output = subprocess.check_output("python3 recognize.py --detector face_detection_model --embedding-model openface_nn4.small2.v1.t7 --recognizer output/recognizer.pickle --le output/le.pickle --image "+root.filename, shell=True)
    output = output.decode('utf-8')
    pic_name = output.split('\n')[0]
     
    my_image = ImageTk.PhotoImage(Image.open("images/"+pic_name+"/"+pic_name+"1.jpeg"))
    my_image_label = Label(image = my_image).grid(row = 1 ,column = 0)

    name_label = Label(text = pic_name).grid(row=2,column=0)

    my_image1 = ImageTk.PhotoImage(Image.open("images/"+pic_name+"/"+pic_name+"2.jpeg"))
    my_image_label1 = Label(image = my_image1).grid(row =1 ,column=1)

    my_image2 = ImageTk.PhotoImage(Image.open("images/"+pic_name+"/"+pic_name+"3.jpeg"))
    my_image_label2 = Label(image = my_image2).grid(row = 1,column = 2)


button1 = Button(root,text = "Train" , command = train_button).grid(row=0 ,column=0)

button2 = Button(root,text = "Recognise from image", command = select_photo).grid(row = 0 ,column=1)



root.mainloop()

This is how the program shows images Resulting program

Thank you for your time

Upvotes: 0

Views: 6816

Answers (1)

furas
furas

Reputation: 142651

It is bug in PhotoImage which removes image when it is assigned to local variable in function.

You have to assing it to global variable (it can be list if you have many images) or assign to widgets which you use to display it - label.photo = image


I can test it but here is version which uses label.photo = image to resolve this problem

It also uses for-loop to create labels and keep them on list.

But when you use label.photo = image then list is not necessary. List is only useful to access labels to remove old labels before you create new labels.

import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import filedialog

# --- functions ---

def train_button():
    os.system('python3 extract_embeddings.py --dataset dataset --embeddings output/embeddings.pickle --detector face_detection_model --embedding-model openface_nn4.small2.v1.t7')
    os.system('python3 train_model.py --embeddings output/embeddings.pickle --recognizer output/recognizer.pickle --le output/le.pickle')
    messagebox.showinfo("INFO","Training completed")

def select_photo():
    #global all_labels
    
    root.filename = filedialog.askopenfilename(initialdir="test", title ="Select a photo", filetypes=(("all files","*.*"),("png files","*.png"),("jpeg files","*.jpeg")))
    output = subprocess.check_output("python3 recognize.py --detector face_detection_model --embedding-model openface_nn4.small2.v1.t7 --recognizer output/recognizer.pickle --le output/le.pickle --image "+root.filename, shell=True)
    output = output.decode('utf-8')
    pic_name = output.split('\n')[0]

    # remove previous labels
    for label in all_labels:
        label.destroy()
    
    for number in range(3):
        #filename = f"images/{pic_name}/{pic_name}{number+1}.jpeg" # f-string (Python 3.6+)
        filename = "images/{}/{}{}.jpeg".format(pic_name, pic_name, number+1) # (Python 2.7, 3.0+)
        
        image = ImageTk.PhotoImage(Image.open(filename))
        
        label = tk.Label(image=image)
        label.photo = image   # assign to class variable to resolve problem with bug in `PhotoImage`
        
        label.grid(row=1, column=number)
        
        all_labels.append(label)

# --- main ---

all_labels = []

root = tk.Tk()

button1 = tk.Button(root, text="Train", command=train_button)
button1.grid(row=0, column=0)

button2 = tk.Button(root, text="Recognise from image", command=select_photo)
button2.grid(row=0, column=1)

root.mainloop()

Upvotes: 1

Related Questions