news 2026/5/6 10:19:33

基于树莓派4b的安防门禁系统从零实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于树莓派4b的安防门禁系统从零实现

从零打造智能门禁:树莓派4B + 人脸识别实战全记录

最近在折腾一个让我既兴奋又头疼的小项目——用一块树莓派4B,搭一套能“认脸开门”的智能门禁系统。听起来像是科技公司的产品?其实成本不到500块,代码全是自己写的,硬件也是淘宝拼凑的。今天就来分享下这个DIY全过程,不讲空话套话,只聊真实踩过的坑、调过的参数、跑得动的代码


为什么是树莓派4B?

市面上做嵌入式开发的板子不少,Nano、ESP32也能跑基础逻辑,但要做实时人脸识别+网络服务+远程访问这一整套闭环,还得靠性能在线的平台。

我最终选了Raspberry Pi 4 Model B(8GB内存版),原因很实际:

关键指标树莓派4B表现实际意义
CPU四核Cortex-A72 @1.5GHz能跑轻量级深度学习模型
内存最高8GB LPDDR4多任务不卡顿,缓存视频流更稳
视频输入CSI-2接口 + 支持USB摄像头可接官方摄像头,低延迟采集
网络千兆以太网 + 双频Wi-Fi远程推流不断连
GPIO40针通用引脚控制继电器毫无压力

坦白说,如果你打算做个“按按钮开灯”级别的小玩具,树莓派有点杀鸡用牛刀。但一旦涉及图像处理+联网+本地决策,它几乎是目前性价比最高的选择。

更重要的是——社区资源太丰富了。OpenCV、PyTorch都能装,GitHub上随便一搜就是成堆的参考项目。省下的时间,够你多调试三轮算法。


核心技术拆解:人脸怎么“看懂”你是谁?

整个系统的灵魂当然是人脸识别。很多人一听就觉得高深莫测,其实现在开源工具链已经非常成熟,关键在于如何让它在树莓派这种边缘设备上跑得快、认得准

我的技术路线:MTCNN + FaceNet 组合拳

没有用什么商业SDK,全部基于facenet_pytorch库实现,两个核心组件:

  1. MTCNN:负责从画面中“找脸”
  2. InceptionResnetV1(FaceNet变体):把脸变成一串数字特征向量

这套组合的好处是:
- 模型小(<100MB),适合部署
- 准确率高,在LFW数据集上能达到99%+
- PyTorch支持良好,推理过程可控性强

实战代码优化版(亲测可用)

下面这段是我最终定稿的人脸识别函数,比原生示例更稳定,加了置信度过滤和异常处理:

import cv2 import torch import numpy as np from facenet_pytorch import MTCNN, InceptionResnetV1 # 自动检测是否可用CUDA(虽然Pi没有GPU,但保持结构统一) device = 'cpu' # Raspberry Pi无独立GPU mtcnn = MTCNN(keep_all=True, thresholds=[0.6, 0.7, 0.7], device=device) resnet = InceptionResnetV1(pretrained='vggface2').eval().to(device) # 加载已注册用户的特征库 registered_embeddings = { "张三": np.load("embeddings/zhangsan.npy"), "李四": np.load("embeddings/lisi.npy") } def recognize_face(frame): """ 输入BGR图像帧,返回是否匹配成功及姓名 """ boxes, probs = mtcnn.detect(frame) if boxes is None: return False, None for box, prob in zip(boxes, probs): if prob < 0.8: # 置信度太低直接跳过 continue x1, y1, x2, y2 = [int(b) for b in box] face_img = frame[y1:y2, x1:x2] try: face_tensor = mtcnn.preprocess(frame, box).unsqueeze(0).to(device) with torch.no_grad(): embedding = resnet(face_tensor).cpu().numpy() except Exception as e: print(f"特征提取失败: {e}") continue # 计算欧氏距离(越小越相似) min_distance = float('inf') matched_name = "未知" for name, saved_emb in registered_embeddings.items(): dist = np.linalg.norm(embedding - saved_emb) if dist < min_distance: min_distance = dist # 设定阈值(根据训练数据调整,一般0.8~1.0之间) if min_distance < 0.9: matched_name = list(registered_embeddings.keys())[ list(np.linalg.norm(embedding - v) for v in registered_embeddings.values()).index(min_distance) ] # 绘制框和标签 color = (0, 255, 0) if matched_name != "未知" else (0, 0, 255) cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2) cv2.putText(frame, f"{matched_name} ({min_distance:.2f})", (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2) if matched_name != "未知": return True, matched_name return False, None

💡经验贴士
- 阈值0.9是我通过测试几百张正脸/侧脸样本调出来的平衡点,太低会误识别,太高则熟人也进不来。
- 摄像头尽量固定位置,避免逆光或强阴影影响识别稳定性。
- 建议每人注册至少3张不同光照条件下的照片生成特征向量取平均。


