Some thoughts after the defense of the face recognition project

Recently, the weather has become hotter and hotter. With the downturn of the overall Internet environment, anxiety on the Internet has spread like a virus.

Only by sinking your heart can you do good deeds———

Recognition using MTCNN

  • MTCNN adopts a multi-level cascade structure, which can detect faces at different scales. This is useful for dealing with faces of different sizes, as faces may appear at different sizes in an image. Through multi-scale detection, MTCNN can effectively capture faces at different scales.
  • Real-time performance: MTCNN has undergone effective network design and optimization, enabling it to run quickly in real-time scenarios. The cascade structure allows the model to be pruned and screened in each stage, which reduces the amount of calculation and improves the detection speed. This makes MTCNN suitable for many real-time applications, such as face recognition, expression recognition, and face tracking.
  • Essence: find one by one + image pyramid

Loss function: Arcfaceloss

Reduce class cohesion and increase class distance

It’s easy to understand on paper, I don’t know that this matter needs to be coded

import cv2
import torch
from PIL import Image
from torchvision import transforms
import os
from MTCNN_Detect import Mtcnn_detect, loader_mtcnn, loader_Densenet201


Mtcnn_net = loader_mtcnn()  # 加载MTCNN
Densenet201 = loader_Densenet201()  # 网络


def library(image, name, Densenet201):     # image 人脸生图,   name 入库人姓名, Densenet201 网络
    Mtcnn_result = Mtcnn_detect(image, Mtcnn_net)   # MTCNN侦测方法,返回的是旋转拉正的人脸图片
    # 判断MTCNN人脸检测是否为None
    if Mtcnn_result==None:
        return

    img = Mtcnn_result    # 入库人脸图片
    img = transforms.ToTensor()(img)
    img = torch.unsqueeze(img, dim=0)

    li = []   # 库字典
    # 网络放入cuda
    Densenet201 = Densenet201.cuda()
    # net.load_state_dict(torch.load(r"D:\pythonProject1\person_face\parames\wight1.pth"))  # 加载权重文件
    # net.eval()   # 打开推理模式(测试模式)

    img = img.cuda()  # 放入cuda
    feature = Densenet201.feature(img)   # 获取网络输出特征向量
    feature = feature.tolist()   # 张量数据结构  转为列表
    li.append([name, feature])  # 姓名:特征向量, 键值对
    print(type(li))

    # pth文件入库
    path = r"D:\FaceProject\Face\faces.pth"   # pth 文件路径

    # 检查.pth文件是否为空
    if os.path.getsize(path) == 0:
        # .pth文件路径
        torch.save([li], path)

    # 当前库文件如果不是空的就需要把入库人脸特征添加进去,防止覆盖
    else:
        existing_data = torch.load(path)
        # 将新数据添加到现有数据中
        existing_data.append(li)
        # 保存更新后的数据回.pth文件
        torch.save(existing_data, path)

    return li


    # 判断库文件是否存在
    # if os.path.exists(r"D:\pythonProject1\person_face\libray.txt"):
    #     pass
    # else:
    #     with open(r"D:\pythonProject1\person_face\libray.txt", "w+", ) as libray:    # 创建库文件   os 是创建文件夹不是文件,
    #         print(f"库文件: libray.txt  创建成功")
    #
    # # 入库
    # with open(r"D:\pythonProject1\person_face\libray.txt", "a", encoding='utf-8') as file:
    #     file.write(f"{li}\n")
    #     print("入库成功")
    #     # file.write(li)
    # return li



# 入库3次
# for i in range(3):
#     image = Image.open(r"E:\FaceImage\陈昊\dst_img\chenhao (1).jpg")
#     a = library(image)




def video_ku():
    # 加载两个网络
    mtcnn_net = loader_mtcnn()
    densenet201_net = loader_Densenet201()

    # 打开视频文件
    video = cv2.VideoCapture(0)

    # 确保视频文件打开成功
    if not video.isOpened():
        print("无法打开视频文件")
        return

    # 获取视频的帧率
    fps = video.get(cv2.CAP_PROP_FPS)
    print(fps)

    # 设置视频窗口大小
    window_width = 800
    window_height = 800
    cv2.namedWindow("Video", cv2.WINDOW_NORMAL)
    cv2.resizeWindow("Video", window_width, window_height)

    # 设置保存区域的起始坐标和大小
    save_x = 80
    save_y = 20
    save_width = 450
    save_height = 400

    # 设置矩形的颜色和线宽
    rectangle_color = (255, 0, 0)  # 蓝色
    rectangle_thickness = 3


    while True:
        # 读取视频的帧
        ret, frame = video.read()    # ret 是一个布尔值,表示是否成功读取到了一帧。如果成功读取到帧,则 ret 的值,   frame是一个表示视频帧的图像数据,通常是一个 NumPy 数组。如果成功读取到帧,

        # 检查是否成功读取帧
        if not ret:
            break

        cv2.rectangle(frame, (save_x, save_y), (save_x + save_width, save_y + save_height), rectangle_color,
                      rectangle_thickness)
        cv2.imshow("Video", frame)       # 显示

        # 检测是否按下空格键
        if cv2.waitKey(1) == ord(' '):
            # 保存当前帧为图片
            frame = frame
            print("截取成功!")
            # 将图像从 BGR 格式转换为 RGB 格式
            image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            # 创建 PIL 对象
            image_pil = Image.fromarray(image_rgb)
            print(image_pil)

            # 入库
            library(image_pil, name=None, Densenet201=None)


        key = cv2.waitKey(1)
        # 如果按下键盘上的 "q" 键,则退出循环
        if key == ord("q"):
            break


    # 释放视频对象
    video.release()

