【上海晶珩睿莓 1 开发板试用体验】智能门禁系统
本文介绍了上海晶珩睿莓 1 单板计算机结合 OpenCV 人脸识别和 PWM 舵机控制实现智能门禁系统的项目设计,包括硬件连接、舵机控制、人脸识别、网页前端设计、网页服务器设计、流程图、代码和效果演示等流程。
项目介绍
- 准备工作:硬件连接、OpenCV 安装、人脸识别模型、训练图像等;
- 舵机控制:PWM输出、转速和角度控制、代码、效果等;
- 门禁系统:文件目录、流程图、代码、效果等。
准备工作
包括硬件连接、虚拟环境创建、OpenCV 安装、模型获取、图像训练等。
硬件连接
- 连接 WiFi 实现无线网络通信;
- 使用 Micro-USB 数据线实现设备供电;

根据板载 40pin 引脚定义,驱动舵机使用支持 PWM 的物理引脚 7,对应GPIO 83;

将舵机的信号线与 GPIO83 连接,还有供电和接地
| Raspberry Pi |
SG90 |
Description |
|---|
| GPIO83 (Pin7) |
S (Yellow) |
Signal |
| 5V (Pin2) |
5V (Red) |
Power supply |
| GND (Pin6) |
GND (Brown) |
Ground |

OpenCV 安装
mkdir ~/cv && cd ~/cv
python3 -m venv venv
source venv/bin/activate
pip install -U pip numpy
pip install opencv-python opencv-contrib-python
python3 -c "import cv2,sys,numpy;print('OpenCV:',cv2.__version__,'NumPy:',numpy.__version__)"
详见:OpenCV .
人脸识别
OpenCV 注册并训练目标人脸,使用 YuNet 模型检测人脸,之后结合 sface 模型识别人脸。
详见:opencv_zoo/models/face_recognition_sface · GitHub .
模型获取
下载所需模型文件;
wget https://github.com/opencv/opencv_zoo/blob/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx
wget https://github.com/opencv/opencv_zoo/blob/main/models/face_recognition_sface/face_recognition_sface_2021dec.onnx
将文件存放在 ./model 路径
参考:SFace Recognition | Github .
训练图片
- 将目标人脸图片裁剪至合适大小;
- 文件名为对应的人名;
- 置于
./face 文件夹。

舵机控制
使用板载 40pin 引脚 GPIO,实现 4 相 8 拍步进电机驱动,并控制旋转速度和角度。
代码
终端执行指令 touch step_motor.py 新建程序文件,并添加如下代码
import subprocess
import time
GPIO_CHIP = "0"
MOTOR_PIN_1 = "83"
STEPS_PER_REV = 4096
def set_gpios_bulk(pin_states):
"""批量设置GPIO引脚状态"""
try:
cmd = ["gpioset", GPIO_CHIP]
for pin, state in pin_states:
cmd.append(f"{pin}={state}")
subprocess.run(
cmd,
check=True,
stderr=subprocess.PIPE,
stdout=subprocess.DEVNULL
)
return True
except subprocess.CalledProcessError as e:
print(f"GPIO控制错误: {e.stderr.decode().strip()}")
return False
except Exception as e:
print(f"设置GPIO时发生错误: {e}")
return False
def reset_motor_pins():
"""重置所有电机引脚为低电平"""
set_gpios_bulk([
(MOTOR_PIN_1, 0)
])
def setup_gpio():
"""初始化GPIO引脚"""
reset_motor_pins()
print("GPIO初始化完成")
def step_once(delay_ms=2):
"""执行一步,带可控延时"""
for seq in STEP_SEQUENCE:
set_gpios_bulk([
(MOTOR_PIN_1, seq[0])
])
time.sleep(delay_ms / 1000.0)
def rotate(angle: float, speed: float = 960):
"""
步进电机版 rotate
angle : 目标角度(°),正负决定方向
speed : 越大越快,单位 步/秒(约 960 对应 1 圈/4.3 s)
"""
steps = int(abs(angle) / 360.0 * STEPS_PER_REV)
delay = 1000.0 / speed
direction = 1 if angle > 0 else -1
for _ in range(steps):
seq = STEP_SEQUENCE if direction > 0 else reversed(STEP_SEQUENCE)
for s in seq:
set_gpios_bulk([
(MOTOR_PIN_1, s[0])
])
time.sleep(delay / 1000.0)
reset_motor_pins()
def door_cycle():
"""门控动作:开 90° → 停 3 s → 关 90°"""
rotate(90)
time.sleep(3)
rotate(-90)
if __name__ == "__main__":
setup_gpio()
door_cycle()
保存代码。
效果
终端执行指令 python servo360.py 90 舵机逆时针转动 90 度。
详见顶部视频。
门禁系统
在人脸识别和舵机控制的基础上,实现门禁系统的项目设计,包括文件目录、流程图、代码、效果演示等。
文件目录
~/AI/FaceRecognition $ tree
.
├── access.names
├── app.py
├── face
│ ├── Arnold.jpg
│ ├── Clarke.jpg
│ ├── Perry.jpg
│ └── Robert.jpg
├── model
│ ├── face_detection_yunet_2023mar.onnx
│ ├── face_recognition_sface_2021dec.onnx
│ └── face_registry.pkl
├── static
│ └── result.jpg
└── templates
└── index.html
流程图