如何让“识别结果”真正控制门锁?GPIO实战详解

识别出来了,接下来就得动手——怎么让软件判断变成物理世界的“咔哒”一声开门?

答案就是:GPIO + 继电器模块

硬件连接要点

我用的是常见的5V继电器模块(某宝十几块钱),接线如下:

树莓派GPIO接继电器端口说明
Pin 18 (BCM 18)IN控制信号输入
Pin 6 (GND)GND共地
继电器COM12V电源正极主回路接入点
继电器NO电磁锁正极常开触点,通电闭合
电磁锁负极接12V电源负极构成完整回路

⚠️重要提醒:电磁锁工作电压通常是12V,绝对不能直接接到树莓派!必须通过继电器隔离,否则轻则烧IO口,重则主板报废。

控制代码封装成可靠函数

别小看这一步,我第一次写完就忘了清理GPIO,重启后发现继电器一直吸合……差点把锁烧了。

改进后的安全版本:

import RPi.GPIO as GPIO import time RELAY_PIN = 18 GPIO.setmode(GPIO.BCM) GPIO.setup(RELAY_PIN, GPIO.OUT) GPIO.output(RELAY_PIN, GPIO.LOW) # 初始状态断开 def unlock_door(duration=3): """ 打开门锁 duration 秒后自动关闭 """ try: GPIO.output(RELAY_PIN, GPIO.HIGH) print(f"[{time.strftime('%H:%M:%S')}] 门已开启") time.sleep(duration) GPIO.output(RELAY_PIN, GPIO.LOW) print(f"[{time.strftime('%H:%M:%S')}] 门已关闭") except Exception as e: print(f"开门过程中出错: {e}") finally: pass # 不在此处 cleanup,防止其他线程受影响 # 使用示例 if __name__ == "__main__": try: unlock_door(5) finally: GPIO.cleanup() # 程序退出时释放资源

这个duration=3很关键——没人希望门一直开着。3秒足够进出,又能防尾随。


能不能不在现场也能开门?远程访问怎么搞?

设想一下:朋友来访你不在家,能不能手机一点,“滴”,门开了?

完全可以。我在树莓派上起了一个轻量级 Web 服务,前端用 HTML + JS 做了个简易面板,功能包括:

  • 查看实时画面(MJPG-Streamer 推流)
  • 点击按钮远程开门
  • 查询最近10条出入记录
  • 异常报警微信通知(后面讲)

Flask 服务最小可行实现

考虑到安全性,这里只暴露必要接口,并加入简单 token 验证:

from flask import Flask, jsonify, request import threading import logging app = Flask(__name__) SECRET_TOKEN = "your_very_secret_token_here" # 替换为你自己的密钥 is_locked = True @app.route('/status') def get_status(): return jsonify({ "locked": is_locked, "timestamp": time.time() }) @app.route('/unlock', methods=['POST']) def remote_unlock(): token = request.headers.get('X-Auth-Token') if token != SECRET_TOKEN: return jsonify({"success": False, "message": "认证失败"}), 403 global is_locked unlock_door(3) is_locked = False return jsonify({"success": True, "message": "门已开启"}) # 启动Web服务(单独线程) def start_web_server(): logging.basicConfig(level=logging.WARNING) app.run(host='0.0.0.0', port=8080, threaded=True) web_thread = threading.Thread(target=start_web_server) web_thread.daemon = True web_thread.start()

然后通过 Nginx 反向代理 + Let’s Encrypt 证书实现 HTTPS,再配合花生壳之类的动态DNS,外网就能安全访问了。

🔐安全建议
- 不要用默认端口80/443,容易被扫描
- 加IP白名单或登录页面更好
- Token定期更换


完整系统是如何运转的?

把所有模块串起来,整个流程就像一条流水线:

[摄像头] → [人脸检测] → [特征提取] → [比对数据库] → ↓(匹配成功) ↓(失败多次) [触发GPIO开锁] [记录日志 + 可选报警] ↓ [更新状态 → Web界面可见]

主循环伪代码大致如下:

cap = cv2.VideoCapture(0) # 或使用 picamera2 while True: ret, frame = cap.read() if not ret: continue success, name = recognize_face(frame) if success: log_access(name, success=True) unlock_door(3) send_welcome_message(name) # 如语音播放“欢迎回家” # 显示画面(调试用) cv2.imshow('Door Access System', frame) if cv2.waitKey(1) == ord('q'): break cap.release() cv2.destroyAllWindows()

实际部署中的那些“坑”

理论美好,落地才见真章。以下是几个血泪教训:

1. 电源问题最致命

一开始图省事,用同一个5V电源给树莓派和继电器供电,结果一启动继电器,树莓派直接重启——电压跌落严重

