gpt4 book ai didi

python - 用鼠标选择图像区域并记录选择的尺寸

转载 作者:太空宇宙 更新时间:2023-11-04 08:27:39 26 4
gpt4 key购买 nike

我希望能够使用鼠标光标将矩形选区拖到程序中显示的图像上,并读取选区的尺寸,以便稍后可以使用它们来裁剪该图像。我如何在 Python 3 中执行此操作?

更新:

假设我这样做:

import tkinter as tk
from PIL import ImageTk, Image

#This creates the main window of an application
window = tk.Tk()
window.title("Join")
window.geometry("900x900")
window.configure(background='grey')

path = "Book.jpg"

#Creates a Tkinter-compatible photo image, which can be used everywhere Tkinter expects an image object.
img = ImageTk.PhotoImage(Image.open(path))

#The Label widget is a standard Tkinter widget used to display a text or image on the screen.
panel = tk.Label(window, image = img)

#The Pack geometry manager packs widgets in rows or columns.
panel.pack(side = "bottom", fill = "both", expand = "yes")

#Start the GUI
window.mainloop()

最佳答案

不幸的是,这是另一种更复杂的方法(因为它完成了您在对我的 first answer 的评论中提到的几件事情)。它使用 tkinter 的矢量图形(不是 PIL 的图像处理)功能对选择之外的区域进行着色,我认为这使它成为重量更轻,也可能更快的方法,因为它不涉及处理相对大量的图像数据和传输它。

最初我试图将阴影外部区域绘制为单个连续多边形,但这没有用,因为 tkinter 不支持这种凹多边形形状,因此绘制了四个无边框矩形取而代之的是——加上一个空的,只有一个边框来勾勒出所选区域的轮廓(下图)。

我借用了一个ActiveState Code » Recipe中使用的一些有趣的想法标题为 Pʏᴛʜᴏɴ Tᴋɪɴᴛᴇʀ Cᴀɴᴠᴀs Rᴇᴄᴛᴀɴɢʟᴇ Sᴇʟᴇᴄᴛɪᴏɴ Bᴏx Sunjay Varma 着。

该代码是面向对象的,希望能使其更易于理解(和扩展)。请注意,您可以通过调用 MousePositionTracker 类实例的 cur_selection() 方法将当前选择矩形作为两个点获取,这样可用于获取执行实际操作所需的信息图像裁剪(可能涉及使用PIL)。

import tkinter as tk
from PIL import Image, ImageTk


class MousePositionTracker(tk.Frame):
""" Tkinter Canvas mouse position widget. """

def __init__(self, canvas):
self.canvas = canvas
self.canv_width = self.canvas.cget('width')
self.canv_height = self.canvas.cget('height')
self.reset()

# Create canvas cross-hair lines.
xhair_opts = dict(dash=(3, 2), fill='white', state=tk.HIDDEN)
self.lines = (self.canvas.create_line(0, 0, 0, self.canv_height, **xhair_opts),
self.canvas.create_line(0, 0, self.canv_width, 0, **xhair_opts))

def cur_selection(self):
return (self.start, self.end)

def begin(self, event):
self.hide()
self.start = (event.x, event.y) # Remember position (no drawing).

def update(self, event):
self.end = (event.x, event.y)
self._update(event)
self._command(self.start, (event.x, event.y)) # User callback.

def _update(self, event):
# Update cross-hair lines.
self.canvas.coords(self.lines[0], event.x, 0, event.x, self.canv_height)
self.canvas.coords(self.lines[1], 0, event.y, self.canv_width, event.y)
self.show()

def reset(self):
self.start = self.end = None

def hide(self):
self.canvas.itemconfigure(self.lines[0], state=tk.HIDDEN)
self.canvas.itemconfigure(self.lines[1], state=tk.HIDDEN)

def show(self):
self.canvas.itemconfigure(self.lines[0], state=tk.NORMAL)
self.canvas.itemconfigure(self.lines[1], state=tk.NORMAL)

def autodraw(self, command=lambda *args: None):
"""Setup automatic drawing; supports command option"""
self.reset()
self._command = command
self.canvas.bind("<Button-1>", self.begin)
self.canvas.bind("<B1-Motion>", self.update)
self.canvas.bind("<ButtonRelease-1>", self.quit)

def quit(self, event):
self.hide() # Hide cross-hairs.
self.reset()


