简体   繁体   English

如何在 Tkinter 界面中显示来自 OpenCV 的图像?

[英]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.我正在尝试在取自 OpenCV 的 VideoCapture 的 Tkinter 界面中连续显示和替换图像。 However, I am getting the following error that I think is a result of improper formatting of the image numpy array:但是,我收到以下错误,我认为这是图像 numpy 数组格式不正确的结果:

TypeError: unhashable type: 'numpy.ndarray'类型错误:不可散列类型:'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.首先,您需要使用PIL.Image.fromarray()将捕获的图像转换为PIL.Image.fromarray()支持的格式。

Second better not use while loop in main thread as it will block the tkinter mainloop.其次最好不要在主线程中使用 while 循环,因为它会阻塞 tkinter 主循环。 Use after() instead.使用after()代替。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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