本网页已闲置超过3分钟,按键盘任意键或点击空白处,即可回到网页

基于Bolt的人脸解锁智能门

发布时间:2022-07-28
分享到:

基于Bolt的人脸解锁智能门

发布时间:2022-07-28
分享到:

背景说明

本文旨在通过使用 Bolt IoT 将面部解锁功能带到您的架子、门或衣柜。

我们生活在一个互联网革命的时代,现在比以往任何时候都更容易进行实验和创新,以提出可以对全世界数百万人产生积极影响的绝妙想法。

曾经想为您家中的架子、抽屉、衣柜或门增加一点额外的安全性吗?当谈到使用互联网进行创新时,在我们可用的数千个平台和工具中,有几个脱颖而出的。这个项目中,我们将修改一个标准架子,使其拥有一个使用人脸验证解锁的安全系统。我们将用C#构建一个Windows 窗体应用程序,它可以存储、验证和解锁受信任的面孔。它用于面部验证和Bolt IoT Cloud API,用于与 Bolt WiFi 模块和 Arduino 进行通信。我们将 Bolt WiFi 模块与Arduino Uno连接,它将控制伺服电机锁定/解锁门。在这个项目的开发过程中,很多这些概念都派上了用场。

第 1 步:构建软件
我们将使用 Visual Studio 构建一个 Windows 窗体应用程序。此应用程序在 Windows 机器上运行,将负责管理授权人脸、使用 FacePlusPlus API 验证人脸以及与 Bolt WiFi 模块通信。我们将使用 C# 进行编码。

启动 Visual Studio 并创建新的 Windows 窗体应用程序项目。如果您完全不熟悉 Visual Studio,我建议您学习使用 Visual Studio 进行 Windows 窗体应用程序开发的基础知识。

在本文中,我将仅使用项目中执行主要和重要功能的代码片段来解释代码。浏览整个代码将是乏味且不必要的,因为其中大部分都是不言自明且有据可查的。

我们的 Visual Studio 项目将 3 个库用于各种目的。他们是:

  • AForge .NET:一种流行的 .NET 框架,用于 Windows 中的图像处理。我们使用它从网络摄像头捕获图像。
  • Bolt IoT API .NET:我用 C# 编写的非官方客户端库,用于与 Bolt Cloud API 进行通信。
  • Newtonsoft JSON:一种流行的 .NET 高性能 JSON 框架。用于在我们的项目中解析 A​​PI 响应。

入门
在开始编码之前,我们需要设置一些东西。

1. Bolt Cloud API 凭证

如果您还没有,请访问cloud.boltiot.com并设置一个帐户。登录后,将您的 WiFi 模块与 Bolt Cloud 链接。为此,请在您的手机上下载 Bolt IoT 设置应用程序。按照应用程序中的说明将您的设备与您的帐户相关联。这涉及将 Bolt 与本地 WiFi 网络配对。成功链接后,您的仪表板将显示您的设备。您现在可以从仪表板获取您的设备 ID和API 密钥。

2. FacePlusPlus API 凭证

我们在这个项目中依赖的另一个 API 服务是FacePlusPlus API。它是一个免费平台,提供各种图像识别服务。我们用它来进行面部识别。创建一个帐户并转到 FacePlusPlus 控制台。转到下方并单击。记下新生成的API Key和API Secret 。API KeyApps+Get API Key

现在您应该准备好以下内容:

private readonly string BOLT_DEVICE_ID = "BOLTXXXXXX";
private readonly string BOLT_API_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
  
private readonly string FPP_API_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
private readonly string FPP_API_SECRET = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

我们创建一个名为 的 Bolt 类的新全局实例myBolt,通过它我们将与 WiFi 模块进行所有未来的通信:

myBolt = new Bolt(BOLT_API_KEY, BOLT_DEVICE_ID);

也就是说,现在让我们看看我们的应用程序如何执行一些核心功能。

功能介绍

1. 锁定/解锁门
我们设计了这样的电路,当数字引脚 0 为HIGH时,门应该被锁定,而当数字引脚 3 为 时HIGH,门应该被解锁。稍后我们讨论电路原理图时会更清楚地说明这一点。

对于锁定,我们使用DigitalMultiWrite库中的方法将HIGH值写入 D0 并将 LOW 值写入 D3。这将向 Arduino 发出锁门信号。同样对于解锁,我们将LOW值写入 D0 并将HIGH值写入 D3。这将向 Arduino 发出解锁门的信号。

