最近天气愈发燥热,伴随着互联网整体大环境的下行,网络上的焦虑像病毒一样蔓延。
沉下心,才能做好事————
识别用了MTCNN
- MTCNN采用多层级的级联结构,可以在不同尺度上检测人脸。这对于应对不同大小的人脸很有用,因为人脸在图像中可能以不同的尺寸出现。通过多尺度检测,MTCNN能够有效捕捉不同尺度下的人脸。
- 实时性能:MTCNN经过有效的网络设计和优化,使其在实时场景下能够快速运行。级联结构允许模型在每个阶段中进行剪枝和筛选,减少了计算量,提高了检测速度。这使得MTCNN适用于很多实时应用,如人脸识别、表情识别和人脸跟踪等。
- 本质:一个一个找 + 图像金字塔
损失函数:Arcfaceloss
减小类内聚、增加类间距
纸上得来终觉浅,绝知此事要coding
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的展示界面:
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_())