0

I am trying to continuously display and replace an image in a Tkinter interface taken from OpenCV's VideoCapture. However, I am getting the following error that I think is a result of improper formatting of the image numpy array:

TypeError: unhashable type: 'numpy.ndarray'

How can I reformat it to all it to display properly? Below is my code:

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

main = tk.Tk()
main.title("Hole Pattern Recognition")
main.geometry("300x300")

frame = tk.Frame(main)
frame.pack()

def startScan():
    global main, frame
    #begins utilizing webcam for scan
    cap = cv2.VideoCapture(0)
    while(True):
        ret,img = cap.read()
        img = ImageTk.PhotoImage(img)
        panel = tk.Label(main, image = img)
        panel.pack(side = "bottom", fill = "both", expand = "yes")
        ch = cv2.waitKey(1)
        if ch == ord('q'):
            break
        
    cap.release()
    cv2.destroyAllWindows()

    
    
startButton = tk.Button(frame, 
                   text="Start Scan", 
                   fg="blue",
                   command=startScan)

startButton.pack(side=tk.TOP)
main.mainloop()
6
  • Could you please include you import statements? Commented Oct 29, 2020 at 23:33
  • stackoverflow.com/questions/28670461/… I think this will work for you. Commented Oct 30, 2020 at 0:24
  • First you need to use PIL.Image.fromarray() to convert the captured image to format supported by tkinter. Second better not use while loop in main thread as it will block the tkinter mainloop. Commented Oct 30, 2020 at 1:38
  • 1
    @Ralubrusto I just updated the import statements Commented Oct 30, 2020 at 1:57
  • 1
    Use after() instead of the while loop. Commented Oct 30, 2020 at 2:47

1 Answer 1

1

First you need to use PIL.Image.fromarray() to convert the captured image to format supported by tkinter.

Second better not use while loop in main thread as it will block the tkinter mainloop. Use after() instead.

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

cap = None

main = tk.Tk()
main.title('Hole Pattern Recognition')
#main.geometry('300x300')

frame = tk.Frame(main)
frame.pack()

def startScan():
    global cap

    def scan():
        ret, img = cap.read()
        if ret:
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
            img = Image.fromarray(img)
            tkimg = ImageTk.PhotoImage(img)
            panel.config(image=tkimg)
            panel.tkimg = tkimg # save a reference to the image to avoid garbage collection
        panel.after(25, scan) # change 25 to other value to adjust FPS

    if cap is None:
        cap = cv2.VideoCapture(0)
        scan() # start the capture loop
    else:
        print('capture already started')

startButton = tk.Button(frame, text='Start Scan', fg='blue', command=startScan)
startButton.pack()

panel = tk.Label(main)
panel.pack()

main.mainloop()

if cap:
    cap.release()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.