✅ 解决方案:树莓派用专用5V/3A适配器,继电器和电磁锁另接12V/2A稳压电源,共地但不共电。

2. 摄像头角度决定识别率

装太高,拍到头顶;装太低,下巴都看不见。反复调试后发现:

最佳安装高度:1.6米左右,俯角10°~15°,人脸基本正对镜头。

3. 特征库要多样化

只用一张正面照注册?那遇到戴帽子、眼镜、晚上光线差的情况,基本就歇菜了。

✅ 建议每人录入5张以上:白天/夜晚、戴镜/不戴镜、微笑/自然表情。

4. 日志一定要持久化

系统运行几天后想查谁什么时候进来过?没做日志等于瞎子。

✅ 用 SQLite 存每条识别事件:

CREATE TABLE access_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, success BOOLEAN, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP );

总结:这不是玩具,而是可用的解决方案

做完这套系统我才意识到,真正的智能不是炫技,而是解决问题

它帮我解决了几个实实在在的问题:

  • 不用带钥匙,刷脸进门,下雨天单手拎包也能进
  • 临时访客来了,手机一点就能放行
  • 有人半夜强行撬门?连续识别失败立刻发微信告警
  • 所有出入都有记录,再也不用猜“到底是谁忘关门”

未来我还计划升级的方向:

  • 接入 Home Assistant,实现“回家模式”自动开灯拉窗帘
  • 用 TensorFlow Lite + Coral USB Accelerator 加速推理
  • 添加语音提示:“您好,张三,门已为您打开”
  • 结合温湿度传感器,做一个多功能门口机

如果你也在考虑做个属于自己的智能门禁,不妨从这块小小的树莓派开始。
代码我已经整理好放在 GitHub,硬件清单也不超过500元。

技术不该只是大厂的专利,每个人都可以亲手构建自己想要的生活方式。

👉 想要完整项目代码或遇到具体问题?欢迎留言交流,一起完善这个“家门口的AI守卫”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 11:16:23

语义分割全流程:TensorFlow U-Net实现

语义分割全流程&#xff1a;TensorFlow U-Net实现 在自动驾驶系统中&#xff0c;准确识别道路边缘、行人和障碍物是安全决策的前提&#xff1b;在医学影像诊断里&#xff0c;肿瘤区域的像素级勾画直接影响治疗方案的制定。这些任务背后&#xff0c;都依赖于同一种核心技术——图…

作者头像 李华
网站建设 2026/5/1 9:59:17

数据增强技巧:TensorFlow图像预处理流水线

数据增强技巧&#xff1a;TensorFlow图像预处理流水线 在深度学习驱动的计算机视觉项目中&#xff0c;一个常见的瓶颈并非模型结构本身&#xff0c;而是数据供给的质量与效率。我们常常遇到这样的场景&#xff1a;训练刚开始&#xff0c;GPU 利用率却始终徘徊在30%以下——问题…

作者头像 李华
网站建设 2026/5/5 0:33:22

RakNet目录差异传输技术:智能文件同步的革命性解决方案

RakNet目录差异传输技术&#xff1a;智能文件同步的革命性解决方案 【免费下载链接】RakNet 项目地址: https://gitcode.com/gh_mirrors/rak/RakNet 在当今多玩家游戏和分布式应用开发中&#xff0c;文件同步和资源更新已成为关键挑战。RakNet的DirectoryDeltaTransfer…

作者头像 李华
网站建设 2026/5/3 10:32:59

云美广告公司管理系统的设计与实现开题报告

本科毕业设计开题报告云美广告公司管理系统的设计与实现 学生姓名&#xff1a; xx 学 号&#xff1a; xx 专 业&#xff1a; 计算机科学与技术 指导教师&#xff1a; 尤菲菲 讲师 1.研究现状及意义当前&#xff0c;广告行业…

作者头像 李华
网站建设 2026/5/1 7:33:39

0成本搭建!20分钟用 Workers AI + Vectorize 搞定 RAG(附全套源码)

引言 想给公司做个智能客服&#xff0c;查了一圈 RAG 教程&#xff0c;要么讲理论云里雾里&#xff0c;要么让你先租个 GPU、搭环境&#xff0c;看着就头大。说实话&#xff0c;我刚开始研究这块的时候也一样&#xff0c;光是配置 LangChain 和向量数据库就折腾了两天&#xf…

作者头像 李华
网站建设 2026/5/1 3:35:33

Frappe Framework实战宝典:从零开始构建企业级应用全攻略

Frappe Framework实战宝典&#xff1a;从零开始构建企业级应用全攻略 【免费下载链接】frappe frappe/frappe: Frappe 是一套全面的Web应用程序开发框架&#xff0c;基于Python和MariaDB数据库&#xff0c;主要用于创建ERP系统和其他企业级应用。其核心产品包括ERPNext&#xf…

作者头像 李华