这两天看opencv-python的HSV色彩空间,在写程序时发现用HSV来提取图像区域是件令人恶心的麻烦事。拿阈值分割做个对比,阈值最多也就一两个参数需要调整;但是HSV需要对三个通道调整上下限,也就是起码有6个参数。于是乎,就一时兴起决定做个小程序,把参数都做成滑动块,这样自然方便许多。一开始,想直接用opencv来做,但是百度了一下它没有很好的GUI支持。所以决定还是用python自带的tkinter来设计UI。
UI设计最重要的还是布局,之前学CSS就差点搞得我稀里糊涂。tkinter有三种布局方式,网上说grid是常用的,然而我用了一会,感觉这种excel类型的方法有点死板,唯一的好处是不用计算坐标,所以我布局滑块时就使用了grid,其他一律使用place。
我要的程序界面得划出两块地方显示图片,tkinter没有专用的控件,不过可以利用Lable的image属性来设置背景图片。并且,image属性对图片数据流的格式有所要求,得用PIL模块里的Image和ImageTk两个工具先对图片进行处理。在处理时,我还得对它大小限制一下,要不然不同图片导进来,布局就乱了。接下来就导入滑块和按钮,调一下布局罢了,没啥难度,就是审美得纠结一下。所有控件都导入以后,为了看起来不那么单调,本来想是给整个窗口加一个高雅的背景图的,但是当我把背景改成暗灰色以后,奇迹就发生了——这东西居然还有border。暗灰色背景,配上亮白色边框,别有一番味道啊!!
最后,在给按钮和字调下颜色,然后把窗口的默认ico图标换一下,这还是跟之前的图片导入类似,所以很快就解决了。剩下的事情就是事件控制了,因为按钮挺多的,功能也越想越复杂,因此,这部分代码就留给以后写,文末贴个程序界面截图和实现代码。

1 import os
2 from tkinter import *
3 from PIL import Image, ImageTk
4
5 os.chdir('D:/programe/matlab/img')
6
7
8
9
10 class GUI():
11 def __init__(self,window):
12 self.window = window
13 #title
14 self.window.title("HsvMaster")
15 #siz=800*600,position=(500,200)
16 self.window.geometry('1000x600+500+200')
17 self.window["bg"] = "DimGray"
18 # icon
19 self.icon = ImageTk.PhotoImage(file='hsv_icon.ico')
20 self.window.call('wm','iconphoto',self.window._w,self.icon)
21
22
23 def create_widgets(self):
24
25 #scale
26 self.hmin_label = Label(self.window,text='色调下限',fg='WhiteSmoke',bg="DimGray")
27 self.hmin_scale = Scale(self.window,orient=HORIZONTAL,from_=0,to=255,resolution=1,tickinterval=50,length=200,width=7,fg='WhiteSmoke',bg="DimGray")
28 self.hmax_label = Label(self.window,text='色调上限',fg='WhiteSmoke',bg="DimGray")
29 self.hmax_scale = Scale(self.window,orient=HORIZONTAL,from_=0,to=255,resolution=1,tickinterval=50,length=200,width=7,fg='WhiteSmoke',bg="DimGray")
30 self.smin_label = Label(self.window,text='饱和度下限',fg='WhiteSmoke',bg="DimGray")
31 self.smin_scale = Scale(self.window,orient=HORIZONTAL,from_=0,to=255,resolution=1,tickinterval=50,length=200,width=7,fg='WhiteSmoke',bg="DimGray")
32 self.smax_label = Label(self.window,text='饱和度上限',fg='WhiteSmoke',bg="DimGray")
33 self.smax_scale = Scale(self.window,orient=HORIZONTAL,from_=0,to=255,resolution=1,tickinterval=50,length=200,width=7,fg='WhiteSmoke',bg="DimGray")
34 self.vmin_label = Label(self.window,text='明度下限',fg='WhiteSmoke',bg="DimGray")
35 self.vmin_scale = Scale(self.window,orient=HORIZONTAL,from_=0,to=255,resolution=1,tickinterval=50,length=200,width=7,fg='WhiteSmoke',bg="DimGray")
36 self.vmax_label = Label(self.window,text='明度上限',fg='WhiteSmoke',bg="DimGray")
37 self.vmax_scale = Scale(self.window,orient=HORIZONTAL,from_=0,to=255,resolution=1,tickinterval=50,length=200,width=7,fg='WhiteSmoke',bg="DimGray")
38
39 # scale position
40 self.hmin_label.grid(row=0, column=0,padx=15)
41 self.hmin_scale.grid(row=0,column=1,pady=2)
42 self.hmax_label.grid(row=1, column=0)
43 self.hmax_scale.grid(row=1,column=1,pady=2)
44 self.smin_label.grid(row=2, column=0)
45 self.smin_scale.grid(row=2,column=1,pady=2)
46 self.smax_label.grid(row=3, column=0)
47 self.smax_scale.grid(row=3,column=1,pady=2)
48 self.vmin_label.grid(row=4, column=0)
49 self.vmin_scale.grid(row=4,column=1,pady=2)
50 self.vmax_label.grid(row=5, column=0)
51 self.vmax_scale.grid(row=5,column=1,pady=2)
52
53 #img
54 self.img = Image.open('man.jpg')
55 self.img = self.img.resize((300, 300))
56 self.img = ImageTk.PhotoImage(self.img)
57
58 self.orign = Label(self.window,image=self.img,width=300,height=300)
59 self.work = Label(self.window,image=self.img,width=300,height=300)
60 #img position
61 self.orign.place(x=320, y=30)
62 self.work.place(x=650,y=30)
63
64 #Button
65 self.import_button = Button(self.window, text='导入原图',font=('隶书',45), height=2, width=9,fg='WhiteSmoke',bg="BurlyWood")
66 self.clear_button = Button(self.window, text='删除所有',font=('隶书',12), height=2, width=15,fg='WhiteSmoke',bg="BurlyWood")
67 self.delete_button = Button(self.window, text='删除当前',font=('隶书',12), height=2, width=15,fg='WhiteSmoke',bg="BurlyWood")
68 self.switch_button = Button(self.window,text='区域切换',font=('隶书',12), height=2, width=15,fg='WhiteSmoke',bg="BurlyWood")
69 self.save_button = Button(self.window, text='区域暂存',font=('隶书',12), height=2, width=15,fg='WhiteSmoke',bg="BurlyWood")
70 self.merge_button = Button(self.window, text='合并区域',font=('隶书',12), height=2, width=15,fg='WhiteSmoke',bg="BurlyWood")
71 self.picture_button = Button(self.window, text='生成图片',font=('隶书',12), height=2, width=15,fg='WhiteSmoke',bg="BurlyWood")
72
73 #button position
74 self.import_button.place(x=18,y=400)
75 self.clear_button.place(x=370,y=420)
76 self.delete_button.place(x=570,y=420)
77 self.switch_button.place(x=770,y=420)
78 self.save_button.place(x=370,y=500)
79 self.merge_button.place(x=570,y=500)
80 self.picture_button.place(x=770,y=500)
81
82
83
84
85 def gui_start():
86
87 my_window = Tk()
88 my_gui = GUI(my_window)
89 my_gui.create_widgets()
90 my_window.mainloop()
91
92
93 gui_start()
来源:https://www.cnblogs.com/kensporger/p/12209856.html