[英]Mouse events on cv2 images in Tkinter window
I'm working on a program that allows you to free-form crop an image and simultaneously show you the resultant image.我正在开发一个程序,该程序允许您自由裁剪图像并同时向您显示生成的图像。 The following code achieves this.
下面的代码实现了这一点。
import numpy as np
import cv2
def crop(pts):
global res
pts = np.array(pts)
mask = np.zeros((height, width), dtype=np.uint8)
cv2.fillPoly(mask, [pts], (255))
res = cv2.bitwise_and(img,img,mask = mask)
rect = cv2.boundingRect(pts) # returns (x,y,w,h) of the rect
cropped = res[rect[1]: rect[1] + rect[3], rect[0]: rect[0] + rect[2]]
cv2.imshow('res', res)
def mouse_callback(event, x, y, flags, params):
global selecting, pts, img
if event == cv2.EVENT_LBUTTONDOWN:
selecting = True
elif event == cv2.EVENT_MOUSEMOVE:
if selecting == True:
pts.append((x, y))
crop(pts)
print((x,y))
elif event == cv2.EVENT_LBUTTONUP:
selecting = False
res = None
selecting = False
pts = []
img = cv2.imread("girl.png", -1)
height = img.shape[0]
width = img.shape[1]
cv2.namedWindow('image')
cv2.setMouseCallback('image', mouse_callback)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.imwrite("res.png", res)
My challenge is to encapsulate the above code into an interface as follows:我的挑战是将上述代码封装到一个接口中,如下所示:
So far I have followed a tutorial to achieve something similar:到目前为止,我已经按照教程来实现类似的目标:
# import the necessary packages
from tkinter import *
from PIL import Image
from PIL import ImageTk
from tkinter import filedialog as tkf
import cv2
def select_image():
# grab a reference to the image panels
global panelA, panelB
# open a file chooser dialog and allow the user to select an input
# image
path = tkf.askopenfilename()
# ensure a file path was selected
if len(path) > 0:
# load the image from disk, convert it to grayscale, and detect
# edges in it
image = cv2.imread(path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edged = cv2.Canny(gray, 50, 100)
# OpenCV represents images in BGR order; however PIL represents
# images in RGB order, so we need to swap the channels
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# convert the images to PIL format...
image = Image.fromarray(image)
edged = Image.fromarray(edged)
# ...and then to ImageTk format
image = ImageTk.PhotoImage(image)
edged = ImageTk.PhotoImage(edged)
# if the panels are None, initialize them
if panelA is None or panelB is None:
# the first panel will store our original image
panelA = Label(image=image)
panelA.image = image
panelA.pack(side="left", padx=10, pady=10)
# while the second panel will store the edge map
panelB = Label(image=edged)
panelB.image = edged
panelB.pack(side="right", padx=10, pady=10)
# otherwise, update the image panels
else:
# update the pannels
panelA.configure(image=image)
panelB.configure(image=edged)
panelA.image = image
panelB.image = edged
# initialize the window toolkit along with the two image panels
root = Tk()
panelA = None
panelB = None
# create a button, then when pressed, will trigger a file chooser
# dialog and allow the user to select an input image; then add the
# button the GUI
btn = Button(root, text="Select an image", command=select_image)
btn.pack(side="bottom", fill="both", expand="yes", padx="10", pady="10")
# kick off the GUI
root.mainloop()
What I have not managed to accomplish is implement the mouse event in tkinter, as the function takes in a window name - but I only want it to get applied to the image.我没有设法完成的是在 tkinter 中实现鼠标事件,因为 function 采用 window 名称 - 但我只希望它应用于图像。 How can I achieve this?
我怎样才能做到这一点?
Instead of bind your command to your image, bind it to the tk.Label that contains the image:不要将命令绑定到图像,而是将其绑定到包含图像的 tk.Label:
import tkinter as tk
from PIL import Image
from PIL import ImageTk
root = tk.Tk()
ima = Image.open('test.png')
imag = ImageTk.PhotoImage(ima)
lab = tk.Label(root, image=imag)
lab.pack()
lab.bind('<Button-1>', *function)
root.mainloop()
Explaination解释
Tkinter provides a powerful mechanism to let you deal with events yourself.
Tkinter 提供了强大的机制让您自己处理事件。 For each widget , you can bind Python functions and methods to events.
对于每个小部件,您可以将Python 函数和方法绑定到事件。
(...)
(...)
Events are given as strings, using a special event syntax :
事件以字符串形式给出,使用特殊的事件语法:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.