借助tkinter设计人脸检测的界面(摄像头检测,视频检测,视频检测并保存)

结构:
借助tkinter设计人脸检测的界面(摄像头检测,视频检测,视频检测并保存)_第1张图片
注:hometown是背景图
界面:
借助tkinter设计人脸检测的界面(摄像头检测,视频检测,视频检测并保存)_第2张图片

Save_Generate_Video模块:(用来检测视频并将检测之后的视频保存):

import cv2
import dlib
import tkinter
import numpy as np
from tqdm import tqdm
from PIL import Image,ImageTk
detector=dlib.get_frontal_face_detector()

#设置显示的图像大小
img_width=500
img_height=400
def TKImages(frame):
    #摄像头翻转
    # frame=cv2.flip(frame,1)
    image=cv2.cvtColor(frame,cv2.COLOR_BGR2RGBA)
    image=image.astype(np.uint8)
    PILimage=Image.fromarray(image)
    PILimage=PILimage.resize((img_width,img_height),Image.ANTIALIAS)
    try:
        tkImage=ImageTk.PhotoImage(image=PILimage)
    except:
        return 0
    return tkImage

def Canvas_(root):
    # 创建画布
    canvas = tkinter.Canvas(root, bg='white', width=img_width, height=img_height)
    canvas.place(x=150, y=50)
    # 创建标签
    label = tkinter.Label(root, text='人脸检测', font=('黑体', 14), width=15, height=1)
    # `anchor=nw`则是把图片的左上角作为锚定点
    label.place(x=300, y=20, anchor='nw')
    return canvas
# 将视频检测的视频保存起来
image_path='hometown.jpg'
tkimage=''
def generate_video(input_path):
	global tkimage
    #获取视频名称
    filehead = input_path.split('/')[-1]
    #保存的位置
    output_path = 'Output_Video/'+'out_'+filehead

    print('视频开始处理')

    # 获取视频总帧数
    cap = cv2.VideoCapture(input_path)
    frame_count = 0
    while cap.isOpened():
        success, frame = cap.read()
        frame_count += 1
        if not success:
            break
    cap.release()
    # fps=cap.get(cv2.CAP_PROP_FPS)
    # frame_count=cap.get(cv2.CAP_PROP_FRAME_COUNT)
    print('视频总的帧数: {}'.format(frame_count))

    cap = cv2.VideoCapture(input_path)
    #获取帧的高度和宽度
    frame_size = (cap.get(cv2.CAP_PROP_FRAME_WIDTH), cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

    #获取保存的视频格式
    fource = cv2.VideoWriter_fourcc(*'mp4v')
    #获取视频帧
    fps = cap.get(cv2.CAP_PROP_FPS)

    #视频的保存
    out = cv2.VideoWriter(output_path, fource, fps, (int(frame_size[0]), int(frame_size[1])))
    margin = 0.2
    # 设置显示的字体
    font = cv2.FONT_HERSHEY_SIMPLEX
    try:
        #进度条功能
        with tqdm(total=frame_count) as pbar:
            for i in range(frame_count):
                success, frame = cap.read()
                try:
                    #获取帧的高宽
                    img_h, img_w, _ = np.shape(frame)
                    detected = detector(frame)
                    #如果检测的帧中有人脸则进行画框和检测
                    if len(detected) > 0:
                        for i, locate in enumerate(detected):
                            x1, y1, x2, y2, w, h = locate.left(), locate.top(), locate.right() + 1, locate.bottom() + 1, locate.width(), locate.height()

                            xw1 = max(int(x1 - margin * w), 0)
                            yw1 = max(int(y1 - margin * h), 0)
                            xw2 = min(int(x2 + margin * w), img_w - 1)
                            yw2 = min(int(y2 + margin * h), img_h - 1)

                            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)

                            cv2.putText(frame, 'person', (x1, y1 - 10), font, 1.2, (0, 255, 0), 3)
                    pic=TKImages(frame)
                    canvas.create_image(0,0,anchor='nw',image=pic)
                    root.updata()
                    root.after(1)
                except Exception as e:
                    #                     print('error',e)
                    pass
                if success == True:
                    out.write(frame)
                    pbar.update(1)
    except:
        print('中途中断')
        pass
    img=cv2.imread(image_path)
    tkimage=TKImages(img)
    canvas.create_image(0,0,anchor='nw',image=tkimage)
    cv2.destroyAllWindows()
    out.release()
    cap.release()
    print('视频已保存至{}'.format(output_path))



主程序:

import os
import cv2
import dlib
import tkinter
import threading
import numpy as np
import Save_Generate_Video
from PIL import Image,ImageTk
from tkinter import filedialog
from tkinter import messagebox
from tensorflow.keras.preprocessing.image import img_to_array

detector=dlib.get_frontal_face_detector()
root=tkinter.Tk()
#设置窗体的高宽
# root.geometry('200x200')
root['height']=600
root['width']=800
#设置显示的图像大小
img_width=500
img_height=400
#设置窗体的标题
root.title('Detect')
#设置标题为图像形式,第一个参数设置为True,表示该图标适用于所有的窗口
#这里注意图像格式为.png,就算是从.jpg到.png的格式转换也不能,只能是.png格式
root.iconphoto(True,tkinter.PhotoImage(file='title.png'))

