python - Tkinter 窗口中 cv2 图像上的鼠标事件

标签 python opencv tkinter

我正在开发一个程序,该程序允许您自由裁剪图像并同时向您显示生成的图像。下面的代码实现了这一点。

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)
我的挑战是将上述代码封装到一个接口(interface)中,如下所示:
enter image description here
到目前为止,我已经按照教程来实现类似的目标:
# 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()
我没有设法完成的是在 tkinter 中实现鼠标事件,因为该函数接受一个窗口名称 - 但我只希望它应用于图像。我怎样才能做到这一点?

最佳答案

与其将命令绑定(bind)到图像,不如将其绑定(bind)到包含图像的 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()
解释

Tkinter provides a powerful mechanism to let you deal with events yourself. For each widget, you can bind Python functions and methods to events.

(...)

Events are given as strings, using a special event syntax:

关于python - Tkinter 窗口中 cv2 图像上的鼠标事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63171685/

相关文章:

Python3 - Tkinter - 即时消息

python - GEMM 使用 Numpy einsum

javascript - 从 python 调用 Javascript

Python:奇怪的 for 循环行为

c++ - 调试断言失败表达式 : _pFirstBlock == pHead using OpenCV and C++ trying to call SurfFeatureDetector

c++ - HoughLinesP 和 opencv 内存管理

python - 执行时 tkinter 窗口为空白

python - 如何使用 pandas styler 对象的 .head() 方法?

opencv - 使用opencv将一个形状放在另一个形状内

python - 所有 Tkinter 事件的主列表?