基于tkinter的简单相机

文章目录

  • 前言
  • 功能
  • 模块
  • 思路
  • 核心代码
  • 完整代码
  • 总结:


前言

前一篇记录了一些常用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,命名方式很灵活,连拍的话,只需要再增加一个表质量或者别的更好的方法
拍摄视频,增加命名方式的多样性,显示保存路径,可选择保存路径,改变帧率,分辨率等等,都可以实现的
到此就结束了,感谢阅读,给大佬敬礼
基于tkinter的简单相机_第1张图片
2021.05.21 20:36

你可能感兴趣的:(python,tkinter,tkinter,python)