执行锁定的代码:

private async Task LockDoor()
{
   MultiPinConfig multiPinConfig = new MultiPinConfig();
   MultiPinConfig.AddPinState(DigitalPins.D0, DigitalStates.High); //Lock Signal 
   multiPinConfig.AddPinState(DigitalPins.D3, DigitalStates.Low); //Unlock Signal
  
   await myBolt.DigitalMultiWrite(multiPinConfig);
  
   multiPinConfig = new MultiPinConfig();
   multiPinConfig.AddPinState(DigitalPins.D0, DigitalStates.Low); //Lock Signal 
   multiPinConfig.AddPinState(DigitalPins.D3, DigitalStates.Low); //Unlock Signal
  
   await myBolt.DigitalMultiWrite(multiPinConfig);
}

执行解锁的代码:

private async Task UnlockDoor()
{
   MultiPinConfig multiPinConfig = new MultiPinConfig();
   multiPinConfig.AddPinState(DigitalPins.D0, DigitalStates.Low); //Lock Signal 
   multiPinConfig.AddPinState(DigitalPins.D3, DigitalStates.High); //Unlock Signal
  
   await myBolt.DigitalMultiWrite(multiPinConfig);
  
   multiPinConfig = new MultiPinConfig();
   multiPinConfig.AddPinState(DigitalPins.D0, DigitalStates.Low); //Lock Signal 
   multiPinConfig.AddPinState(DigitalPins.D3, DigitalStates.Low); //Unlock Signal
  
   await myBolt.DigitalMultiWrite(multiPinConfig);
}

2. 添加/删除可信面孔
可信人脸的图像数据被编码为 Base64 字符串,并存储在本地机器中。还存储了每个人脸的对应名称列表。在我们的程序中,要添加人脸,我们首先验证当前帧中是否有可用的人脸。我们使用FacePlusPlus的Detect API来执行此操作。它返回一个 JSON 响应,其中包含检测到的面部特征。如果没有检测到人脸,则响应将是[]。一旦检测到人脸,我们就会保存图像的 base64 编码字符串和相应的名称。

去除脸部非常简单。按删除按钮将从保存的列表中删除图像数据和名称。

添加和保存人脸信息的代码:

//Converting image to base64 string and adding it to the list. 
ImageDataList.Add(ImageToBase64((Image)PreviewBox.Image.Clone()));
//Adding name of the face to the list
NameList.Add(FaceNameTextBox.Text.Trim());
  
//Saves the face image data as a base encoded string, along with its name
Properties.Settings.Default.Base64ImageData = ImageDataList;
Properties.Settings.Default.FaceNames = NameList;
Properties.Settings.Default.Save();

删除人脸信息的代码:

//Removing face information at specified position in the list
NameList.RemoveAt(e.RowIndex);
ImageDataList.RemoveAt(e.RowIndex);
  
//Saving the the list after removal of a face
Properties.Settings.Default.FaceNames = NameList;
Properties.Settings.Default.Base64ImageData = ImageDataList;
Properties.Settings.Default.Save();

3.人脸验证
我们通过使用FacePlusPlus 中的比较 API来验证人脸是否可信。在此过程中,我们线性迭代保存列表中的每个人脸,并将其与捕获的图像进行比较。如果 API 返回超过 80% 的置信度,我们将解锁门。

进行此比较的代码如下所示:

WebClient client = new WebClient();
  
byte[] response = client.UploadValues("https://api-us.faceplusplus.com/facepp/v3/compare", new NameValueCollection()
{
    { "api_key", FPP_API_KEY },
    { "api_secret", FPP_API_SECRET },
    { "image_base64_1", face1Base64},
    { "image_base64_2", face2Base64}
    });
});
  
string confidence = JObject.Parse(System.Text.Encoding.UTF8.GetString(response))["confidence"].ToString();

4. 侦听铃声
我们计划提供一个物理按钮,类似于呼叫铃按钮,以便用户可以在看着摄像头时按下以解锁门。为了使这成为可能,我们需要创建一个新的专用线程来持续侦听铃声按钮按下事件。

在本文的后面,我们将看到如何使用按钮以及按下按钮时它将如何使 Bolt WiFi 模块HIGH的 D4 引脚。现在,我们只假设上述情况。所以在这个线程中,我们不断地计算 D4 引脚的值。如果是,我们将其作为铃声事件并进行人脸捕获和验证。DigitalReadHIGH

