[英]Using a tkinter Canvas to display an image then drawing on the image using cv2.circle/cv2.line
我对 Python 比较陌生,我正在尝试使用 tkinter 构建一个 GUI,利用tkinter
的cv2
。
我希望引入一个图像( tk.Canvas
当前用于显示),使用tk.Entry
框从用户创建组件列表,从用户输入创建单选按钮,然后使用鼠标单击在图像上绘制圆圈,每个组件都有不同的颜色。
到目前为止,我已经成功创建了tkinter
window,除了在图像上绘制之外,它还可以完成上述所有操作。 我最初创建了一个单独的代码,用于将cv2.circles
绘制到可以正常工作的 JPEG 上,我只是不知道如何将 tkinter GUI 链接到cv2
库。
任何帮助将不胜感激,因为我找不到任何问同样问题的东西。 我附上了下面的部分代码......
最好的,乔治
function 用于选择文件路径、导入图像并在 canvas 上显示:
def selecting_file(self):
self.file_path = filedialog.askopenfilename()
self.cv_img = cv2.cvtColor(cv2.imread(self.file_path), cv2.COLOR_BGR2RGB)
self.height, self.width, self.no_channels = self.cv_img.shape
self.canvas = tk.Canvas(self.window, width=self.width, height=self.height)
self.canvas.pack()
self.photo = PIL.ImageTk.PhotoImage(image=PIL.Image.fromarray(self.cv_img))
self.canvas.create_image(0, 0, image=self.photo, anchor=tk.NW)
self.label = tk.Label(image=self.photo)
self.label.image = self.photo
创建单选按钮然后从中获取值的函数:
def compile_radio(self):
self.v = tk.StringVar()
for i in App.part_list:
self.radio = tk.Radiobutton(self.window, text=i, variable=self.v, value=App.part_list.index(i)+1, command=self.radio_select)
self.radio.pack()
val = 0
def radio_select(self):
self.radio_value = self.v.get()
self.radio_value = App.val
function 和不在此脚本中的代码允许将圆圈绘制到 cv2.imshow 上:
def draw_circle1(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
cv2.circle(img, center = (x, y), radius = 5, color = (0,0,255), thickness = 2)
global red_count
red_count += 1
img = cv2.imread('IMAGE.jpg')
cv2.namedWindow(winname = 'Drawing')
cv2.setMouseCallback('Drawing', draw_circle1)
while True:
cv2.imshow('Drawing',img)
if cv2.waitKey(10) & 0xFF == 27:
break
cv2.destroyAllWindows()
无需使用cv2
来绘制它。 您可以为此使用tkinter
和PIL
。
首先,您必须将图像加载为普通 PIL image
self.image = Image.open(self.file_path)
self.width, self.height = self.image.size
接下来,您必须创建用于在 canvas 上显示的photo
并draw
并保存。
self.photo = ImageTk.PhotoImage(image=self.image)
self.draw = ImageDraw.Draw(self.image)
您可以使用tkinter
到 select 放置在显示的图像上
self.canvas.bind('<Button-1>', self.draw_circle)
并运行 function 将在 canvas 上draw
圆圈并在可以保存的绘制上。
# display on canvas
self.canvas.create_oval((event.x-5, event.y-5, event.x+5, event.y+5), width=2, outline='#FF0000')
# draw on self.image
self.draw.ellipse((event.x-5, event.y-5, event.x+5, event.y+5), width=2, outline=(255,0,0))
稍后您可以保存它
self.image.save('output.jpg')
顺便说一句:如果您使用Canvas
来显示图像,那么您不需要使用Label
。
最少的工作代码。
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk, Image, ImageDraw
class App():
def __init__(self):
self.window = tk.Tk()
self.window.after(100, self.selecting_file)
self.window.mainloop()
def selecting_file(self):
self.file_path = filedialog.askopenfilename()
#self.file_path = filedialog.askopenfilename(initialdir='images/', initialfile='example.jpg')
self.image = Image.open(self.file_path)
self.width, self.height = self.image.size
self.draw = ImageDraw.Draw(self.image)
self.photo = ImageTk.PhotoImage(image=self.image)
self.canvas = tk.Canvas(self.window, width=self.width, height=self.height)
self.canvas.pack()
self.canvas.bind('<Button-1>', self.draw_circle)
self.canvas.create_image(0, 0, image=self.photo, anchor=tk.NW)
self.save_button = tk.Button(self.window, text='Save', command=self.save)
self.save_button.pack()
def draw_circle(self, event):
# display on canvas
self.canvas.create_oval((event.x-5, event.y-5, event.x+5, event.y+5), width=2, outline='#FF0000')
# draw on self.image
self.draw.ellipse((event.x-5, event.y-5, event.x+5, event.y+5), width=2, outline=(255,0,0))
def save(self):
self.image.save('output.jpg')
# --- main ---
App()
编辑:
带有可更改颜色、图形和半径的按钮的版本。
import tkinter as tk
from tkinter import filedialog, colorchooser
from PIL import ImageTk, Image, ImageDraw
class App():
def __init__(self):
self.color = '#FF0000'
self.figure = 'circle'
self.figure = 'rectangle'
self.size = 5
self.window = tk.Tk()
self.window.after(100, self.selecting_file)
self.window.mainloop()
def selecting_file(self):
self.file_path = filedialog.askopenfilename()
#self.file_path = filedialog.askopenfilename(initialdir='images/', initialfile='example.jpg')
self.image = Image.open(self.file_path)
self.width, self.height = self.image.size
self.draw = ImageDraw.Draw(self.image)
self.photo = ImageTk.PhotoImage(image=self.image)
self.frame_tools = tk.Frame(self.window)
self.frame_tools.pack()
self.rectangle_button = tk.Button(self.frame_tools, text='Rectangle', command=lambda:self.change_figure('rectangle'))
self.rectangle_button.pack(side='left')
self.circle_button = tk.Button(self.frame_tools, text='Circle', command=lambda:self.change_figure('circle'))
self.circle_button.pack(side='left')
self.size_entry = tk.Entry(self.frame_tools)
self.size_entry.bind('<Return>', self.change_size)
self.size_entry.pack(side='left')
self.color_button = tk.Button(self.frame_tools, text='Color: #FF0000', command=self.change_color)
self.color_button.pack(side='left')
self.canvas = tk.Canvas(self.window, width=self.width, height=self.height)
self.canvas.pack()
self.canvas.bind('<Button-1>', self.on_click)
self.canvas.create_image(0, 0, image=self.photo, anchor=tk.NW)
self.save_button = tk.Button(self.window, text='Save', command=self.save)
self.save_button.pack()
def on_click(self, event):
if self.figure == 'circle':
self.draw_circle(event)
elif self.figure == 'rectangle':
self.draw_rectangle(event)
def draw_circle(self, event):
x1 = event.x - self.size
y1 = event.y - self.size
x2 = event.x + self.size
y2 = event.y + self.size
# display on canvas
self.canvas.create_oval((x1, y1, x2, y2), width=2, outline=self.color)
# draw on self.image
self.draw.ellipse((x1, y1, x2, y2), width=2, outline=self.color)
def draw_rectangle(self, event):
x1 = event.x - self.size
y1 = event.y - self.size
x2 = event.x + self.size
y2 = event.y + self.size
# display on canvas
self.canvas.create_rectangle((x1, y1, x2, y2), width=2, outline=self.color)
# draw on self.image
self.draw.rectangle((x1, y1, x2, y2), width=2, outline=self.color)
def save(self):
self.image.save('output.jpg')
def change_color(self):
rgb, color_string = colorchooser.askcolor(initialcolor=self.color)
#print(rgb, color_string)
if color_string:
self.color = color_string
self.color_button['text'] = 'Color: ' + color_string
def change_figure(self, figure):
self.figure = figure
def change_size(self, event=None):
try:
self.size = int(self.size_entry.get())
except Exceptions as ex:
print(ex)
# --- main ---
App()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.