基于OpenCV-python的人脸识别系统

import sys
import os
import tkinter as tk
from tkinter.ttk import Style
import numpy as np
import cv2
from PIL import ImageTk, ImageDraw, ImageFont
from panel.models.tabulator import theme

from Model import *
from tkinter import ttk, filedialog, simpledialog, messagebox
import pickle



face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
# 准备好识别方法LBPH方法
recognizer = cv2.face.LBPHFaceRecognizer_create()

file_path = 'face_list.pkl'
dict_path = 'name_dict.pkl'

if os.path.exists(file_path) and os.path.exists(dict_path):
    with open(file_path, 'rb') as f:
        face_package = pickle.load(f)
    face_label = [i for i in range(len(face_package))]
    with open(dict_path, 'rb') as f:
        face_name = pickle.load(f)
    recognizer.train(face_package,np.array(face_label))
else:
    face_package = []
    face_label = []
    face_name = dict()




#设置字体
font = ImageFont.truetype('./msyhbd.ttc',30)

def choice_get_face_way():
    is_capture = False
    #隐藏主窗口
    root.withdraw()
    '''创建一个顶级窗口'''
    root2 = tk.Toplevel(root)
    root2.geometry("1000x600")
    root2.title("choose get face way")
    def close_new_window():
        root2.destroy()
        root.deiconify()  # 恢复显示原窗口

    cap = cv2.VideoCapture(0)
    def capture_photo():
        # 从摄像头读取一帧
        ret, frame = cap.read()
        if ret:
            gray_img = cv2.cvtColor(frame, code=cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray_img)
            if len(faces) > 0:
                input_value = simpledialog.askstring("输入", "请输入录入人脸的名字:")
                if input_value:
                    for x, y, w, h in faces:
                        face_label.append(len(face_package))
                        face_package.append(gray_img[y:y+h,x:x+w])
                    #训练人脸
                    recognizer.train(face_package,np.array(face_label))

                    face_name[str(len(face_label))] = input_value
                    print(face_name)
                    print(face_label)
            else:
                messagebox.showinfo("提示", "没有检测到人脸,请重新输入")
        else:
            print("无法读取摄像头数据")

    # 定义更新图像的函数
    def update_frame():
        # 从摄像头读取一帧
        ret, frame = cap.read()
        if ret:
            # 将BGR图像转换为RGB格式
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            gray_img = cv2.cvtColor(frame,code=cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray_img)
            for x, y, w, h in faces:
                cv2.rectangle(frame, (x, y), (x + w, y + h), [0, 0, 255], 3)
            # 将图像转换为PIL格式
            image = Image.fromarray(frame)
            # 将PIL图像转换为PhotoImage格式
            photo = ImageTk.PhotoImage(image)
            # 更新标签上的图像
            label.config(image=photo)
            label.image = photo
            label.place(x=50, y=50)
        # 每隔50毫秒更新一次
        root2.after(50, update_frame)

    label2 = tk.Label(root2)
    label2.pack()

    # 打开文件选择对话框并加载图片
    def open_image():
        # 打开文件选择对话框,过滤仅显示图片文件
        file_path = filedialog.askopenfilename(
            title="选择图片",
            filetypes=[("Image Files", "*.jpg;*.jpeg;*.png;*.bmp;*.gif")]
        )

        if file_path:
            # 打开图片
            img = Image.open(file_path)
            img.thumbnail((300, 300))  # 设置缩略图大小
            img = np.array(img)
            gray_img = cv2.cvtColor(img, code=cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray_img)
            if len(faces) > 0:
                input_value = simpledialog.askstring("输入", "请输入录入人脸的名字:")
                for x, y, w, h in faces:
                    if input_value:
                        print('录入人脸成功!')
                        face_label.append(len(face_package))
                        face_package.append(gray_img[y:y+h,x:x+w])
                        face_name[str(len(face_label))] = input_value
                    print(face_label)
                    print(face_name)
            else:
                messagebox.showinfo("提示", "没有检测到人脸,请重新输入")
            recognizer.train(face_package, np.array(face_label))

    # 创建Label控件,用于显示摄像头画面
    label = tk.Label(root2)
    label.place(x=50, y=50)  # 固定位置(x=50, y=50)

    # 启动图像更新
    update_frame()

    # label3 = ttk.Label(root2, text='人脸录入', font=("华文行楷", 35, "bold"))
    # label3.pack(pady=10)



    close_button = tk.Button(root2, text="开始从摄像头录入", font=("华文行楷", 20, "bold"), fg="white", bg="green", width=15,
                             height=2, command=capture_photo)
    close_button.place(x=750, y=80)
    close_button = tk.Button(root2, text="选择图片录入", font=("华文行楷", 20, "bold"), fg="white", bg="green", width=15,
                             height=2, command=open_image)
    close_button.place(x=750, y=240)
    close_button = tk.Button(root2, text="返回主页面",font=("华文行楷", 20, "bold"),fg="white", bg="red",width=15,height=2,command=close_new_window)
    close_button.place(x=750,y=400)