这是将在铃声侦听线程上连续运行的代码:

while (ListenForBell)
{
    Response R = await myBolt.DigitalRead(DigitalPins.D4);
    if (R.Value == "1")
    {
        RingBell_Click(null, null);
        Thread.Sleep(2000);
    }
    Thread.Sleep(2000);
}
我们在每次迭代之间停止并等待 2 秒。否则会很快耗尽 Bolt Cloud API 的使用配额。

第 2 步:构建 Visual Studio 项目
在 Visual Studio 中打开下方提供的文件。解决方案加载后,打开文件并使用您的 API 凭据更新代码。按名为“开始”的绿色播放按钮,构建并运行程序。 Facebolt Doorlock.slnForm1.cs

该程序允许您从连接到系统的摄像头设备中进行选择,并查看来自摄像头的实时信息。您可以添加/删除受信任的面孔。开始人脸监控。一旦程序验证了您的 Bolt 设备的连接性,您就可以直接从程序中按铃或锁门。

如果您现在对程序中人脸验证、锁定和解锁的工作方式感到困惑,没关系。一旦我们看到电路原理图设计和Arduino代码,就会变得更加清晰。最后,我还将分解每个操作的事件流。

第 3 步:电路设计和 Arduino 代码
在我们的电路中,我们打算实现以下功能:

  • 分别用于锁定和解锁门状态的红色和绿色 LED 指示灯。
  • 一个按钮,就像一个呼叫铃开关。按下时,我们的 WinForms 应用程序应验证面部并在成功进行面部身份验证后打开门。
  • 另一个按钮来锁门。
  • 在门铃响起和门锁时发出蜂鸣声的蜂鸣器。

我们项目的电路连接如下图所示:

在上传代码之前,请确保您已在 IDE 设置中设置了正确的 Arduino 模型和端口。

Arduino代码:

#include <Servo.h>
  
#define ServoPin 4
#define LockSignalPin 2
#define UnLockSignalPin 3
#define BellButtonPin 5
#define LockButtonPin 8
#define RingBellSignalPin 6
#define BuzzerPin 7
#define GreenLedPin 9
#define RedLedPin 10
  
Servo myServo;
  
void setup() 
{
    pinMode(LockSignalPin, INPUT);
    pinMode(UnLockSignalPin, INPUT);
    pinMode(BellButtonPin, INPUT);
    pinMode(LockButtonPin, INPUT);
  
    pinMode(BuzzerPin, OUTPUT);
    pinMode(RedLedPin, OUTPUT);
    pinMode(GreenLedPin, OUTPUT);
    pinMode(RingBellSignalPin, OUTPUT);
  
    digitalWrite(RedLedPin, LOW);
    digitalWrite(GreenLedPin, LOW);
    digitalWrite(RingBellSignalPin, LOW);
  
    myServo.attach(ServoPin);
    Serial.begin(9600);
}
  
void loop() 
{
    int lockButton, lock, unlock, bell;
    char snum[5];
  
    lock = digitalRead(LockSignalPin);
    unlock = digitalRead(UnLockSignalPin);
    
    // Check if lock signal from Bolt is HIGH
    if(lock == HIGH)
    {
        // Turn motor to locked position
        myServo.write(120);
        
        // Set LED indications
        digitalWrite(GreenLedPin, LOW);
        digitalWrite(RedLedPin, HIGH);
  
        // Buzz locking sound
        digitalWrite(BuzzerPin, HIGH);
        delay(1000);
        digitalWrite(BuzzerPin, LOW);
        delay(1000);
    }
    // Check if unlock signal from Bolt is HIGH
    else if(unlock == HIGH)
    {
        // Turn motor to unlocked position
        myServo.write(0);
        
        // Set LED indications
        digitalWrite(GreenLedPin, HIGH);
        digitalWrite(RedLedPin, LOW);
        delay(2000);
    }
  
    bell = digitalRead(BellButtonPin);
    if(bell == HIGH) // User pressed bell ring betton
    {
        // Signal Bolt that ring button was pressed
        digitalWrite(RingBellSignalPin, HIGH);
  
        // A calling bell sound pattern !
        digitalWrite(BuzzerPin, HIGH); 
        delay(100);
        digitalWrite(BuzzerPin, LOW);
        delay(20);
        digitalWrite(BuzzerPin, HIGH);
        delay(200);
        digitalWrite(BuzzerPin, LOW);
        delay(100);
        digitalWrite(BuzzerPin, HIGH);
        delay(100);
        digitalWrite(BuzzerPin, LOW);
        delay(20);
        digitalWrite(BuzzerPin, HIGH);
        delay(200);
        digitalWrite(BuzzerPin, LOW);
        delay(1500);
  
        // Turn off the signal
        digitalWrite(RingBellSignalPin, LOW);
    }
  
    lockButton = digitalRead(LockButtonPin);
    if(lockButton == HIGH) // User pressed lock betton
    {
        // Turn motor to locked position
        myServo.write(120);
        
        // Set LED indications
        digitalWrite(GreenLedPin, LOW);
        digitalWrite(RedLedPin, HIGH);
  
        // Buzz locking sound
        digitalWrite(BuzzerPin, HIGH);
        delay(1000);
        digitalWrite(BuzzerPin, LOW);
    }
}

