Home > database >  How to implement opencv selectROI in tkinter?
How to implement opencv selectROI in tkinter?

Time:09-24

I have a image that I want to use it in tkinter and use select ROI function from OpenCv with the mouse events. I have no idea on how to achieve this problem but I tried the best I can, here is my code. My problem is I have error saying my variable at (lbl tkimgis) is not defined. Is there any other way to achieve this or any suggestions that I can make changes? Thank you for your help. Have a nice day!

from tkinter import *
import numpy as np
import cv2
import sys
import PIL.Image as imge
import PIL.ImageTk as imtk

ev = None

def click(event, u16):
    global subregion, tkimgis, ev
    if ev == None:
        ev = event
        return None
    bbox = cv2.selectROI("Image", u16, fromCenter=False)
    cv2.destroyWindow("Image")

    print("region:", bbox)
    ####Here u16 is my image array from another jupyter notebook cell

    tkimgis = imtk.PhotoImage(image=imge.fromarray(u16))
    lbl.config(image=tkimgis)
    (x,y,w,h) = bbox
    subregion = na[y:y h, x:x w]
    ev = event
root = Tk()
lbl = Label(root, image=tkimgis)
lbl.place(x=0, y=0)
root.bind('<Button-1>', lambda event: click(event))
root.mainloop()

CodePudding user response:

Currently, your code has so many other things that I feel are not done right, So I'll provide a code that you can then carefully study.

In short, you need to run cv2.selectROI in a different thread, and then update the label image from the main thread.

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


def display_roi(event):
    global tkimg

    if image:
        tkimg = ImageTk.PhotoImage(image)
        cropped_lbl.config(image=tkimg)

def select_roi():
    global image

    img = cv2.imread("sample.png")
    roi  = cv2.selectROI(img)

    imCrop = img[int(roi[1]):int(roi[1] roi[3]), int(roi[0]):int(roi[0] roi[2])]
    
    if len(imCrop)>0:
        image = Image.fromarray(cv2.cvtColor(imCrop, cv2.COLOR_BGR2RGB))

    cv2.destroyAllWindows()
    root.event_generate("<<ROISELECTED>>")

def start_thread():

    thread = Thread(target=select_roi, daemon=True)
    thread.start()


root = tk.Tk()

cropped_lbl = tk.Label(root)
cropped_lbl.pack(expand=True, fill="both")

tk.Button(root, text="select ROI", command=start_thread).pack()

root.bind("<<ROISELECTED>>", display_roi)
root.mainloop()

  • Related