2

I wrote a code in Tkinter that should execute the function of face recognition as soon as the user click on the button and simultaneously it should redirect to the next frame.

What the problem I am currently facing is, when the user clicks on the button, the face recognition function, that is in my code gen(), executes first and as soon as it terminates, it redirects to the next frame.

What I want is both should work at the same time.. Any suggestion please?

from tkinter import *
from PIL import Image, ImageTk
import cv2
import numpy as np
import os
import json
  
class tkinterApp(Tk): 
      
    def __init__(self, *args, **kwargs):  
          
        Tk.__init__(self, *args, **kwargs) 
          
        container = Frame(self)   
        container.pack(side = "top", fill = "both", expand = True)  
   
        self.frames = {}

        for F in (StartPage, Page1, Page2): 
   
            frame = F(container, self) 

            self.frames[F] = frame  
   
            frame.grid(row = 0, column = 0, sticky ="nsew")
        self.update()
        self.show_frame(StartPage)

    def show_frame(self, cont):
        if cont not in self.frames:
            self.frames[cont] = cont(self.container, self)
        frame = self.frames[cont]
        frame.tkraise()
        frame.event_generate("<<ShowFrame>>")

   
class StartPage(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        self.controller = controller
        self.bind("<<ShowFrame>>", self.myStartPage)

    def myStartPage(self,controller):
        super(StartPage).__init__()

        canvas = Canvas(self,width=2300, height=900, bd=0, highlightthickness=0, relief='ridge')
        canvas.pack()

        self.background = PhotoImage(file="Images/background.png")
        canvas.create_image(525,425,image=self.background, tags="B")

        self.bg = PhotoImage(file="Images/bg-top.png")
        canvas.create_image(0,335,image=self.bg, anchor=NW)

        self.my_pic1 = PhotoImage(file="Images/start000-befored.png")
        obj1 = canvas.create_image(1200,290,image=self.my_pic1, anchor=NW)

        recognizer = cv2.face.LBPHFaceRecognizer_create()
        recognizer.read('trainer/trainer.yml')
        cascadePath = "Cascades/haarcascade_frontalface_default.xml"
        faceCascade = cv2.CascadeClassifier(cascadePath)

        font = cv2.FONT_HERSHEY_SIMPLEX

        cam = cv2.VideoCapture(0)
        cam.set(3, 640)
        cam.set(4, 480)

        minW = 0.1*cam.get(3)
        minH = 0.1*cam.get(4)            

        def get_frame():
            laebl = ""
            names = ['None', 'Marcelo', 'Paula', 'Ilza', 'Z', 'W'] 
            while True:
                ret, img =cam.read()
                gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
                faces = faceCascade.detectMultiScale(
                    gray,
                    scaleFactor = 1.2,
                    minNeighbors = 5,
                    minSize = (int(minW), int(minH)),
                    )
                for(x,y,w,h) in faces:
                    cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
                    label, confidence = recognizer.predict(gray[y:y+h,x:x+w])
                    if (confidence < 50):
                        label = names[label]
                        confidence = "  {0}%".format(round(100 - confidence))
                    else:
                        label = "unknown"
                        confidence = "  {0}%".format(round(100 - confidence))
                    cv2.putText(img, str(label), (x+5,y-5), font, 1, (255,255,255), 2)
                    cv2.putText(img, str(confidence), (x+5,y+h-5), font, 1, (255,255,0), 1)
                    #cv2.imshow('camera',img)
                ret, jpeg = cv2.imencode('.jpg', img)
                cv2.destroyAllWindows()
                return label, jpeg.tobytes()

        def gen():
            flag = 1
            while True:
                label, frame = get_frame()
                flag += 1
                if label=="unknown" and flag > 70:
                    cam.release()
                    print("Unknown Face Detected!")
                    break

        canvas.tag_bind(obj1, '<1>', lambda event=None : [self.controller.show_frame(Page1), gen()]) 
           
class Page1(Frame): 
      
    def __init__(self, parent, controller): 
          
        Frame.__init__(self, parent)
        self.controller = controller
        self.bind("<<ShowFrame>>", self.myPage1)


    def myPage1(self,controller):
        super(Page1).__init__()

        canvas = Canvas(self,width=2300, height=900, bd=0, highlightthickness=0, relief='ridge')
        canvas.pack()

        self.background = PhotoImage(file="Images/background.png")
        canvas.create_image(525,425,image=self.background, tags="B")

        self.bg = PhotoImage(file="Images/bg-top.png")
        bg_tk = canvas.create_image(0,335,image=self.bg, anchor=NW)

        self.bg1 = PhotoImage(file="Images/bg-bottom.png")
        bg1_tk = canvas.create_image(0,335,image=self.bg1, anchor=NW)

        self.after(3000, lambda event=None : self.controller.show_frame(Page2))
        
class Page2(Frame): 
      
    def __init__(self, parent, controller): 
          
        Frame.__init__(self, parent)
        self.controller = controller
        self.bind("<<ShowFrame>>", self.myPage2)

    def myPage2(self,controller):
        super(Page1).__init__()
        canvas = Canvas(self,width=2300, height=900, bd=0, highlightthickness=0, relief='ridge')
        canvas.pack()

        self.background = PhotoImage(file="Images/background.png")
        canvas.create_image(525,425,image=self.background)

        self.bg = PhotoImage(file="Images/bg-top.png")
        bg_tk = canvas.create_image(0,70,image=self.bg, anchor=NW)

        self.bg1 = PhotoImage(file="Images/bg-bottom.png")
        bg1_tk = canvas.create_image(0,777,image=self.bg1, anchor=NW)


# Driver Code 
app = tkinterApp()
app.title("My Project")
app.mainloop() 

martineau
  • 119,623
  • 25
  • 170
  • 301
sodmzs1
  • 324
  • 1
  • 12
  • It won't be easy to do. Suggest you read accepted answer to [Tkinter — executing functions over time](https://stackoverflow.com/questions/9342757/tkinter-executing-functions-over-time) which is about even-driven programming in GUIs in general. – martineau Dec 13 '20 at 09:06
  • Thanks for the suggestion but I don't think it's relevant in my case. I can't use `after()` method to execute my `gen()` (face recognition function) as I want it in the backend, while on the frontend, it should redirect to the another frame. so basically, both should happens at the same time. – sodmzs1 Dec 13 '20 at 09:40
  • Unfortunately, `tkinter` doesn't support multithreading — and it sounds like that's what you need — in the sense that only one thread in a such an application can access the library. A common workaround is to use a `Queue` to pass information between threads and use `after()` in the GUI thread to periodically check for new data having been put into it (and change the GUI's appearance if appropriate). – martineau Dec 13 '20 at 09:57
  • ...see my answer to [Freezing/Hanging tkinter Gui in waiting for the thread to complete](https://stackoverflow.com/questions/53696888/freezing-hanging-tkinter-gui-in-waiting-for-the-thread-to-complete) for an example. – martineau Dec 13 '20 at 10:05
  • Can you help me with the code ? I don't understand properly to to implement this in it :9 – sodmzs1 Dec 13 '20 at 10:36
  • I am not too sure about the intentions but you can try looking into multithreading. Try to create multiple threads for concurrent tasks (if they are independent of each other) – Tanishq Vyas Dec 13 '20 at 11:54
  • Sorry, I can't help with your code because it isn't a [mre] and is using modules (and hardware I don't have). Unfortunately, that will also prevent others from being able to assist as well… – martineau Dec 13 '20 at 16:57
  • 1
    @TanishqVyas: Suggest you read earlier preceding comments to avoid posting your own, redundant ones. – martineau Dec 13 '20 at 17:01
  • Try running `gen()` in a thread: `canvas.tag_bind(obj1, '<1>', lambda e: [threading.Thread(target=gen,daemon=True).start(), self.controller.show_frame(Page1)]) `. You need to `import threading`. – acw1668 Dec 14 '20 at 09:58

0 Answers0