简体   繁体   中英

How to display an image from OpenCV in a Tkinter interface?

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()

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM