项目名称:基于RetinaFace+Jetson Nano的智能门锁系统
项目时间:2024年4月-2024年6月
项目平台:PC、Linux
项目语言:Python、C
项目软件:Pycharm、阿里云、Arduino、VScode
在科技发展的推动下,门锁系统的演进日新月异。从原始、简单的机械构造,门锁技术已迈向了一个全新的智能化阶段,这一转变涵盖了生物识别、通讯技术、机械工程以及计算机科学的深度融合与应用。门锁系统的初期阶段一般使用机械门锁,但由于其仅依赖于钥匙这一验证方式,容易被盗用,安全性不足。所以,改进后的门锁就诞生了,它有电子锁,也有电子卡,可以用密码和磁卡进行识别。随着网络、物联网、计算机和生物特征识别等技术的不断进步,门禁系统越来越具有安全性、可靠性、便利性和便于管理的特点。
人脸识别技术凭借普通摄像头即可轻松采集信息,为用户提供了便捷的基础信息获取途径,同时非接触的识别过程确保了良好的用户体验。并且,人脸识别技术的实施并无需大量特殊装置,只需对现有计算机系统进行功能升级即可实现,不仅可以保证使用者的资金投入,而且可以扩充装置的功能,更能满足使用者的安全性要求。因此,在门锁系统中引入人脸识别技术,是一项很有实用价值的研究课题。
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瓦,适合于嵌入式应用和便携式设备。
Retinaface 算法在 WiderFace 数据集上取得了显著的 AP 提升,这一结果显示了其在人脸识别领域的出色性能。Retinaface的人脸检测方式如图2.4所示,该算法的源代码已在insightface 平台上公开,原模型基于mxnet框架开发,但目前在社区中,基于其他框架的复现版本也颇受欢迎。Retinaface的核心创新在于在原有的检测网络RetinaNet基础上,巧妙地融合了三个层级的SSH检测模组,这一设计显著提升了人脸侦测的准确度。研究人员给出了两个不同的网络模型,前者是为了提高检测的速度,后者是为了提高检测的准确性。
Mobilenet网络如下表所示,一共28层,第一层是标准卷积,剩下的就是Depth wise Separable Convolution深度可分离卷积
FaceNet的核心策略在于利用卷积神经网络来学习人脸图像在欧式空间中的特征表示。这种方法的设计初衷在于通过训练,使得在欧式空间中,两张属于同一人的人脸图像所对应的特征向量之间的距离尽可能小。换言之,如果两幅人脸图像的特征向量在欧式空间中的距离越近,那么这两幅图像属于同一人的可能性就越大。这种策略为人脸识别任务提供了一种高效且准确的方法,使得在海量的人脸数据中快速、准确地识别出目标个体成为可能。此算法的实现过程:首先计算人脸特征的特征向量,然后通过比较距离并设置阈值,即可确定两张人脸照片是否来自同一人。在成功构建人脸图像特征提取模型后,人脸验证过程实质上转化为了一个比较过程:比较两幅图像特征向量的相似度与预设阈值的大小。
对于人脸识别任务,问题进一步转化为在已提取的特征向量集中进行K近邻分类的问题,通过寻找与待识别图像特征最相近的 K个已知类别特征,来确定其所属身份。此外,对于人脸聚类任务,本文可以采用k-means聚类算法对提取到的人脸特征集进行分组,从而实现将相似的人脸图像聚类到同一个类别中的目的。这样,不同的人脸图像处理任务就可以通过这些高效且准确的方法得到妥善解决。
工作流程:
通过PyQt5,本文创建了三个基本页面,分别是登录界面、主窗口、录入界面。程序启动后,会展示出登录界面,登录界面有两个基本功能,一个是登录,一个是注册,用户注册后的信息会存储到csv的表格中。登陆界面如下图所示
在这一课题中,舵机由 Esp8266 控制,在检测视频的模式下,当确认身份信息后,Jetson Nano 会将确认信息发送给Esp8266,Esp8266收到确认信息后,控制舵机的开启与关闭。舵机的启动结果会通过mqtt协议上传到阿里云,用户可以远程监控门锁的开启情况。
#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())
#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","39ab0c4c3dc156df441d38bf15783717269ca7db7739beb141fce70aa6cf");
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();
}
项目难点:在特征提取网络的选择上,有两个选择,可以选择resnet和MobileNet,但是因为resnet的参数多,所以选择MobileNet,但是运行速度快,就意味着一定的精度损失,所以引入了例如SSH这样的特征提取模块,提高精确度。
在PC端能跑起来,但是在开发板不能运行,或者运行卡顿,找到原因是因为算力不足,所以需要引入tensorrt加速。
linux配置环境很复杂,需要重新编译几个库,在运行软件的时候,使用strace跟踪程序运行进程,检查在哪里卡住了。
[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.
11-18.
[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:///weixin_447919/article/details/108220265.
[12]Bubbliiiing. 聪明的人脸识别4——Pytorch 利用Retinaface+Facenet搭建人脸识别平台[EB/OL]. (2020-12-13)[2024-11-12]. https:///weixin_447919/article/details/111130326.
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务