def TKImages(frame):
    #摄像头翻转
    # frame=cv2.flip(frame,1)
    image=cv2.cvtColor(frame,cv2.COLOR_BGR2RGBA)
    image=image.astype(np.uint8)
    PILimage=Image.fromarray(image)
    PILimage=PILimage.resize((img_width,img_height),Image.ANTIALIAS)
    try:
        tkImage=ImageTk.PhotoImage(image=PILimage)
    except:
        return 0
    return tkImage
def Canvas_():
    # 创建画布
    canvas = tkinter.Canvas(root, bg='white', width=img_width, height=img_height)
    canvas.place(x=150, y=50)
    # 创建标签
    label = tkinter.Label(root, text='人脸检测', font=('黑体', 14), width=15, height=1)
    # `anchor=nw`则是把图片的左上角作为锚定点
    label.place(x=300, y=20, anchor='nw')
    return canvas

#关闭主界面时弹出的确认窗口
def closeEvent(root):
    # root.withdraw()  # 仅显示对话框,隐藏主窗口
    btn_close=tkinter.Button(root,text='退出检测',font=('黑体', 14), height=1, width=30,command=root.destroy)
    btn_close.place(x=260,y=560)


image_path = 'hometown.jpg'
#这里需要将tkImage设置为全局变量,不然显示不图片
tkImage=''
def set_BackGround(image_path):
    global tkImage
    image_path = 'hometown.jpg'
    canvas = Canvas_()
    img = cv2.imread(image_path)
    tkImage = TKImages(img)
    canvas.create_image(0, 0, anchor='nw', image=tkImage)

#初始化整个界面
def Init(root,image_path):
    set_BackGround(image_path)
    btn_2 = tkinter.Button(root, text='打开摄像头检测', font=('黑体', 14), height=1, width=30,
                           command=lambda: Detect_Real_Time(0, root))
    btn_2.place(x=260, y=455)
    bnt_File = tkinter.Button(root, text='打开视频进行检测', font=('黑体', 14), width=30,
                              height=1, command=lambda :Select_File_Detect(root))
    bnt_File.place(x=260, y=490)
    bnt_Save = tkinter.Button(root, text='视频进行检测并保存', font=('黑体', 14), width=30, height=1,
                              command=lambda: Select_File_Detect_Save(root))
    bnt_Save.place(x=260, y=525)

 #关闭检测函数
def Close_Video(cap,root,image_path):
    cap.release()
    cv2.destroyAllWindows()
    Init(root,image_path)

def Detect_Real_Time(parameter,root):
    ##第二个参数表示捕获的图像分辨率
    # cap=cv2.VideoCapture(parameter,cv2.CAP_DSHOW)
    cap=cv2.VideoCapture(parameter)

    #这句是关闭摄像头
    btn = tkinter.Button(root, text='停止检测', font=('黑体',14),width=15,height=1,command=lambda :Close_Video(cap,root,image_path))
    btn.place(x=350, y=455)
    canvas=Canvas_()

    margin = 0.2
    frame_count = 0
    face_count = 0
    # 设置显示的字体
    font = cv2.FONT_HERSHEY_SIMPLEX
    while True:
        OK,frame=cap.read()
        if OK==False and parameter==0:
            print('请面对摄像头')
            break
        elif OK==False and parameter!=0:
            print('结束视频检测')
            Init(root,image_path)
            break
        img_h, img_w, _ = np.shape(frame)
        detected = detector(frame)
        #如果检测的帧中有人脸则进行画框和检测
        if len(detected) > 0:
            for i, locate in enumerate(detected):
                face_count += 1
                x1, y1, x2, y2, w, h = locate.left(), locate.top(), locate.right() + 1, locate.bottom() + 1, locate.width(), locate.height()

                xw1 = max(int(x1 - margin * w), 0)
                yw1 = max(int(y1 - margin * h), 0)
                xw2 = min(int(x2 + margin * w), img_w - 1)
                yw2 = min(int(y2 + margin * h), img_h - 1)

                cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)

                cv2.putText(frame, 'person', (x1, y1 - 10), font, 1.2, (0, 255, 0), 3)
        pic=TKImages(frame)
        canvas.create_image(0,0,anchor='nw',image=pic)
        root.update()
        root.after(1)
    cap.release()
    cv2.destroyAllWindows()

def Select_File_Detect(root):
    #选择open文件进行识别
    filename=filedialog.askopenfilename(title='选择文件进行识别')
    if filename:
        print('进行视频人脸检测')
        Detect_Real_Time(filename,root)

#将检测的视频进行保存
def Select_File_Detect_Save(root):
    #选择open文件进行识别
    filename=filedialog.askopenfilename(title='选择文件进行识别')
    if filename:
        print('进行视频人脸检测')
        #放在线程中不会出现卡顿,并且速度更快
        #这个地方注意args中的参数如果只有一个的话,后面需要加一个','
        thread_generate=threading.Thread(target=Save_Generate_Video.generate_video,args=(filename,root))
        thread_generate.start()

if __name__=='__main__':
    # Detect_Real_Time(0)
    # Detect_Video(root)
    Init(root,image_path)
    closeEvent(root)
    root.mainloop()



关于这个程序要说明的地方和函数功能已经在程序中说明,如果读者还有什么不懂之处,请留言。

你可能感兴趣的:(python,计算机视觉,opencv,python,人工智能)