我正在努力扩展以前给我的解决方案。
用户可以在TkInter Canvas小部件上使用鼠标随机绘制,之后,在OpenCV窗口上绘制具有相同像素坐标的相同曲线。
我想修改这个解决方案,使TkInter画布和OpenCV窗口必须在同一时间显示:每次suer完成在TkInter上绘制一条曲线时,它立即在OpenCV窗口上重新绘制。
有办法实现这个目标吗?
提前感谢您的帮助
这比稍后在OpenCV中绘制所有线条更容易。
我让MaClasse
类只制作一个空白的图像,在初始化时打开一个窗口显示它,并给它一个方法来绘制单线并再次显示图像。然后你可以在Test
中创建一个MaClasse
对象,每次在Tkinter中画一条线时,在OpenCV中画一条线。然后你甚至不需要保存你画的所有线(你可以完全删除self.liste
)。
from Tkinter import *
import numpy as np
import cv2
class Test:
def __init__(self):
self.b1="up"
self.xold=None
self.yold=None
self.liste=[]
self.maclasse = MaClasse()
def test(self,obj):
self.drawingArea=Canvas(obj)
self.drawingArea.pack()
self.drawingArea.bind("<Motion>",self.motion)
self.drawingArea.bind("<ButtonPress-1>",self.b1down)
self.drawingArea.bind("<ButtonRelease-1>",self.b1up)
def b1down(self,event):
self.b1="down"
def b1up(self,event):
self.b1="up"
self.xold=None
self.yold=None
self.liste.append((self.xold,self.yold))
def motion(self,event):
if self.b1=="down":
if self.xold is not None and self.yold is not None:
event.widget.create_line(self.xold,self.yold,event.x,event.y,fill="red",width=3,smooth=TRUE)
self.maclasse.dessiner_ligne(self.xold,self.yold,event.x,event.y)
self.xold=event.x
self.yold=event.y
self.liste.append((self.xold,self.yold))
class MaClasse:
def __init__(self):
self.s=600,600,3
self.ma=np.zeros(self.s,dtype=np.uint8)
cv2.namedWindow("OpenCV",cv2.WINDOW_AUTOSIZE)
cv2.imshow("OpenCV",self.ma)
def dessiner_ligne(self, xold, yold, x, y):
cv2.line(self.ma,(xold, yold),(x,y),[255,255,255],2)
cv2.imshow("OpenCV",self.ma)
if __name__=="__main__":
root = Tk()
root.wm_title("Test")
v = Test()
v.test(root)
root.mainloop()
由于上面使用Tkinter窗口和OpenCV窗口的代码对你不起作用,你也可以在Tkinter顶层窗口中显示OpenCV图像。
from Tkinter import *
import numpy as np
import cv2
import Image, ImageTk
class Test:
def __init__(self, parent):
self.parent = parent
self.b1="up"
self.xold=None
self.yold=None
self.liste=[]
self.maclasse = MaClasse(self.parent)
def test(self):
self.drawingArea=Canvas(self.parent)
self.drawingArea.pack()
self.drawingArea.bind("<Motion>",self.motion)
self.drawingArea.bind("<ButtonPress-1>",self.b1down)
self.drawingArea.bind("<ButtonRelease-1>",self.b1up)
def b1down(self,event):
self.b1="down"
def b1up(self,event):
self.b1="up"
self.xold=None
self.yold=None
self.liste.append((self.xold,self.yold))
def motion(self,event):
if self.b1=="down":
if self.xold is not None and self.yold is not None:
event.widget.create_line(self.xold,self.yold,event.x,event.y,fill="red",width=3,smooth=TRUE)
self.maclasse.dessiner_ligne(self.xold,self.yold,event.x,event.y)
self.xold=event.x
self.yold=event.y
self.liste.append((self.xold,self.yold))
class MaClasse:
def __init__(self, parent):
self.s=600,600,3
self.ma=np.zeros(self.s,dtype=np.uint8)
self.top = Toplevel(parent)
self.top.wm_title("OpenCV Image")
self.label = Label(self.top)
self.label.pack()
self.show_image()
def dessiner_ligne(self, xold, yold, x, y):
cv2.line(self.ma,(xold, yold),(x,y),[255,255,255],2)
self.show_image()
def show_image(self):
self.im = Image.fromarray(self.ma)
self.imgtk = ImageTk.PhotoImage(image=self.im)
self.label.config(image=self.imgtk)
if __name__=="__main__":
root = Tk()
root.wm_title("Test")
v = Test(root)
v.test()
root.mainloop()