文章目录
1.项目背景
在科技发展的推动下,门锁系统的演进日新月异。从原始、简单的机械构造,门锁技术已迈向了一个全新的智能化阶段,这一转变涵盖了生物识别、通讯技术、机械工程以及计算机科学的深度融合与应用。门锁系统的初期阶段一般使用机械门锁,但由于其仅依赖于钥匙这一验证方式,容易被盗用,安全性不足。所以,改进后的门锁就诞生了,它有电子锁,也有电子卡,可以用密码和磁卡进行识别。随着网络、物联网、计算机和生物特征识别等技术的不断进步,门禁系统越来越具有安全性、可靠性、便利性和便于管理的特点。
2.研究目的
人脸识别技术凭借普通摄像头即可轻松采集信息,为用户提供了便捷的基础信息获取途径,同时非接触的识别过程确保了良好的用户体验。并且,人脸识别技术的实施并无需大量特殊装置,只需对现有计算机系统进行功能升级即可实现,不仅可以保证使用者的资金投入,而且可以扩充装置的功能,更能满足使用者的安全性要求。因此,在门锁系统中引入人脸识别技术,是一项很有实用价值的研究课题。
3.项目架构
3.1 Nvidia Jetson Nano
Nvidia Jetson Nano 是一款由 Nvidia推出的小型嵌入式计算机,如图2.1所示,其旨在提供高性能的人工智能计算能力。Jetson Nano采用了Nvidia的Tegra系列系统级芯片,这款设备配备了四核 ARM Cortex-A57 处理器和 Nvidia Maxwell 架构的 GPU,带有 128 个 CUDA 核心,同时还搭载了 4GB LPDDR4 内存。提供了强大的计算能力,支持各种人工智能算法和深度学习模型的部署和运行。并且有丰富的连接接口,包括4个USB 3.0端口、1个Gigabit Ethernet端口、1个 HDMI输出端口、1个DisplayPort输出端口、1个MIPI CSI摄像头接口和1个MIPI DSI显示器接口等,与此同时,Jetson Nano采用了低功耗设计,功耗仅为5-10瓦,适合于嵌入式应用和便携式设备。
3.2 工作逻辑
智能门锁的工作逻辑如图2.3所示,系统是由Jetson Nano作为主控芯片,PyQt5界面作为用户端窗口,系统启动后,为用户展示登录界面,用户在登录后,可以进行检测视频、检测照片、人脸编码、录入人脸的功能,启动程序后,选择检测视频模式,程序调用Retinaface 和 FaceNet 开始实时对人脸进行检测,当检测到的人脸信息与在数据库中的人脸信息匹配后,把检测结果到Esp8266,假如 Esp8266收到了身份确认的消息,则开门。反之,假如Esp8266没有收到确认身份的消息,则不开门,开门的信息会以日志形式回传到阿里云平台,用户可以远程监测门锁开启的时间。
用户在选择“检测图片”模式后,会弹出文件选择窗口,供用户选取测试图片,在系
统目录下/img文件夹内有若干个图片可供测试,此功能用于测试模型能否工作。
用户在首次启动本系统时,要先选择“录入人脸信息”模式,点击此按钮会弹出新窗
口,可以进行拍照、命名、保存,在人脸信息成功保存后,退出当前窗口,再点击“编码人脸信息”,系统则会自动开始编码,当编码完成之后,用户便可选择“检测视频”模式,查看系统能否正常工作。 项目的整体情况如下图所示,屏幕上显示的用户的登陆与注册界面,在用户登陆进入系统之后,即可开始执行人脸检测模式或人脸录入模式。Jetson Nano连接了Esp8266,假如人脸数据在数据中并且识别通过的话,Jetson Nano会向Esp8266发送指令,Esp8266收到指令后,控制舵机的开启。
下面是系统的工作流程图
4.主要算法
4.1 Retinaface 算法
Retinaface 算法在 WiderFace 数据集上取得了显著的 AP 提升,这一结果显示了其在人脸识别领域的出色性能。Retinaface的人脸检测方式如图2.4所示,该算法的源代码已在insightface 平台上公开,原模型基于mxnet框架开发,但目前在社区中,基于其他框架的复现版本也颇受欢迎。Retinaface的核心创新在于在原有的检测网络RetinaNet基础上,巧妙地融合了三个层级的SSH检测模组,这一设计显著提升了人脸侦测的准确度。研究人员给出了两个不同的网络模型,前者是为了提高检测的速度,后者是为了提高检测的准确性。
4.2 FaceNet算法
FaceNet的核心策略在于利用卷积神经网络来学习人脸图像在欧式空间中的特征表示。这种方法的设计初衷在于通过训练,使得在欧式空间中,两张属于同一人的人脸图像所对应的特征向量之间的距离尽可能小。换言之,如果两幅人脸图像的特征向量在欧式空间中的距离越近,那么这两幅图像属于同一人的可能性就越大。这种策略为人脸识别任务提供了一种高效且准确的方法,使得在海量的人脸数据中快速、准确地识别出目标个体成为可能。此算法的实现过程:首先计算人脸特征的特征向量,然后通过比较距离并设置阈值,即可确定两张人脸照片是否来自同一人。在成功构建人脸图像特征提取模型后,人脸验证过程实质上转化为了一个比较过程:比较两幅图像特征向量的相似度与预设阈值的大小。
对于人脸识别任务,问题进一步转化为在已提取的特征向量集中进行K近邻分类的问题,通过寻找与待识别图像特征最相近的 K个已知类别特征,来确定其所属身份。此外,对于人脸聚类任务,本文可以采用k-means聚类算法对提取到的人脸特征集进行分组,从而实现将相似的人脸图像聚类到同一个类别中的目的。这样,不同的人脸图像处理任务就可以通过这些高效且准确的方法得到妥善解决。
4.3 PyQt界面
通过PyQt5,本文创建了三个基本页面,分别是登录界面、主窗口、录入界面。程序启动后,会展示出登录界面,登录界面有两个基本功能,一个是登录,一个是注册,用户注册后的信息会存储到csv的表格中。登陆界面如下图所示
当用户输入帐号密码后,会进入到人脸检测系统的主页面。主界面如图 2.12所示。
主界面有四个功能,分别是检测视频、检测图片、编码人脸信息、录入人脸。检测视频的功能是开启摄像头,利用摄像头进行实时检测,检测图片的主要功能是测试算法能否正常运行。点击“检测图片”按钮后,会弹出选择人脸图片的窗口,选择好人脸图片后,执行算法显示检测信息。编码人脸信息的主要功能是对录入的人脸信息进行编码,把人脸信息存储到数据库中。录入人脸会打开新的窗口,启动Jetson Nano的摄像头进行拍摄功能。
4.4 MG996R舵机
在这一课题中,舵机由 Esp8266 控制,在检测视频的模式下,当确认身份信息后,Jetson Nano 会将确认信息发送给Esp8266,Esp8266收到确认信息后,控制舵机的开启与关闭。舵机的启动结果会通过mqtt协议上传到阿里云,用户可以远程监控门锁的开启情况。
5.项目核心文件与代码
5.1 项目文件目录
文件目录如下所示
5.2 项目部分代码
5.2.1 Main.py
#coding=utf-8
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QFileDialog
import time
import cv2
import csv
import numpy as np
from retinaface import Retinaface
import extract_name
import compare
from SelectPic import pick_video
from SelectPic import pick_pic
from SelectPic import encode_pic
import sys
from PyQt5 import QtCore,QtWidgets
from PyQt5.QtWidgets import *
import predict_pic
import predict_video
from LoginWindow import Ui_loginWindow
from SelectPic import FilePicker
import serial
class LoginWindow(QMainWindow,Ui_loginWindow):
def __init__(self):
super().__init__()
# 继承外部ui
self.setupUi(self)
# 隐藏外部多余窗口 他们要一起写上
self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
# 主窗体阴影
self.shadow = QtWidgets.QGraphicsDropShadowEffect(self)
self.shadow.setOffset(0,0)
self.shadow.setBlurRadius(15)
self.shadow.setColor(QtCore.Qt.blue)
self.frame_1.setGraphicsEffect(self.shadow)
self.frame_2.setGraphicsEffect(self.shadow)
# 主按钮绑定事件
self.stackedWidget_login.setCurrentIndex(1)
self.pushButton_login.clicked.connect(lambda :self.stackedWidget_login.setCurrentIndex(1))
self.pushButton_register.clicked.connect(lambda :self.stackedWidget_login.setCurrentIndex(0))
self.pushButton_sure.clicked.connect(self.verify_login)
self.pushButton_r_register.clicked.connect(self.register_submit)
def register_submit(self):
account = self.lineEdit_r_account.text()
pwd1 = self.lineEdit_r_pwd.text()
pwd2 = self.lineEdit_r_pwd2.text()
# 检查密码是否一致
if pwd1 != pwd2:
self.label_message.setText('两次输入的密码不一样')
return
# 将账户和密码写入 CSV 文件
csv_file = 'user_accounts.csv'
with open(csv_file, 'a', newline='') as file:
writer = csv.writer(file)
writer.writerow([account, pwd1])
self.label_message.setText('注册成功')
# 自定义内部ui
self.setup_ui()
def verify_login(self):
account = self.lineEdit_account.text()
pwd = self.lineEdit_pwd.text()
# 从 CSV 文件中读取账户和密码信息
csv_file = 'user_accounts.csv'
with open(csv_file, 'r', newline='') as file:
reader = csv.reader(file)
for row in reader:
if row[0] == account and row[1] == pwd:
print('登录成功')
try:
self.main = FilePicker()
self.main.show()
self.close()
except Exception as e:
print(e)
return
# 如果账户或密码错误,则显示错误消息
self.label_message.setText('账号或密码错误,请重试')
def setup_ui(self):
pass
# 主界面类
class MianWindow(QMainWindow,FilePicker):
def __init__(self):
super().__init__()
self.ui = FilePicker()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = LoginWindow()
window.show()
sys.exit(app.exec_())
predict_pic.detect_pic(pick_pic())
# predict_video.detect_video(pick_video())
5.2.2 Esp8266.c
#include <Servo.h>
#include <ArduinoMqttClient.h>
#include <ESP8266WiFi.h>
// 舵机控制引脚
const int servoPin = D5;
Servo servo;
// 串口通信参数
const int baudRate = 9600;
// 定义舵机初始角度和目标角度
const int initialAngle = 90;
const int targetAngle = 180;
// 定义舵机转动速度
const int servoSpeed = 1; // 舵机转动速度,可以根据需要调整
bool servoMoving = false;
char ssid[] = "meng"; // your network SSID (name)
char pass[] = "25197758"; // your network password (use for WPA, or use as key for WEP)
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = "iot-06z00eaojla1tr3.mqtt.iothub.aliyuncs.com";
int port = 1883;
const char inTopic[] = "/sys/k15pz2oiJaP/Cloud/thing/service/property/set";
const char outTopic[] = "/sys/k15pz2oiJaP/MG996R/thing/service/property/set";
const long interval = 10000;
unsigned long previousMillis = 0;
int count = 0;
void setup() {
// 初始化舵机引脚
servo.attach(servoPin);
// 初始化串口通信
Serial.begin(baudRate);
// 将舵机移动到初始位置
servo.write(initialAngle);
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// attempt to connect to WiFi network:
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// failed, retry
Serial.print(".");
delay(5000);
}
Serial.println("You're connected to the network");
Serial.println();
mqttClient.setId("k15pz2oiJaP.MG996R|securemode=2,signmethod=hmacsha256,timestamp=1713862406063|");
mqttClient.setUsernamePassword("MG996R&k15pz2oiJaP","39ab0c4c3dc156df441d38bf1578371726899ca7db789739beb141fce70aa6cf");
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("You're connected to the MQTT broker!");
Serial.println();
// set the message receive callback
mqttClient.onMessage(onMqttMessage);
Serial.print("Subscribing to topic: ");
Serial.println(inTopic);
Serial.println();
int subscribeQos = 1;
mqttClient.subscribe(inTopic, subscribeQos);
Serial.print("Waiting for messages on topic: ");
Serial.println(inTopic);
Serial.println();
}
void loop() {
int command = Serial.parseInt();
servo.write(90);
mqttClient.poll();
String payload;
if (command == 1 && !servoMoving) {
//servoMoving = true;
//moveServo();
servo.write(targetAngle);
delay(5000);
servo.write(90);//停止了
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
payload += "Start!";
//payload += "hello world!";
//payload += " ";
//payload += count;
Serial.print("Sending message to topic: ");
Serial.println(outTopic);
Serial.println(payload);
bool retained = false;
int qos = 1;
bool dup = false;
mqttClient.beginMessage(outTopic, payload.length(), retained, qos, dup);
mqttClient.print(payload);
mqttClient.endMessage();
Serial.println();
count++;
}
}
// 检查舵机是否在运动中,如果是,则更新舵机角度
if (servoMoving) {
if (servo.read() == targetAngle) {
// 舵机已经到达目标位置,复位并停止运动
servoMoving = false;
servo.write(initialAngle);
}
}
//unsigned long currentMillis = millis();
// 读取串口输入
// if (currentMillis - previousMillis >= interval) {
// previousMillis = currentMillis;
// payload += "hello world!";
// //payload += " ";
// //payload += count;
// Serial.print("Sending message to topic: ");
// Serial.println(outTopic);
// Serial.println(payload);
// bool retained = false;
// int qos = 1;
// bool dup = false;
// mqttClient.beginMessage(outTopic, payload.length(), retained, qos, dup);
// mqttClient.print(payload);
// mqttClient.endMessage();
// Serial.println();
// count++;
// }
}
void onMqttMessage(int messageSize) {
// we received a message, print out the topic and contents
Serial.print("Received a message with topic '");
Serial.print(mqttClient.messageTopic());
Serial.print("', duplicate = ");
Serial.print(mqttClient.messageDup() ? "true" : "false");
Serial.print(", QoS = ");
Serial.print(mqttClient.messageQoS());
Serial.print(", retained = ");
Serial.print(mqttClient.messageRetain() ? "true" : "false");
Serial.print("', length ");
Serial.print(messageSize);
Serial.println(" bytes:");
// use the Stream interface to print the contents
while (mqttClient.available()) {
Serial.print((char)mqttClient.read());
}
Serial.println();
Serial.println();
}
6.参考文献
[1] 李浩轩.手背静脉身份识别方法门锁系统研究[J].冶金设备,2023(S1):14-17+117.
[2] 贺云飞,甘雨,肖国锐.基于ZigBee的智能门锁系统设计[J].电子设计工程,2023,31(16):6-10.
[3] 谷月. 虹膜识别“解锁”智能门锁[N]. 中国电子报,2023-04-21(006).
[4] J. B. Jin, H. K. Hee, S. S. Soo. Door-Lock System to Detect and Transmit in Real Time according to External Shock Sensitivity[J]. Journal of the Korea Convergence Society, 2018, 9(7): 9-16.
[5] P.Jayasri ,C.Pradeepthi,B.Madhavi, et al.SMART DOOR LOCK SYSTEM INTEGRATED WITH RASPBERRY PI USING IoT[J].Journal of Critical Reviews,2020,7(16):2244-2250.
[6] M. Shanthini, G. Vidya and R. Arun, “IoT Enhanced Smart Door Locking System,” 2020 Third International Conference on Smart Systems and Inventive Technology (ICSSIT), Tirunelveli, India, 2020, pp. 92-96.
[7] Y. Sun, X. Wang and X. Tang, “Deep Learning Face Representation from Predicting 10,000 Classes,”
2014 IEEE Conference on Computer Vision and Pattern Recognition, Columbus, OH, USA, 2014, pp.
1891-1898.
[8] X. Deng and P. L. Dragotti, “Deep Convolutional Neural Network for Multi-Modal Image Restoration and Fusion,” in IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 43, no. 10, pp. 3333
3348, 1 Oct. 2021.
[9] Liu, W., Anguelov, D., Erhan, D., Szegedy, C., Reed, S.E., Fu, C., & Berg, A.C. (2015). SSD: Single Shot MultiBox Detector. European Conference on Computer Vision.
[10] J. Deng, J. Guo, N. Xue and S. Zafeiriou, “ArcFace: Additive Angular Margin Loss for Deep Face Recognition,” 2019 IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR), Long Beach, CA, USA, 2019, pp. 4685-4694.
[11]Bubbliiiing. 聪明的人脸识别3——Pytorch 搭建自己的Facenet人脸识别平台[EB/OL]. (2020-11-24)[2024-04-13]. https://blog.csdn.net/weixin_44791964/article/details/108220265.
[12]Bubbliiiing. 聪明的人脸识别4——Pytorch 利用Retinaface+Facenet搭建人脸识别平台[EB/OL]. (2020-12-13)[2024-11-12]. https://blog.csdn.net/weixin_44791964/article/details/111130326.