前一篇记录了一些常用tkinter控件及其使用方式,今天再次使用tkinter创建一个简易相机
1.拍照
2.录像
所需工具:
pycharm 2020.3.3
python 3.9
os
tkinter
PIL
cv2
threading
tkinter.messagebox
1.创建一个界面
2.添加一个Lable用来显示摄像头的画面
3.分别添加拍照,开始录像,结束录像按钮
4.设置视频或照片的格式
5.打开摄像头,经过处理画面显示到Lable上
6.完善拍照,录像功能
7.整体优化(方法有很多,例如使用类来优化)
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)#不加第二个参数,会出现错误,只要你不在意,可忽略
#每一帧的宽和高
cap.set(3, 640)
cap.set(4, 480)
处理画面并且显示到Lable上,必须是灰度化之后的照片,通过fromarray(实现array到image的转换)转化,因为tkinter只能显示.gif的图片,所以要经过PhotoImage的处理才可,最后一句vidLabel.image = frame3不可少
while True:
ret, frame = cap.read()
frame1 = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame2 = Image.fromarray(frame1)
frame3 = ImageTk.PhotoImage(frame2)
vidLabel.configure(image=frame3)
vidLabel.image = frame3
视频格式,VideoWriter的参数依次为:名称、编解码方式、帧率、画面大小
# # 指定视频编解码方式为MJPG 需要解码器
codec = cv2.VideoWriter_fourcc(*'MJPG')
fps = 5 # 指定写入帧率为5
frameSize = (640, 480) # 指定窗口大小
# # 创建 VideoWriter对象
output = cv2.VideoWriter('Video.avi', codec, fps, frameSize)
最后一个重点:是标志量的设定,这个在学习单片机的时候经常使用,所以就通过设置标志量的方式来实现相对应的功能
import os
import tkinter
from PIL import Image, ImageTk
import cv2
import threading
from tkinter.messagebox import showerror
root = tkinter.Tk()
root.geometry('645x550')
# # 指定视频编解码方式为MJPG 需要解码器
codec = cv2.VideoWriter_fourcc(*'MJPG')
fps = 5 # 指定写入帧率为5
frameSize = (640, 480) # 指定窗口大小
# # 创建 VideoWriter对象
output = cv2.VideoWriter('Video.avi', codec, fps, frameSize)
def kill(pid):
# 本函数用于中止传入pid所对应的进程
if os.name == 'nt':
# Windows系统
cmd = 'taskkill /pid ' + str(pid) + ' /f'
try:
os.system(cmd)
print(pid, 'killed')
except Exception as e:
print(e)
elif os.name == 'posix':
# Linux系统
cmd = 'kill ' + str(pid)
try:
os.system(cmd)
print(pid, 'killed')
except Exception as e:
print(e)
else:
print('Undefined os.name')
def videoLoop():
global cap
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
cap.set(3, 640)
cap.set(4, 480)
global root
global flag
flag=False
def paizhao():
global flag
flag=True
print(flag)
but = tkinter.Button(root,
text="拍照",
command=paizhao)
but.grid(row=1,column=1)
global flag_video
flag_video=False
def luxiang():
global flag_video
flag_video=True
def lu():
global flag_video
output.release()
flag_video = False
B1 = tkinter.Button(root,
text='结束录像',
command=lu)
B1.grid(row=2, column=2)
but1 = tkinter.Button(root,
text='开始录像',
command=luxiang)
but1.grid(row=1,column=2)
def ex():
output.release()
cap.release()
pP = os.getpid()
kill(pid=pP)
but2 = tkinter.Button(root,
text='退出',
command=ex)
but2.grid(row=1,column=3)
vidLabel = tkinter.Label(root,
width=640,
height=400,
)
vidLabel.place(x=0,y=100)
while True:
ret, frame = cap.read()
frame1 = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame2 = Image.fromarray(frame1)
frame3 = ImageTk.PhotoImage(frame2)
vidLabel.configure(image=frame3)
vidLabel.image = frame3
if flag and not flag_video:
cv2.imwrite('paizhao'+'.jpg',frame)
flag=False
if flag_video and not flag:
output.write(frame)
def closeWindow():
tkinter.messagebox.showinfo(title='关闭错误', message='请点击退出按钮!') # 错误消息框
return
root.protocol('WM_DELETE_WINDOW', closeWindow)#如果关闭窗口的话,执行closeWindow函数
videoThread = threading.Thread(target=videoLoop, args=())
videoThread.start()
root.mainloop()
重点关注核心代码和整体框架,另外一点就是逻辑,以上代码使用了很少的算法。
到此一个简易版的相机(可录象、可拍照)就完成了
缺点:
只能排一张,实现排多张或连续拍的话,首先需要解决命名方式的问题,可通过设置一个变量,例如拍照的时间、设置一个变量n每排一张就n就增加1,命名方式很灵活,连拍的话,只需要再增加一个表质量或者别的更好的方法
拍摄视频,增加命名方式的多样性,显示保存路径,可选择保存路径,改变帧率,分辨率等等,都可以实现的
到此就结束了,感谢阅读,给大佬敬礼
2021.05.21 20:36