智能门禁系统实战:集成cv_resnet101_face-detection与STM32的硬件方案
智能门禁系统实战:集成cv_resnet101_face-detection与STM32的硬件方案
最近在捣鼓一个挺有意思的小项目:用一块小小的STM32开发板,加上一个普通的摄像头,再结合云端的人脸识别模型,自己动手做一个智能门禁的原型系统。听起来是不是有点复杂?其实拆解开来,每一步都挺清晰的。
这个想法的核心很简单:让门禁系统能“认人”。传统的门禁要么刷卡,要么输密码,要么按指纹,总归需要你主动去操作一下。而智能门禁的理想状态是,你走到门前,它看一眼就知道是你,然后自动开门,整个过程自然又流畅。要实现这个“看一眼”,就需要把嵌入式硬件和AI能力结合起来。STM32负责“眼睛”(采集图像)和“手脚”(控制门锁),而复杂的“大脑”(人脸识别)则交给云端更强大的模型来处理。
今天,我就把自己搭建这个原型系统的整个过程、踩过的坑以及最终跑通的方案,详细地分享出来。如果你也对物联网、嵌入式AI应用感兴趣,希望这篇内容能给你带来一些实实在在的参考。
1. 系统整体设计思路:让硬件与AI对话
在开始动手焊接电路或写代码之前,我们得先想清楚整个系统是怎么跑起来的。你不能指望让STM32这块单片机自己去运行庞大的人脸识别模型,这不现实。它的算力和内存都有限。所以,我们的策略是“分工协作”。
核心思路是:边缘采集,云端推理。 我把这个系统的运行流程画成了下面这张图,你可以先有个直观的印象:
[STM32 + 摄像头] --(拍摄图片)--> [本地预处理] --(发送图片)--> [星图GPU云平台]
|
[控制门锁/显示] <--(接收结果)-- [STM32] <--(返回识别结果)-- [人脸识别模型]
简单来说,STM32和摄像头扮演“前线侦察兵”的角色。它们负责在现场捕捉图像,然后通过网络把“情报”(图片数据)发送给后方的“指挥中心”——也就是部署在云端GPU服务器上的cv_resnet101_face-detection模型。这个“指挥中心”拥有强大的分析能力,它能快速判断图片里有没有人脸、是谁的脸,然后把“识别结果”这个指令回传给前线的STM32。STM32收到指令后,再决定是开门、报警还是提示认证失败。
这样做的好处很明显:STM32只需要完成它擅长的实时控制、数据采集和通信任务,而复杂的AI计算则交给了性能强劲、专门优化的云端环境。两者通过网络各司其职,共同完成一个复杂的智能任务。
2. 硬件选型与搭建:精打细算的“侦察兵”
确定了思路,接下来就得准备“侦察兵”的装备了。硬件选型不求最贵,但求合适、够用且性价比高。
2.1 核心主控:STM32F103C8T6
我选择了经典的STM32F103C8T6,也就是大家常说的“蓝色药丸”或“最小系统板”。选它的理由很充分:
- 性价比极高:价格非常亲民,适合学习和原型开发。
- 资源足够:72MHz主频,64KB Flash,20KB RAM。对于运行一个轻量级的网络协议栈、控制摄像头采集和驱动外设来说,完全够用。
- 生态丰富:资料、教程、社区支持都非常多,遇到问题容易找到解决方案。
- 接口齐全:拥有USART、SPI、I2C等常用通信接口,方便连接各种模块。
2.2 图像采集:OV2640摄像头模块
为了让系统能“看见”,我选用的是OV2640摄像头模块。它是一款200万像素的传感器,输出图像质量对于人脸识别来说足够了。更重要的是,它支持DVP并行接口和SCCB(类似I2C)配置总线,与STM32的连接和驱动相对成熟。
硬件连接示意:
- DVP数据/控制线:连接至STM32的GPIO口,用于传输像素数据和行场同步信号。
- SCCB总线:连接至STM32的I2C1(PB6, PB7),用于配置摄像头参数(如分辨率、曝光、输出格式)。
- 电源:模块通常需要3.3V和1.8V(或2.8V)两组电压,开发板上的3.3V和LDO可以解决。
2.3 网络通信:ESP-01S WiFi模块
STM32F103本身没有网络功能,所以我们需要一个“传令兵”来负责联网。ESP-01S WiFi模块是基于ESP8266芯片的,体积小、价格低,可以通过AT指令集与STM32进行串口通信,实现联网和数据传输。
连接非常简单:
- 串口连接:ESP-01S的
TX/RX连接到STM32的USART2(PA2, PA3)。 - 电源与使能:
VCC接3.3V,CH_PD和GPIO0接高电平,RST可接STM32的GPIO以便软件复位。
2.4 其他外围设备
- 门锁模拟:用一个5V继电器模块来模拟电磁锁。STM32通过一个GPIO口控制继电器的通断,从而模拟开门动作。
- 反馈指示:用了几个LED灯(红、绿、蓝)和一个小型OLED显示屏(I2C接口)。LED用于快速状态指示(如识别中、识别成功、识别失败),OLED屏可以显示更详细的信息(如“识别中...”、“欢迎,张三”)。
- 电源:整个系统可以用一个5V/2A的USB电源供电,通过开发板的稳压电路为各模块提供3.3V。
把这些模块在面包板上连接好,你的硬件“侦察兵”就初步成型了。
3. 软件与通信设计:打通任督二脉
硬件是躯体,软件是灵魂。这部分的工作就是让各个模块活起来,并学会如何与云端“对话”。
3.1 STM32端软件框架
在STM32上,我使用HAL库进行开发,程序主要跑在一个简单的前后台(超级循环) 系统中,关键任务通过状态机来管理。
核心任务流程如下:
- 初始化:上电后,初始化系统时钟、GPIO、USART(用于ESP-01S)、I2C(用于OV2640和OLED)、SPI等外设。
- 摄像头配置:通过I2C(SCCB)向OV2640写入一系列寄存器值,将其配置为输出
320x240或640x480分辨率的JPEG图像。为什么是JPEG?因为它的压缩率高,能极大减少网络传输的数据量。 - WiFi联网:通过USART向ESP-01S发送一系列AT指令,例如:
AT+CWMODE=1 // 设置为Station模式 AT+CWJAP="SSID","PASSWORD" // 连接WiFi AT+CIPSTART="TCP","your_server_ip",80 // 连接云服务器 - 主循环:
- 图像捕获:等待OV2640的帧中断,将一帧JPEG数据从DVP接口读取到STM32的缓冲区。由于内存有限,一帧数据可能需要分块处理。
- 图像预处理:这里可以做最简单的处理,比如在内存中检查JPEG数据的头尾,确保数据完整。更复杂的处理(如缩放、格式转换)可以放在云端。
- 组包与发送:将JPEG数据按照自定义的简单协议打包。例如,协议帧可以设计为:
[帧头][数据长度][图像数据][校验和]。然后通过串口指令让ESP-01S以TCP方式发送给云服务器。
// 示例:通过AT指令发送数据 sprintf(cmd, "AT+CIPSEND=%d", data_length); uart_send(esp_uart, cmd); // 发送数据长度指令 wait_for_esp_response(">"); // 等待模块提示可以发送数据 uart_send_raw(esp_uart, jpeg_data, data_length); // 发送JPEG数据- 等待与接收:发送完成后,等待ESP-01S返回云服务器的响应。响应内容应该是一个简单的JSON或自定义格式的字符串,例如:
{"status":"success", "result":"recognized", "name":"ZhangSan"}或{"status":"success", "result":"unknown"}。 - 结果处理:解析响应数据。根据
result字段,控制继电器模拟开门(识别成功),或让红灯闪烁、OLED显示“未知人员”(识别失败)。
3.2 云端API服务搭建
云端部分,我们需要一个“中间人”服务。它接收STM32发来的图片,调用人脸识别模型,再把结果返回。我选择用Python的Flask框架快速搭建一个RESTful API。
这个API服务主要做三件事:
- 接收图片:提供一个HTTP POST接口(比如
/face_recognition),接收STM32上传的JPEG二进制数据。 - 调用模型:将收到的图片数据,传递给部署好的
cv_resnet101_face-detection模型进行推理。这里假设模型已经部署在星图GPU平台上,并提供了Python调用接口。 - 返回结果:将模型的识别结果(是否有人脸、是谁)封装成JSON格式,返回给STM32。
一个极简的示例代码:
from flask import Flask, request, jsonify
import cv2
import numpy as np
# 假设这是从星图平台获得的模型调用客户端
from your_model_client import FaceDetectionClient
app = Flask(__name__)
model_client = FaceDetectionClient() # 初始化模型客户端
@app.route('/face_recognition', methods=['POST'])
def face_recognition():
try:
# 1. 接收图片
image_data = request.data
if not image_data:
return jsonify({'status': 'error', 'message': 'No image data'}), 400
# 2. 将二进制数据转为OpenCV格式
nparr = np.frombuffer(image_data, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
# 3. 调用人脸识别模型
# 这里调用星图平台上的cv_resnet101_face-detection模型
# 模型返回的可能是人脸框坐标、特征向量或直接是识别出的标签
result = model_client.predict(img)
# 4. 处理结果。假设模型返回一个标签列表,为空则表示未识别
if result and result['faces']:
# 这里简化处理,取第一个识别出的人脸标签
recognized_name = result['faces'][0]['label']
if recognized_name != 'unknown':
return jsonify({'status': 'success', 'result': 'recognized', 'name': recognized_name})
else:
return jsonify({'status': 'success', 'result': 'unknown'})
else:
return jsonify({'status': 'success', 'result': 'no_face'})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
3.3 通信协议与数据格式
为了保证通信的可靠性,设计一个简单的应用层协议很重要。
- STM32 -> 云端:可以是一个简单的二进制帧,包含帧头(如0xAA, 0xBB)、图像数据长度(2字节)、JPEG数据本身、以及一个CRC8校验和。云端服务接收到后,先校验,再提取JPEG数据。
- 云端 -> STM32:建议使用JSON格式的字符串。它结构清晰,易于STM32端解析(可以使用轻量级的解析库如
jsmn)。内容包含状态、识别结果、人员姓名等关键信息。
4. 模型集成与业务逻辑:云端“大脑”的思考
cv_resnet101_face-detection模型主要负责在图片中定位并识别人脸。在星图GPU平台上部署好该模型后,我们的API服务会调用它。
一个典型的集成与处理流程:
- 人脸检测:模型首先在图片中找出所有人脸的位置(边界框)。如果没找到人脸,直接返回“no_face”。
- 人脸对齐与裁剪:根据检测到的人脸框,将每张人脸裁剪出来,并进行标准化处理(如缩放、归一化),为识别做准备。
- 特征提取与比对:模型会为每张标准化后的人脸提取一个高维特征向量。将这个特征向量与预先注册在数据库中的人脸特征库进行比对(计算余弦相似度或欧氏距离)。
- 决策与返回:如果比对结果中,有某个特征向量的相似度超过设定的阈值(比如0.7),则认为识别成功,返回对应的人员ID或姓名。否则,返回“unknown”。
对于STM32端,业务逻辑就基于云端的返回结果:
result: "recognized":驱动继电器动作(模拟开门),绿灯亮,OLED显示欢迎信息。result: "unknown":红灯闪烁,OLED显示“陌生人警告”,可考虑触发蜂鸣器。result: "no_face":蓝灯闪烁,表示正在等待检测目标。status: "error":黄灯闪烁,OLED显示“网络或服务器错误”。
5. 原型测试与效果展示
把所有代码烧录进去,硬件连接检查无误后,就可以上电测试了。
测试过程:
- 上电初始化:OLED屏幕显示“系统启动中...”,随后WiFi连接成功,显示服务器IP。
- 待机状态:蓝灯慢闪,OLED显示“等待识别...”。
- 人脸识别:
- 将摄像头对准已注册的人员。STM32的指示灯会快速闪烁几下(表示正在采集和发送数据),稍等片刻(网络延迟+云端推理时间),绿灯常亮,继电器“咔哒”一声吸合,OLED显示“欢迎,张三”。
- 将摄像头对准未注册的人员或遮挡面部。红灯闪烁,OLED显示“识别失败”,继电器无动作。
- 压力测试:尝试在不同光照条件下、以不同角度进行测试,观察识别成功率。同时,可以模拟网络不稳定的情况,看系统是否有超时重传等容错机制。
从实际测试来看,这个原型系统基本实现了预期的功能。识别速度主要受限于网络延迟和云端模型推理时间,STM32本地的图像采集和发送开销其实很小。对于实时性要求不是极端高的门禁场景(比如家庭、办公室),这个延迟(通常在1-3秒内)是可以接受的。
6. 总结与思考
折腾完这个项目,感觉就像完成了一次小小的系统集成挑战。它涉及了嵌入式硬件驱动、网络通信、服务器编程和AI模型调用多个环节。虽然只是一个原型,但把想法变成能跑起来的东西,这个过程本身就很有收获。
用STM32这类微控制器去做需要复杂AI能力的应用,“边缘采集+云端推理” 是一个非常务实且高效的架构。它让硬件成本大幅降低,开发难度也集中在通信和业务逻辑整合上,而不是去死磕如何在资源受限的设备上部署大模型。
当然,这个原型还有很多可以优化和改进的地方。比如,可以增加本地的人脸检测(轻量级模型),只有检测到人脸后才上传,节省流量;可以优化通信协议,加入心跳包和重传机制,提升稳定性;可以在云端加入活体检测功能,防止照片攻击。
如果你也想尝试类似的项目,我的建议是分步实现,逐个击破。先搞定STM32驱动摄像头并输出JPEG,再实现WiFi联网和TCP通信,然后搭建最简单的云端回声服务,最后再集成复杂的人脸识别模型。每一步都测试通了,整个系统就跑起来了。希望这个分享能为你提供一条可行的路径。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)