首页 > 其他分享 >基于RetinaFace+Jetson Nano的智能门锁系统——第四篇(完整项目)

基于RetinaFace+Jetson Nano的智能门锁系统——第四篇(完整项目)

时间:2024-11-12 17:45:55浏览次数:3  
标签:RetinaFace mqttClient Nano self println 人脸 print Jetson Serial

文章目录


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.

标签:RetinaFace,mqttClient,Nano,self,println,人脸,print,Jetson,Serial
From: https://blog.csdn.net/qq_42887663/article/details/143703608

相关文章

  • Jetson AGX Orin平台相机驱动r35.4.1升级到r35.5.0版本,vi无数据导致内核崩溃问题【有
    1.问题描述在r35.4.1中的驱动程序中相机采集正常;升级到r35.5.0没有问题后,当使用v4l2-ctl命令打印帧速率时,当没有连接传感器或传感器没有启动流时,在dmesg中发生以下错误:[1432.454398]tegra-camrtc-capture-vitegra-capture-vi:uncorr_err:requesttimedoutafter250......
  • Jetson AGX Orin 实现相机雷达联合标定
    JetsonAGXOrin实现相机雷达联合标定.使用autoware标定工具,联合标定lidar和相机,计算出内外参等参数,实现点云目标映射到图像上.点云分隔目标映射图片环境安装参考:JetsonAGXOrin安装Autowarecalibration_toolkit标定工具标定雷达和相机新开终端roscore......
  • retinaface模型实现人脸识别(pytorch)
    项目源码获取方式见文章末尾!回复暗号:13,免费获取600多个深度学习项目资料,快来加入社群一起学习吧。《------往期经典推荐------》项目名称1.【YOLO模型实现农作物病虫害虫识别带GUI界面】2.【卫星图像道路检测DeepLabV3Plus模型】3.【GAN模型实现二次元头像生成】4.......
  • Jetson_MPU6050_DMP_Python读取
    编译动态链接库I2CDevLib仓库选用Linux上驱动I2C和MPU6050的代码,克隆LinuxI2CDev文件夹到本地,然后进入到文件夹中,创建一个main.cpp用来创建与Python的函数接口,可以自定义。这里的代码没有考虑零偏,只是从DMP取出四元数换算得到结果的,实际用的时候有不小的零偏,可以添加上初始化时......
  • 【jetson orin】jetson-stats安装与使用
    介绍:jetson状态面板,用来实时的查看jetson状态,非常有用推荐安装。安装:#下载自动安装脚本curlhttps://bootstrap.pypa.io/get-pip.py-oget-pip.py#运行安装脚本sudopython3get-pip.pysudopip3installjetson-stats运行:#输入命令就可以打开面板jtop设置风......
  • 【jetson orin】Jetson Containers介绍安装与应用
    MachineLearningContainersforJetsonandJetPack项目地址:项目仓库介绍:他的用途大概是帮助开发者快速的构建和运行一些docker镜像,比如ollama、llama-factory等热门项目都支持。在运行和构建的过程中针对jetson有做相当的优化。所以建议使用jetson容器去运行各个开源框架,......
  • 【玩转jetson orin nano(二)系统基本设置】
    B站运行YOLOv8n视频demo:https://www.bilibili.com/video/BV1dc411J71N文章目录一、系统基本设置1.软件换源2.安装ssh3.jtop安装4.模式切换(可选)5.cuda+cudnn+TensorRT配置5.1cuda配置5.2cudnn配置5.3TensorRT配置5.4查看环境版本一、系统基本设置1.软件......
  • 【玩转jetson orin nano(三)PyTorch深度学习环境安装】
    文章目录一、PyTorch深度学习环境安装1.Anaconda安装1.1下载1.2安装1.3换源1.4创建环境1.5设置默认启动环境1.6卸载2.安装torch+torchvisiion2.1安装torch2.2安装torchvisiion2.3验证2.4备注(可直接跳过)一、PyTorch深度学习环境安装1.Anaconda安装1.1......
  • Gstreamer系列(5):Gstreamer在arm平台(Nano, Orin, Xavier等)使用硬编码对视频进行保存mp
            在工程实践中,通常使用使用英伟达版板卡作为图像处理的控制器,常见的有xavier,TX2,orin,Nano等,这些控制器使用Gstreamer进行硬件编码的插件通常为omxh264enc,nvv4l2h264enc。本文将基于这两个插件进行介绍区别,并给出使用示例本。本系列其他文章有:Gstreamer系......
  • Stanford CS149 -- Assignment 4: NanoGPT149
    作业描述及代码参见:cs149gptWarm-Up:访问张量张量/数组都是按行存储的,四维数组可以看作元素为三维数组的数组,元素大小即为三维数组内元素总数,以此类推。第1部分:简单(但不太高效)的注意力机制实现主要实现两个矩阵乘法和一个softmax运算。第2部分:块矩阵乘法和UnfusedSof......