class SelectionObject:
""" Widget to display a rectangular area on given canvas defined by two points
representing its diagonal.
"""
def __init__(self, canvas, select_opts):
# Create attributes needed to display selection.
self.canvas = canvas
self.select_opts1 = select_opts
self.width = self.canvas.cget('width')
self.height = self.canvas.cget('height')

# Options for areas outside rectanglar selection.
select_opts1 = self.select_opts1.copy() # Avoid modifying passed argument.
select_opts1.update(state=tk.HIDDEN) # Hide initially.
# Separate options for area inside rectanglar selection.
select_opts2 = dict(dash=(2, 2), fill='', outline='white', state=tk.HIDDEN)

# Initial extrema of inner and outer rectangles.
imin_x, imin_y, imax_x, imax_y = 0, 0, 1, 1
omin_x, omin_y, omax_x, omax_y = 0, 0, self.width, self.height

self.rects = (
# Area *outside* selection (inner) rectangle.
self.canvas.create_rectangle(omin_x, omin_y, omax_x, imin_y, **select_opts1),
self.canvas.create_rectangle(omin_x, imin_y, imin_x, imax_y, **select_opts1),
self.canvas.create_rectangle(imax_x, imin_y, omax_x, imax_y, **select_opts1),
self.canvas.create_rectangle(omin_x, imax_y, omax_x, omax_y, **select_opts1),
# Inner rectangle.
self.canvas.create_rectangle(imin_x, imin_y, imax_x, imax_y, **select_opts2)
)

def update(self, start, end):
# Current extrema of inner and outer rectangles.
imin_x, imin_y, imax_x, imax_y = self._get_coords(start, end)
omin_x, omin_y, omax_x, omax_y = 0, 0, self.width, self.height

# Update coords of all rectangles based on these extrema.
self.canvas.coords(self.rects[0], omin_x, omin_y, omax_x, imin_y),
self.canvas.coords(self.rects[1], omin_x, imin_y, imin_x, imax_y),
self.canvas.coords(self.rects[2], imax_x, imin_y, omax_x, imax_y),
self.canvas.coords(self.rects[3], omin_x, imax_y, omax_x, omax_y),
self.canvas.coords(self.rects[4], imin_x, imin_y, imax_x, imax_y),

for rect in self.rects: # Make sure all are now visible.
self.canvas.itemconfigure(rect, state=tk.NORMAL)

def _get_coords(self, start, end):
""" Determine coords of a polygon defined by the start and
end points one of the diagonals of a rectangular area.
"""
return (min((start[0], end[0])), min((start[1], end[1])),
max((start[0], end[0])), max((start[1], end[1])))

def hide(self):
for rect in self.rects:
self.canvas.itemconfigure(rect, state=tk.HIDDEN)


class Application(tk.Frame):

# Default selection object options.
SELECT_OPTS = dict(dash=(2, 2), stipple='gray25', fill='red',
outline='')

def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)

path = "Books.jpg"
img = ImageTk.PhotoImage(Image.open(path))
self.canvas = tk.Canvas(root, width=img.width(), height=img.height(),
borderwidth=0, highlightthickness=0)
self.canvas.pack(expand=True)

self.canvas.create_image(0, 0, image=img, anchor=tk.NW)
self.canvas.img = img # Keep reference.

# Create selection object to show current selection boundaries.
self.selection_obj = SelectionObject(self.canvas, self.SELECT_OPTS)

# Callback function to update it given two points of its diagonal.
def on_drag(start, end, **kwarg): # Must accept these arguments.
self.selection_obj.update(start, end)

# Create mouse position tracker that uses the function.
self.posn_tracker = MousePositionTracker(self.canvas)
self.posn_tracker.autodraw(command=on_drag) # Enable callbacks.


if __name__ == '__main__':

WIDTH, HEIGHT = 900, 900
BACKGROUND = 'grey'
TITLE = 'Image Cropper'

root = tk.Tk()
root.title(TITLE)
root.geometry('%sx%s' % (WIDTH, HEIGHT))
root.configure(background=BACKGROUND)

app = Application(root, background=BACKGROUND)
app.pack(side=tk.TOP, fill=tk.BOTH, expand=tk.TRUE)
app.mainloop()

这里有一些图片展示了它的实际效果:

screenshot of start of selection process

screenshot of end of selection process

关于python - 用鼠标选择图像区域并记录选择的尺寸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55636313/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com