代码
包含三个代码文件,./access.names 为白名单,./app.py 为 flask 服务器后端,``./templates/index.html` 为网页前端。
Flask 后端
终端执行 touch app.py 新建网页服务器后端程序文件,并添加如下代码
import os, cv2, numpy as np, pickle, time
from pathlib import Path
from flask import Flask, request, jsonify, render_template, url_for
import RPi.GPIO as GPIO
import threading
PIN_SERVO = 18
FREQ = 50
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN_SERVO, GPIO.OUT)
pwm = GPIO.PWM(PIN_SERVO, FREQ)
pwm.start(0)
ACCESS_LIST = set(line.strip() for line in open('access.names') if line.strip())
detector = cv2.FaceDetectorYN_create("model/face_detection_yunet_2023mar.onnx", "", (320, 320))
recognizer = cv2.FaceRecognizerSF_create("model/face_recognition_sface_2021dec.onnx", "")
registry = pickle.loads(Path("model/face_registry.pkl").read_bytes()) if Path("model/face_registry.pkl").exists() else {}
def rotate(angle, speed=480):
duty = 2.5 if angle > 0 else 12.5
pwm.ChangeDutyCycle(duty)
time.sleep(abs(angle) / speed)
pwm.ChangeDutyCycle(0)
def door_cycle():
rotate(90); time.sleep(3); rotate(-90)
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/upload', methods=['POST'])
def upload():
file = request.files['image']
img = cv2.imdecode(np.frombuffer(file.read(), np.uint8), cv2.IMREAD_COLOR)
h, w = img.shape[:2]
detector.setInputSize((w, h))
faces = detector.detect(img)[1]
name, score = "Unknown", 0.0
if faces is not None:
face = faces[0]
aligned = recognizer.alignCrop(img, face)
feat = recognizer.feature(aligned)
for reg_name, reg_feat in registry.items():
s = recognizer.match(feat, reg_feat, cv2.FaceRecognizerSF_FR_COSINE)
if s > score:
score, name = s, reg_name
if score < 0.3:
name = "Unknown"
if name != "Unknown" and name in ACCESS_LIST:
threading.Thread(target=door_cycle, daemon=True).start()
tip = f"{name} 请通行"
else:
tip = f"{name} 无权限,拒绝通行"
if faces is not None:
x, y, w_box, h_box = map(int, face[:4])
cv2.rectangle(img, (x, y), (x + w_box, y + h_box), (0, 255, 0), 2)
cv2.putText(img, f"{name}:{score:.2f}", (x, y - 6),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
out_path = "./static/result.jpg"
cv2.imwrite(out_path, img)
return jsonify(name=name, score=round(score, 3), tip=tip,
result_url=url_for('static', filename='result.jpg'))
import atexit
atexit.register(lambda: (pwm.stop(), GPIO.cleanup()))
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=False)
Web 前端
终端执行 touch ./templates/index.html 新建 HTML 前端网页程序,并添加如下代码
<!doctype html>
<html lang="zh">
<head>
<meta charset="utf-8">
<title>门禁</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
:root{
--accent:#00c853;
--danger:#ff1744;
--bg:#e3f2fd;
--card:rgba(255,255,255,.75);
--radius:16px;
--trans:.35s cubic-bezier(.4,0,.2,1)
}
body{margin:0;height:100vh;display:flex;align-items:center;justify-content:center;background:var(--bg);font-family:system-ui,Arial}
#card{width:320px;padding:32px 24px;background:var(--card);backdrop-filter:blur(12px);border-radius:var(--radius);box-shadow:0 8px 32px rgba(0,0,0,.1);text-align:center;transition:var(--trans)}
h2{margin:0 0 20px;font-size:22px;font-weight:600;color:#0d47a1}
input[type=file]{display:none}
label{display:inline-block;padding:10px 20px;border:2px dashed var(--accent);border-radius:var(--radius);cursor:pointer;color:var(--accent);transition:var(--trans)}
label:hover{background:var(--accent);color:#fff}
button{margin-top:16px;padding:10px 0;width:100%;border:none;border-radius:var(--radius);background:var(--accent);color:#fff;font-size:16px;cursor:pointer;transition:var(--trans);box-shadow:0 2px 8px rgba(0,200,83,.3)}
button:active{transform:scale(.97)}
.status{margin-top:18px;font-size:17px;height:24px;opacity:0;transition:var(--trans)}
.status.show{opacity:1}
.status.ok{color:var(--accent)}
.status.no{color:var(--danger)}
img{width:100%;border-radius:var(--radius);margin-top:16px;box-shadow:0 4px 16px rgba(0,0,0,.08);display:none}
</style>
</head>
<body>
<div id="card">
<h2>人脸识别门禁</h2>
<input type="file" id="f" accept="image/*">
<label for="f">选择照片</label>
<button onclick="up()">上传识别</button>
<div id="s" class="status"></div>
<img id="i">
</div>
<script>
async function up(){
const file=f.files[0];
if(!file)return alert('请选择图片');
s.className='status show';s.textContent='识别中…';
const fd=new FormData();fd.append('image',file);
const r=await(fetch('/upload',{method:'POST',body:fd}).then(x=>x.json()));
s.textContent=r.tip;
s.classList.toggle('ok',!r.tip.includes('拒绝'));
s.classList.toggle('no',r.tip.includes('拒绝'));
i.src=r.result_url+'?t='+Date.now();i.style.display='block';
setTimeout(()=>{s.textContent='已关门,等待识别';i.style.display='none'},3000)
}
</script>
</body>
</html>
白名单
终端执行 touch access.names 新建白名单文件,并添加人名列表
Linda
Edward
Clarke
保存代码。
效果
终端执行指令 python app_DC.py 运行程序;
终端打印 Web 服务器网址,如http://192.168.31.117:5000/ ;

浏览器打开服务器前端网页;
- 点击
选择文件 按钮,加载目标识别人脸;
- 点击
上传识别 按钮,立即显示识别结果、是否允许通行;


- 同时舵机逆时针转动,控制门禁档杆移动,表示允许通过;
- 待三秒钟后,舵机顺时针旋转 90 度,表示门禁关闭;
- 网页前端显示门禁已关闭,回到
等待识别 状态。

动态效果见底部视频。
总结
本文介绍了上海晶珩睿莓 1 单板计算机结合 OpenCV 人脸识别和 PWM 舵机控制实现智能门禁系统的项目设计,包括环境部署、预训练模型获取、关键代码、板端推理、效果演示等流程,为相关产品在边缘 AI 领域的快速开发和应用设计提供了参考。