1

I am trying to make a GUI-based face recognition program with tkinter and opencv. I have used the function cv2.VideoCapture() before, but usually NOT inside a function and it worked successfully.

This time, though, I wanted to use it inside a function, but the program just does not run. I got no errors in the terminal, and the window just froze.

Here is my code (I haven't yet added the face recognition functionality)

import tkinter as tk
from PIL import Image, ImageTk

root = tk.Tk()
root.configure(bg='#3d3d3d')
f1 = tk.LabelFrame(root, bg='#3d3d3d')
f1.place(relx=0.5, rely=0.53, anchor=tk.CENTER)
feed = tk.Label(f1)
feed.pack()

cap = cv2.VideoCapture(0)

def capture():    
    while cap.isOpened():
        img = cap.read()[1]  
        img = cv2.flip(img, 1)
        img1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # changing color to RGB
        img = ImageTk.PhotoImage(Image.fromarray(img1)) 
        feed['image'] = img  # putting the webcam feed in the 'feed' LabelFrame

capture()

root.mainloop()

I tried to input values 0, 1, -1 for the VideoCapture() function, but the problem persisted

Note that this is not my full code and I have just included the important parts. I am asking this question because I want to implement this functionality on a Toplevel() window which is opened by clicking a button. The code for the Toplevel() window is indside a function.

Thanks in advance!

NISH3003
  • 92
  • 1
  • 7
  • 2
    Does this answer your question? [Why does Tkinter image not show up if created in a function?](https://stackoverflow.com/questions/16424091/why-does-tkinter-image-not-show-up-if-created-in-a-function) – acw1668 Sep 20 '21 at 07:33
  • 1
    Another issue is that you used while loop which will block `root.mainloop()` from executing. – acw1668 Sep 20 '21 at 07:34
  • I had checked that link earlier, and it doesnt fix the issue – NISH3003 Sep 20 '21 at 07:40
  • The problem, as far as I have tested it, lies within the VideoCapture() function rather than tkinter – NISH3003 Sep 20 '21 at 07:41
  • infact the `feed['image'] = img` line is performing that same function which was provided as an answer for the link you sent – NISH3003 Sep 20 '21 at 07:43
  • 1
    No `feed['image']` is used to change the *`image` option* of the label, whereas `feed.image = img` is using *an attribute named "image"* to store the reference of the image. As I said, `root.mainloop()` has been blocked from executing due to the while loop, so you cannot see the window at all. – acw1668 Sep 20 '21 at 07:47
  • I see, ok mate, can you suggest some fixes if possible? I got your point though – NISH3003 Sep 20 '21 at 07:50

1 Answers1

1

There are mainly two issues in your code:

  • using while loop which will block root.mainloop() from executing. Use after() instead.
  • image created inside a function will be garbage collected if its reference is not saved

Below is a modified code to fix the above issues:

import tkinter as tk
from PIL import Image, ImageTk
import cv2

root = tk.Tk()
root.configure(bg='#3d3d3d')
root.geometry('800x600')

f1 = tk.LabelFrame(root, bg='#3d3d3d')
f1.place(relx=0.5, rely=0.53, anchor=tk.CENTER)

feed = tk.Label(f1)
feed.pack()

cap = cv2.VideoCapture(0)

# used after() instead of while loop
def capture():
    if cap.isOpened():
        ret, img = cap.read()
        if ret:
            img = cv2.flip(img, 1)
            img1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # changing color to RGB
            img = ImageTk.PhotoImage(Image.fromarray(img1))
            feed['image'] = img  # putting the webcam feed in the 'feed' LabelFrame
            feed.image = img # save reference of the image
    root.after(10, capture)

capture()

root.mainloop()
acw1668
  • 40,144
  • 5
  • 22
  • 34