def face_distinguish():
    root.withdraw()
    '''创建一个顶级窗口'''
    root3 = tk.Toplevel(root)
    root3.geometry("1000x600")
    root3.title("facial distinguish")
    label = ttk.Label(root3, text='人脸识别', font=("华文行楷", 35, "bold"))
    label.pack(pady=10)
    def close_new_window():
        root3.destroy()
        root.deiconify()  # 恢复显示原窗口

    cap = cv2.VideoCapture(0)
    def update_frame():
        # 从摄像头读取一帧
        ret, frame = cap.read()
        if ret:
            # 将BGR图像转换为RGB格式
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            gray_img = cv2.cvtColor(frame,code=cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray_img)
            if len(faces) > 0:
                confidence = 10000
                for x, y, w, h in faces:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), [0, 0, 255], 3)
                    if len(face_label) > 0:
                        Label,confidence = recognizer.predict(gray_img[y:y+h,x:x+w])
                    img_pil = Image.fromarray(frame)
                    draw = ImageDraw.Draw(img_pil)
                    if confidence < 120:
                        draw.text((x+80,y-50),face_name[str(Label+1)],font=font,fill=(0,255,255))
                    else:
                        draw.text((x + 80, y - 50),'陌生人', font=font, fill=(0, 255, 255))
                    #再转回到array
                    frame = np.array(img_pil)
            # 将图像转换为PIL格式
            image = Image.fromarray(frame)
            # 将PIL图像转换为PhotoImage格式
            photo = ImageTk.PhotoImage(image)
            # 更新标签上的图像
            label.config(image=photo)
            label.image = photo
            label.place(x=100, y=70)
        # 每隔50毫秒更新一次
        root3.after(50, update_frame)

    # 创建Label控件,用于显示摄像头画面
    label = tk.Label(root3)
    label.place(x=100, y=100)  # 固定位置(x=50, y=50)

    # 启动图像更新
    update_frame()

    # close_button = tk.Button(root3, text="摄像头识别", font=("华文行楷", 20, "bold"), fg="white", bg="blue", width=10,
    #                          height=2, command=close_new_window)
    # close_button.place(x=750, y=80)
    # close_button = tk.Button(root3, text="图片识别", font=("华文行楷", 20, "bold"), fg="white", bg="blue", width=10,
    #                          height=2, command=close_new_window)
    # close_button.place(x=750, y=240)
    close_button = tk.Button(root3, text="返回主页面",font=("华文行楷", 20, "bold"),fg="white", bg="red",width=10,height=2,command=close_new_window)
    close_button.place(x=750,y=400)


def face_show():
    root.withdraw()
    '''创建一个顶级窗口'''
    root4 = tk.Toplevel(root)
    root4.geometry("1000x600")
    root4.title("facial distinguish")
    label = ttk.Label(root4, text='人脸库中的部分人脸', font=("华文行楷", 35, "bold"))
    label.pack(pady=10)
    def close_new_window():
        root4.destroy()
        root.deiconify()  # 恢复显示原窗口
    close_button = tk.Button(root4, text="返回主页面",font=("华文行楷", 20, "bold"),fg="white", bg="red",width=10,height=2,command=close_new_window)
    close_button.place(x=750,y=450)
    Label_dic = {}
    for i in range(len(face_package)):
        img = face_package[i]
        img = cv2.resize(img,(100,100))
        image = Image.fromarray(img)
        name = face_name[str(i+1)]
        Img = ImageTk.PhotoImage(image)
        Label_dic[str(i)] = tk.Label(root4, image=Img)
        Label_dic[str(i)].image = Img
        if i < 9:
            Label_dic[str(i)].place(x=50+i*100, y=60)  # 设置图片的位置,x和y为窗口中的坐标
        elif i >= 9 and i < 18:
            Label_dic[str(i)].place(x=50+(i-9)*100,y=180)
        elif i>=18 and i<27:
            Label_dic[str(i)].place(x=50 + (i - 18) * 100, y=300)


root = tk.Tk()
# 设置窗口大小为300x200


image = ImageTk.PhotoImage(file="background2.jpg")
root.geometry("800x400")
root.title('Facial Recognition')

label = ttk.Label(root,image=image)
label.pack(pady=10)

label1 = tk.Label(root,text='欢迎来到人脸识别系统',font=("华文行楷", 35, "bold"))
label1.place(x = 150,y=0)


button_GetFace = tk.Button(root, text="录入人脸",font=('华文行楷', 20,'bold'),width=10,height=2,command=choice_get_face_way)
button_GetFace.place(x=150,y=100)

button_GetFace = tk.Button(root, text="识别人脸",font=('华文行楷', 20,'bold'),width=10,height=2,command=face_distinguish)
button_GetFace.place(x=480,y=100)

button_GetFace = tk.Button(root, text="人脸显示",font=('华文行楷', 20,'bold'),width=10,height=2,command=face_show)
button_GetFace.place(x=150,y=250)

def exit_program():
    with open(dict_path, 'wb') as f:
        pickle.dump(face_name, f)
    with open(file_path, 'wb') as f:
        pickle.dump(face_package, f)
    sys.exit()  # 直接退出程序

button_GetFace = tk.Button(root, text="退出",font=('华文行楷', 20,'bold'),width=10,height=2,command=exit_program)
button_GetFace.place(x=480,y=250)

root.mainloop()

本人是新手,可能会有很多BUG,但是基本功能还是可以实现,希望对你有所帮助!

你可能感兴趣的:(完整代码,opencv,python,人工智能)