# video_ku()

Qt display interface:

import os
import sys
import cv2
from PIL import Image
from PyQt5.QtGui import QImage, QPixmap, QFont, QColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QLineEdit, QPushButton, QLabel, QTextEdit
from MTCNN_Detect import loader_mtcnn, loader_Densenet201
from input_library import library

# 加载网络和权重
Mtcnn_net = loader_mtcnn()  # 加载MTCNN
Densenet201 = loader_Densenet201()  # 网络
print("网络加载成功")


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("中建八局员工人脸录入系统")
        self.setFixedSize(500, 500)  # 设置固定大小

        layout = QVBoxLayout()

        self.button = QPushButton("请正视摄像头")  # 创建一个按钮
        self.button.clicked.connect(self.button_clicked)
        self.button.setMinimumSize(200, 50)  # 设置按钮的最小宽度为200像素,高度为50像素
        self.button.setMaximumSize(300, 70)  # 设置按钮的最大宽度为300像素,高度为70像素
        layout.addWidget(self.button)

        layout.addWidget(QLabel("请输入员工姓名:"))

        self.text_input = QLineEdit()  # 创建一个文本输入框
        layout.addWidget(self.text_input)

        self.image_label = QLabel()  # 创建一个标签用于显示图像
        layout.addWidget(self.image_label)

        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

        # 设置布局为自适应窗口大小
        layout.setSizeConstraint(QVBoxLayout.SetNoConstraint)

        # 将图像标签的缩放模式设置为自适应布局
        self.image_label.setScaledContents(True)

        # 初始化按键
        self.key = None

        # 功能按钮二  截取图片入库
        self.button2 = QPushButton("人脸入库")
        self.button2.clicked.connect(self.button2_clicked)
        self.button2.setMinimumSize(200, 50)  # 设置按钮的最小宽度为200像素,高度为50像素
        self.button2.setMaximumSize(300, 70)  # 设置按钮的最大宽度为300像素,高度为70像素
        layout.addWidget(self.button2)

        # 显示结果
        self.result_text = QTextEdit()
        font = QFont()
        font.setPointSize(12)  # 设置字体大小为12
        self.result_text.setFont(font)

        # 设置字体颜色
        text_color = QColor(255, 0, 0)  # 设置为红色 (R, G, B)
        self.result_text.setTextColor(text_color)

        layout.addWidget(self.result_text)

        # 获取输入文本
        self.input_text = None

    # 入库按钮
    def button2_clicked(self):
        self.key = " "  # 空格截取
        self.input_text = self.text_input.text()  # 获取文本输入框中的字符串

    # 打开摄像头
    def button_clicked(self):

        # 判断库文件pth 收否存在,
        path = r"D:\FaceProject\Face\faces.pth"  # pth 文件路径
        # 判断当前有无库文件, 没有就创建
        if os.path.exists(path):
            pass
        else:
            with open(path, "w+", ) as libray:  # 创建库文件   os 是创建文件夹不是文件,
                pass

        # if True:
        # 打开视频文件
        video = cv2.VideoCapture(0)

        # 确保视频文件打开成功
        if not video.isOpened():
            print("无法打开视频文件")
            return

        # 获取视频的帧率
        fps = video.get(cv2.CAP_PROP_FPS)
        print(fps)

        while True:
            # 读取视频的帧
            ret, frame = video.read()

            # 检查是否成功读取帧
            if not ret:
                break

            # 将OpenCV的图像转换为QImage格式
            image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            height, width, channel = image.shape
            bytes_per_line = 3 * width
            q_image = QImage(frame.data, width, height, bytes_per_line, QImage.Format_RGB888).rgbSwapped()

            # 将QImage显示在QLabel控件中
            self.image_label.setPixmap(QPixmap.fromImage(q_image))

            QApplication.processEvents()  # # 更新界面

            # 检测是否按下空格键
            if self.key == " ":
                # 保存当前帧为图片
                frame = frame
                # print("截取成功!")
                # 将图像从 BGR 格式转换为 RGB 格式
                image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                # 创建 PIL 对象
                image_pil = Image.fromarray(image_rgb)
                print(image_pil)

                # 入库
                print("姓名:", self.input_text)
                result = library(image_pil, self.input_text,
                                 Densenet201)
                self.result_text.setPlainText(f"入库信息:\n {
      
      str(result)}")
                self.key = None

            else:
                pass


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