事件流
现在我们已经准备好 WinForm 应用程序和 Arduino 设计,让我们深入研究代码并探索每个操作的控制流程。

1. 响铃按钮按下

2. 锁定按钮按下

上述两个操作也可以直接从 Windows 窗体应用程序执行。

在这里,我们可以观察到Bolt WiFi 模块作为 Windows 窗体应用程序和 Arduino 之间的重要无线接口。Bolt Cloud API 的使用使我们能够扩展我们的项目并在 Android 等其他平台上构建应用程序,并使用我们的手机解锁门!这种灵活性是物联网和 Bolt 平台的力量所在。

现在我们已经完成了软件设计部分,让我们继续构建一个可锁定的门机制。

第 4 步:构建硬件
我有一个鞋架,所以在这个项目中,我将用它来演示锁具。您可以使用架子、门或衣柜或任何具有可破解锁定机制的东西。

我们需要建立一个耦合机构,将我们的伺服电机与锁连接起来。为此,我的想法是使用一个瓶子和另一个瓶盖的截断颈部。将瓶颈连接到伺服电机,将盖子连接到锁上。然后我们将使用尼龙线将它们连接起来。每当电机转动时,这将导致锁定/解锁动作。

所需的瓶盖上钻有一个孔,如下图所示。我们将把它连接到鞋架的锁轴上。

另一个瓶子的盖子必须连接到伺服电机上。我们使用铜线将盖子连接到电机的转轴。

现在我们需要将这两者结合起来。为此,我们使用尼龙线。使用所需长度的线制作一个环,并将线连接到两个盖子上。

一旦耦合,它们可以引起相互旋转的动作:

现在我们已经准备好转动机构,是时候进入锁并修复我们的瓶颈了。我们在上面钻了一个孔,所以我们需要做的就是从机架上拧下锁轴,将瓶颈放在上面,然后重新拧紧锁。

现在唯一要做的就是将伺服电机固定在鞋架上。我们将使用热胶枪将电机密封到机架上。

调整好螺纹长度并充分拧紧后,我们就完成了最后的设置。如下图所示,伺服电机可以正确锁门和开锁!

不过,不一定必须使用瓶颈 - 螺纹耦合方法。你可以选择一个最适合和方便您的锁系统的任何方法。

幸运的是,我在机架的正确位置开了一个小口。这使我能够轻松地连接伺服电机。经过一些装饰工作和贴标后,我们最终的智能鞋架现已准备就绪。

我们现在都准备好了。剩下要做的就是启动电路,在 WinForms 应用程序上添加一个受信任的面孔,并享受我们门上的人脸锁安全性。您需要同时为 Arduino 和 Bolt WiFi 模块供电。我使用 10000 mA时的移动电源为他们俩供电。我使用的网络摄像头是 Microsoft LifeCam VX-800。它很旧,但仍然比笔记本电脑的相机好。

结论
该项目是由 Bolt IoT 提供支持的 Internshala 物联网培训的成果。虽然这个项目非常简单,但它向我们展示了物联网的潜力以及它如何让人们的日常生活更轻松。

本文中所用到的一些代码

如果您对此项目有任何想法、意见或问题,请在下方留言。

以上内容翻译自网络,原作者:Divins Mathew,如涉及侵权,可联系删除。

加入微信技术交流群

技术交流,职业进阶

关注与非网服务号

获取电子工程师福利

加入电路城 QQ 交流群

与技术大牛交朋友

讨论