当前位置: 首页 > 科技观察

GUI布局Tkinter完美Python小项目

时间:2023-03-12 19:29:02 科技观察

本Python小项目主要功能:调用电脑摄像头拍照,利用百度API接口实现图像识别。上次完成了API的打包,这次完成了GUI的布局。具体成品如下。opencv中的imwrite方法用于拍照和保存图片。具体例子见上一篇文章。Tkinter布局逻辑中最推荐的Grid布局。实现机制是将Widget在逻辑上分表,将需要的Widget放置在指定的位置。网格布局参数说明具体main.py代码如下。"""@作者:Runsen@微信:RunsenLiu@微信公众号:Python之王@CSDN:https://blog.csdn.net/weixin_44510615@Github:https://github.com/MaoliRUNsen@日期:2020/11/29"""importtimeimportcv2ascv#pipinstallopencv-pythonimporttkinterastkfromtkinterimportttk#下拉框依赖库fromtkinterimportscrolledtext#滚动文本框依赖库fromtkinterimportN,E,S,W#引入Baidu_API类(上一篇)frombaidu_apiimportBaidu_API##Photographdeftakenotebook_aphoto():内置摄像头,所以参数为0,如果有其他摄像头,可以将参数调为1,2cap=cv.VideoCapture(0)img_path=str(int(time.time()))+'.jpg'whileTrue:#从相机读取图片成功,img=cap.read()#转换为灰度图片#gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)##显示相机cv.imshow('-----------pleaseenter"s"totakeapicture----------',img)#保持图片连续,无限等待输入k=cv.waitKey(1)ifk==27:#通过esc键退出cameracv。destroyAllWindows()breakelifk==ord("s"):#用s键保存图片并退出。cv.imwrite(img_path,img)cv.destroyAllWindows()break#关闭相机cap.release()#打印日志scr.insert(tk.END,'[{}]拍摄成功...\n'.format(time.strftime('%Y-%m-%d%H:%M:%S')))#返回图片returnimg_path#--------图形界面各组件功能设计----------#清除窗口日志defclear_the_window():scr.delete(1.0,tk.END)#退出软件defexit():win.quit()#下拉框选项选择defselect_ttk(event):globalnumberChosen#ColorvalueScoreifnumberChosen.current()==1:#获取图片img_path=take_a_photo()try:#发送图片到API获取信息score,age,gender,race=Baidu_API().face_detect(img_path=img_path)#打印日志scr.insert(tk.END,'[{}]年龄「{}」性别「{}」种族「{}」\n'.format(time.strftime('%Y-%m-%d%H:%M:%S'),age,gender,race))scr.insert(tk.END,'[{}]外观分数为:{}/100分\n'.format(time.strftime('%Y-%m-%d%H:%M:%S'),score))except:scr.insert(tk.END,'[{}]{}'.format(time.strftime(time.strftime('%Y-%m-%d%H:%M:%S')),Baidu_API().face_detect(img_path=img_path)))#gesturerecognitionifnumberChosen.current()==2:scr.insert(tk.END,'[{}]请将你的手势放在相机前...\n'.format(time.strftime('%Y-%m-%d%H:%M:%S')))time.sleep(0.1)img_path=take_a_photo()try:classname_en,classname_zh=Baidu_API().gesture(img_path=img_path)scr.insert(tk.END,'[{}]gesture:{}({})\n'.format(time.strftime('%Y-%m-%d%H:%M:%S'),classname_zh,classname_en))except:scr.insert(tk.END,'[{}]{}\n'.format(time.strftime('%Y-%m-%d%H:%M:%S'),Baidu_API().gesture(img_path=img_path)))#智能人脸抠图ifnumberChosen.current()==3:scr.insert(tk.END,'智能人脸抠图\n'.format(time.strftime('%Y-%m-%d%H:%M:%S')))img_path=take_a_photo()out_path=str(int(time.time()))+'.jpg'try:Baidu_API().body_seg(img_path=img_path,out_path=out_path)scr.insert(tk.END,'完成智能人脸抠图')except:scr.insert(tk.END,'[{}]{}\n'.format(time.strftime('%Y-%m-%d%H:%M:%S'),Baidu_API().body_seg(img_path=img_path,out_path=None)))#------------创建窗口------------win=tk.Tk()win.title('客人先关注微信公众号:Python之王!')win.geometry('600x300')#------------窗口组件设计-----------#grid中的参数:column,columnspan,in,ipadx,ipady,padx,pady,row,rowspan,sticky#drop-downboxcomponentnumber=tk.StringVarnumberChosen=ttk.Combobox(win,textvariable=number)numberChosen['value']=('pleaseselect','给我的外貌打分!','识别我的手势','智能人脸抠图')numberChosen.current(0)#设置默认值为第一个一,也就是默认下拉框中的内容numberChosen.grid(row=1,column=1,rowspan=1,sticky=N+E+S+W)#下拉框触发动作(绑定点击事件)numberChosen.bind('<>',select_ttk)#清除按钮组件tk.Button(win,cnf={'text':'clear','command':clear_the_window}).grid(row=1,column=2,ipadx=1,sticky=N+E+S+W)#退出按钮组件tk.Button(win,cnf={'text':'exit','command':exit}).grid(row=1,column=3,ipadx=1,sticky=N+E+S+W)#滚动文本框组件scr=scrolledtext.ScrolledText(win)scr.grid(row=2,column=1,columnspan=3,rowspan=1)#让窗口一直显示win.mainloop()最后可以用Pyinstaller打包Java,一次编译,到处运行。Python没有这么好的能力。Python有一个pyinstaller可以打包exe运行在window平台上。这对Python来说也是非常不利的。好的一面是,打包后的包安装占用内存大:pipinstallpyinstaller。Pyinstaller的具体参数如下。注意:有时在代码末尾加上input(),这样打开exe就不会散了。由于上面的代码本身就是窗口一直显示,所以不需要加上input()。打包的时候没有错误提示,可以成功打包成exe文件。但是运行打包后的软件会提示找不到模块。我遇到的是找不到第三方模块,比如cv2。这时候需要在打包的时候指定-p参数,后面加上python目录下的第三方库模板目录路径site-packages,就打包成功了。cd到代码所在目录,执行pyinstallermain.py-F-pF:\anaconda\Lib\site-packages如果Pyinstaller打包报错numpy.core.multiarrayfailedtoimport,这是numpy和opencv不兼容,这可以减少numpy版本。