import sys
import cv2
from PIL import Image
from PyQt5.QtGui import QImage, QPixmap, QColor, QFont
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QPushButton, QLabel, QTextEdit
from Face_Detect import face_detect
from MTCNN_Detect import Mtcnn_detect, loader_Densenet201, loader_mtcnn

Densenet201 = loader_Densenet201()
Mtcnn = loader_mtcnn()
print("网络加载成功")


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("中建八局人脸识别系统")
        self.setFixedSize(500, 500)  # 设置固定大小

        # self.setWindowTitle("人脸识别检测")

        layout = QVBoxLayout()
        self.button = QPushButton("请正视摄像头")  # 按钮1
        self.button.clicked.connect(self.button_clicked)
        self.button.setMinimumSize(200, 50)  # 设置按钮的最小宽度为200像素,高度为50像素
        self.button.setMaximumSize(300, 70)  # 设置按钮的最大宽度为300像素,高度为70像素
        layout.addWidget(self.button)

        self.image_label = QLabel()  # 添加一个QLabel控件用于显示图像
        layout.addWidget(self.image_label)

        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

        self.button3 = QPushButton("开始检测")
        self.button3.clicked.connect(self.button3_clicked)
        self.button3.setMinimumSize(200, 50)  # 设置按钮的最小宽度为200像素,高度为50像素
        self.button3.setMaximumSize(300, 70)  # 设置按钮的最大宽度为300像素,高度为70像素
        layout.addWidget(self.button3)

        # 设置布局为自适应窗口大小
        layout.setSizeConstraint(QVBoxLayout.SetNoConstraint)

        # 将图像标签的缩放模式设置为自适应布局
        self.image_label.setScaledContents(True)

        # 显示结果
        self.result_text = QTextEdit()
        font = QFont()
        font.setPointSize(12)  # 设置字体大小为12
        self.result_text.setFont(font)

        # 设置字体颜色
        text_color = QColor(255, 0, 0)  # 设置为红色 (R, G, B)
        self.result_text.setTextColor(text_color)

        layout.addWidget(self.result_text)

        # 继续检测开关
        self.num = 0
        # 开始检测按钮
        self.start = None

    # 继续检测按钮
    def button2_clicked(self):
        # 在这里调用你自己的函数
        self.num = 0

    # 开始检测按钮
    def button3_clicked(self):
        # 在这里调用你自己的函数
        self.start = 0

    # 检测人脸
    def button_clicked(self):
        print("正在识别,请稍后......")
        # 在这里调用您自己的函数

        # if True:
        # 打开视频文件
        video = cv2.VideoCapture(0)

        # 确保视频文件打开成功
        if not video.isOpened():
            print("无法打开视频文件")
            return

        # 获取视频的帧率
        fps = video.get(cv2.CAP_PROP_FPS)
        print(fps)

        # 设置检测区域的起始坐标和大小
        save_x = 80
        save_y = 20
        save_width = 450
        save_height = 400

        # 设置矩形的颜色和线宽
        rectangle_color = (255, 0, 0)  # 蓝色
        rectangle_thickness = 3

        frame_count = 0  # 计数
        interval = 20  # 设置检测帧率, 多少帧检测一次

        while True:
            # 读取视频的帧
            ret, frame = video.read()

            # 检查是否成功读取帧
            if not ret:
                break

            # 在视频帧上画出矩形区域
            # cv2.rectangle(frame, (save_x, save_y), (save_x + save_width, save_y + save_height), rectangle_color,
            #               rectangle_thickness)

            # # 将OpenCV的图像转换为QImage格式
            image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            height, width, channel = image.shape
            bytes_per_line = 3 * width
            q_image = QImage(frame.data, width, height, bytes_per_line, QImage.Format_RGB888).rgbSwapped()

            # 将QImage显示在QLabel控件中
            self.image_label.setPixmap(QPixmap.fromImage(q_image))

            QApplication.processEvents()  # 更新界面

            if self.start != None:
                # 设置检测帧率
                if frame_count % interval == 0 and self.num == 0:  # 添加检测开关

                    save_image = frame[save_y:save_y + save_height, save_x:save_x + save_width]
                    # 将图像从 BGR 格式转换为 RGB 格式
                    image_rgb = cv2.cvtColor(save_image, cv2.COLOR_BGR2RGB)
                    image_pil = Image.fromarray(image_rgb)
                    if Mtcnn_detect(image_pil, Mtcnn) == None:
                        continue
                    else:
                        result = Mtcnn_detect(image_pil, Mtcnn)  # 返回MTCNN结果
                        face_result = face_detect(result, threshold=0.6, loader_net=Densenet201)
                        # 显示结果
                        self.result_text.setPlainText(f"人脸识别结果:\n {
      
      str(face_result)}")
                        if face_result != None:  # 设置开关
                            self.num = 1
                        else:
                            pass
            else:
                pass
            frame_count += 1
        video.release()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

Guess you like

Origin blog.csdn.net/weixin_44659309/article/details/131398266