ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

树莓派 OpenCV 人脸识别全流程实战:从环境搭建到 LBPH 模型训练与性能调优

树莓派 OpenCV 人脸识别全流程实战:从环境搭建到 LBPH 模型训练与性能调优

做树莓派上的视觉项目,人脸识别基本上是最绕不开的一个。我最初入坑就是在树莓派 4B 上跑 OpenCV-Python 做人脸检测,后来逐步升级到完整的人脸识别、人脸比对和简单的门禁逻辑。这套东西看起来已经被写烂了,但实际动手过程中,坑比教程多得多。光一个“能不能在树莓派上流畅跑起来”就能劝退不少人,更别说不同摄像头、不同光照、不同版本库之间互相打架的问题。这篇内容,我就把从零搭建到最终跑通全流程的经验整理出来,包括选型思路、环境配置、采集样本、模型训练、实时识别和提速优化,每一步都给出可以直接复用的代码和命令。

1. 整体设计与方案选型思路

1.1 为什么选树莓派 + OpenCV-Python 组合

树莓派这类卡片电脑最大的优势是便宜、低功耗、体积小、够折腾。一块小小的板子加上摄像头模块就能组成一套独立的视觉终端,放在门口做门禁、放在桌面做考勤、装在车模上做跟随,场景非常灵活。相比直接用笔记本电脑或云服务器上跑识别,树莓派方案的核心价值在于:本地算、低功耗、数据不出局域网,尤其适合原型验证和产品雏形阶段。

OpenCV-Python 之所以是首选,不是因为它精度最高,而是因为它生态最成熟。人脸检测用自带的 Haar 特征级联分类器,人脸识别用 LBPH 算法,两者加起来不超过两百行代码就能跑通。对于想快速出结果、又想理解视觉处理底层逻辑的人来说,这套技术栈非常合适。

不过需要提前说清楚一个事实:树莓派的 CPU 并行能力非常有限。真正适合跑深度学习人脸识别的方案是带 NPU 的边缘设备,比如各类 AI 开发板。但树莓派的优势在于“通用计算 + OpenCV + 便宜好买”,配合合理优化,LBPH 这种传统机器学习算法的实时识别完全可以做到。

1.2 人脸检测 vs 人脸识别的概念边界

做项目之前,必须分清两个概念:人脸检测(Face Detection)和人脸识别(Face Recognition)。

人脸检测负责回答“画面里有没有人脸、脸在哪里”,输出的是人脸的矩形框坐标。OpenCV 中的detectMultiScale就是干这件事的,原理是遍历图像的多个尺度,用训练好的级联分类器判断某个区域是否是人脸。

人脸识别则负责回答“这张脸是谁”,通常分为两步:先提取人脸区域的特征向量,再用分类器判别身份。LBPH(Local Binary Pattern Histogram,局部二值模式直方图)算法把每个人的面孔转换成一组特征直方图,识别时计算当前人脸直方图与已训练直方图之间的相似度。

这两个概念很多人混着用,结果训练时总拿整张图去训练,识别率自然惨不忍睹。正确的流程一定是:检测出人脸 -> 裁剪出人脸区域 -> 灰度化 + 统一尺寸 -> 送入训练器或识别器。

1.3 人脸识别算法选型:LBPH 是树莓派最优解

目前 OpenCV 中内置的人脸识别算法有三类:EigenFaces(特征脸)、FisherFaces(线性判别分析)、LBPH(局部二值模式)。三者的适用场景完全不同,如下表所示:

算法原理特点对光照敏感性实时性树莓派上推荐度
EigenFaces将人脸投影到特征脸空间非常敏感中低
FisherFaces考虑类间离散度,降维分类较敏感中低
LBPH提取局部纹理特征的直方图统计相对鲁棒高高

我以前先试过 EigenFaces 和 FisherFaces,在树莓派上跑出来的效果很一般。原因很简单:这两种算法都依赖像素级的全局结构,光照变化后整个人脸在像素空间的分布彻底偏移,识别率断崖式下跌。而 LBPH 关注的是每个像素与其邻域的局部关系,通过比较像素相对大小来编码纹理特征,同一张脸在不同光照条件下局部纹理相对稳定。

LBPH 另一个优势是阈值可调。训练完之后可以设定一个距离阈值,低于阈值才算匹配成功,这样陌生人会被直接挡在外面,而不是强行归类到某个人的标签下。这套机制做门禁、考勤这类场景时特别好用,因为现实场景中总有不是训练集里任何一个人的外人。

2. 环境搭建与基础原理

2.1 树莓派系统与基础环境准备

树莓派上做 OpenCV 开发,系统首选 Raspberry Pi OS(Bookworm 版本或旧版 Bullseye 均可)。除非有特殊需求,不建议用 64 位系统镜像以外的版本,因为很多依赖库对 64 位环境兼容性更好。

拿到系统后,第一步建议先把系统源更新好:

sudo apt update sudo apt upgrade -y

然后是安装一些后续编译、运行过程中必要的基础依赖。如果直接用 pip 安装预编译的 wheel 包,一般不需要自己编译 OpenCV,但摄像头和图像处理相关的底层库还是要装齐:

sudo apt install -y libatlas-base-dev libhdf5-dev libhdf5-serial-dev sudo apt install -y libjpeg-dev libtiff5-dev libjasper-dev libpng-dev sudo apt install -y libavcodec-dev libavformat-dev libswscale-dev libv4l-dev sudo apt install -y libgtk2.0-dev libcanberra-gtk-module libqtgui4

这里有个很常见的坑:libjasper-dev和libqtgui4在较新的系统源里可能找不到,安装时报 “Unable to locate package”,解决办法是把libjasper-dev换成libjasper2(如果存在),或者直接跳过这两个包,影响不大。装不上就别死磕,后续功能受限的只是 GUI 显示相关的扩展。

2.2 OpenCV-Python 安装的两条路径

树莓派上安装 OpenCV-Python 有两条典型路径:pip 安装预编译包,或者源码编译。

pip 安装是最快的:

pip3 install opencv-python pip3 install opencv-contrib-python

注意树莓派的 ARM 架构下,老版本镜像里 pip 默认搜索的源可能没有对应 wheel,会出现 “Could not find a version that satisfies the requirement”。解决办法是换用国内镜像源,或者直接升级 pip 到最新版本后再装。

pip3 install --upgrade pip pip3 install opencv-python opencv-contrib-python -i https://pypi.tuna.tsinghua.edu.cn/simple

源码编译更适合对性能有极致追求、或需要自定义 OpenCV 功能模块的场景。源码编译的耗时在树莓派 4B 上动辄三四个小时,而且在编译过程中有大量依赖要手动处理。对于绝大多数人来说,先 pip 安装跑通功能,再决定要不要源码编译才是合理节奏。我自己早期花了整整一天去编译,最后发现 pip 版本在功能上已经够用,编译带来的性能提升并非肉眼可辨。

2.3 摄像头驱动检测与 OpenCV 接口基础

装完 OpenCV 后,先别急着写人脸检测代码,第一步要确认摄像头是否被系统识别。树莓派官方摄像头模块在raspi-config里开启后,一般会生成设备节点:

sudo raspi-config # 选择 Interface Options -> Camera -> Enable

如果是 USB 摄像头,插入后可以通过以下命令查看是否被识别:

ls /dev/video*

看到/dev/video0或者/dev/video1就说明系统已经识别到设备。注意树莓派在启用 CSI 摄像头后,可能默认占用video0,USB 摄像头会被分配为video1。OpenCV 中调用时注意索引即可:

import cv2 cap = cv2.VideoCapture(0) # 0对应video0,必要时改成1 if not cap.isOpened(): print("无法打开摄像头") exit() ret, frame = cap.read() if ret: print("摄像头读取成功,画面尺寸:", frame.shape) cap.release()

这里建议把frame.shape打印出来确认尺寸,树莓派摄像头模块在默认配置下通常是 640x480 或者 1280x720。对于人脸识别项目,分辨率并非越高越好,高分辨率会直接拖慢处理帧率。640x480 足够用于 LBPH 人脸识别,后续如果需要提升检测距离,再适当调高并做局部裁剪。

2.4 LBPH 人脸识别核心原理

LBPH 的核心操作分为三步:局部二值模式编码、分块直方图统计、比对判分。

第一步,对灰度图中的每个像素,取一个半径范围内的邻域像素(通常半径为 1,取 8 个邻域像素),逐个比较邻域像素与中心像素的大小。邻域像素大于等于中心像素记为 1,否则记为 0。把这 8 个 0/1 值按固定顺序排列成一个二进制数,再转成十进制,就得到该像素的 LBP 编码值。

比如中心像素值是 128,周围 8 个像素值分别是 [130, 105, 140, 160, 90, 170, 188, 72],那么与中心比较后会得到 [1, 0, 1, 1, 0, 1, 1, 0],转成二进制10110110,再变成十进制182。这个值就代表了这个像素点的局部纹理特征。

第二步,把人脸区域划分成若干个小块,比如 8 行 8 列共 64 个网格,对每个网格分别统计 LBP 值的直方图。这样 “哪个块的 LBP 值集中在哪些范围” 就成了描述这张脸的纹理特征向量。LBPH 默认参数中半径radius=1,邻域点数neighbors=8,网格大小grid_x=8,grid_y=8。

第三步,识别时,将当前人脸的特征向量与数据库中的每个人脸直方图计算相似度距离。OpenCV 中 LBPH 使用扩展的卡方距离,距离越小越相似。训练时可以为每个人设定一个threshold,距离超过该阈值则判定为未知。

LBPH 有个特性是低分辨率下依然能保持较高的纹理区分度,这也正是它适配树莓派低分辨率摄像头画面的原因。但它的局限也很明显:对大幅度的姿态变化、夸张表情和遮挡比较敏感。所以在样本采集环节就要尽可能覆盖不同角度。

3. 动手实现全流程

3.1 人脸样本采集模块

模型训练需要足够多样本。采集阶段的目标是:在不同光照、不同角度、不同表情下,为每个人采集 50~100 张人脸灰度图。

我实现采集脚本的思路是:加载 Haar 人脸检测器,循环读取摄像头画面,检测到人脸后裁剪、灰度化、缩放为 200x200,保存到以人名命名的文件夹中。同时按键盘数字键切换人物编号,这样在一台机器上就能连续采集多个人的样本。

import cv2 import os face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + "haarcascade_frontalface_default.xml" ) save_dir = "dataset" os.makedirs(save_dir, exist_ok=True) current_person = 1 person_name = f"person_{current_person}" sample_count = 0 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while True: ret, frame = cap.read() if not ret: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale( gray, scaleFactor=1.2, minNeighbors=5, minSize=(100, 100) ) for (x, y, w, h) in faces: cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) face_region = gray[y:y + h, x:x + w] face_resized = cv2.resize(face_region, (200, 200)) person_dir = os.path.join(save_dir, person_name) os.makedirs(person_dir, exist_ok=True) if sample_count < 100: cv2.imwrite( os.path.join(person_dir, f"{sample_count}.jpg"), face_resized ) sample_count += 1 cv2.putText( frame, f"Person: {person_name} Samples: {sample_count}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2, ) cv2.imshow("collect samples", frame) key = cv2.waitKey(1) if key == ord("q"): break elif key == ord("n"): current_person += 1 person_name = f"person_{current_person}" sample_count = 0 elif key == ord("r"): sample_count = 0 cap.release() cv2.destroyAllWindows()

这里我要强调几个关键点:

  • minSize=(100, 100)的设置很关键,太小会带来大量误检框和重复框。树莓派摄像头正对行人大概 1 米内,100x100 的人脸框是一个比较合理的下限。
  • 如果采集过程中发现某些照片人脸偏转、模糊、眨眼严重,直接按下r重新采集,不要碍于样本数量将烂图混进去。样本质量直接决定模型上限。
  • 每人 50~100 张足够。少于 20 张时 LBPH 稳定性很差,超过 120 张后对精度提升几乎没有贡献,反而增加训练耗时。

3.2 训练 LBPH 模型

采集完成后的数据结构是:

dataset/ person_1/ 0.jpg 1.jpg ... person_2/ 0.jpg 1.jpg ...

训练脚本需要读取所有子文件夹中的图片,提取人脸区域(这里直接用整张图,因为采集时已经裁剪好),并赋予对应的标签编号。标签从 0 开始,在代码中维护一个names列表,将标签数字映射回人名。

import cv2 import os import numpy as np dataset_dir = "dataset" names = [] images = [] labels = [] label_id = 0 for person_dir in sorted(os.listdir(dataset_dir)): person_path = os.path.join(dataset_dir, person_dir) if not os.path.isdir(person_path): continue names.append(person_dir) for img_name in os.listdir(person_path): img_path = os.path.join(person_path, img_name) img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) if img is None: continue images.append(img) labels.append(label_id) label_id += 1 recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.train(images, np.array(labels)) recognizer.save("trainer.yml") print("训练完成,识别标签映射:", names)

这里有个细节:cv2.face.LBPHFaceRecognizer_create()来自opencv-contrib-python包。如果只装了opencv-python,调用时会直接AttributeError: module 'cv2' has no attribute 'face'。这个报错我相信很多人遇到过,解决方案就是补装opencv-contrib-python。

训练完成后会得到一个trainer.yml文件,里面保存的是 LBPH 直方图模型参数。识别阶段只需要加载这个文件即可,不需要再保留训练图像。这个模型文件通常只有几百 KB,可以很方便地复制到其他设备上使用。

3.3 实时识别主程序

识别主程序的逻辑是:加载 Haar 检测器和 LBPH 模型,读取摄像头每一帧,检测人脸,裁剪缩放后输入recognizer.predict(),根据返回的标签和置信度判断身份。

import cv2 face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + "haarcascade_frontalface_default.xml" ) recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read("trainer.yml") names = ["person_1", "person_2"] confidence_threshold = 70 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while True: ret, frame = cap.read() if not ret: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale( gray, scaleFactor=1.1, minNeighbors=5, minSize=(80, 80) ) for (x, y, w, h) in faces: face_region = gray[y:y + h, x:x + w] face_resized = cv2.resize(face_region, (200, 200)) label, confidence = recognizer.predict(face_resized) if confidence < confidence_threshold: person_name = names[label] color = (0, 255, 0) else: person_name = "unknown" color = (0, 0, 255) cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2) cv2.putText( frame, f"{person_name} ({confidence:.1f})", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2, ) cv2.imshow("face recognition", frame) if cv2.waitKey(1) & 0xFF == ord("q"): break cap.release() cv2.destroyAllWindows()

predict()返回的置信度(confidence)在 LBPH 中代表计算出的距离值。距离越低代表越接近训练样本。不同人、不同光照条件下,距离的绝对值分布差异很大,所以阈值不要直接抄网上别人的值,必须根据自己模型的实测结果来调。我的经验是先打印出所有正常识别时 confidence 的取值范围,再设定一个略高于该范围上限的阈值。比如我自己的环境里,本人识别时 confidence 基本在 35~55 之间,陌生人在 85~130 之间,那么阈值取 65 是比较合理的分界点。

3.4 帧率优化与远程查看

树莓派 4B 上跑裸的 OpenCV 人脸识别,帧率通常在 10~15 FPS 左右。如果你觉得画面卡顿,先不要急着换设备,下面这几个优化点逐个试一遍,通常能提高到 20 FPS 以上:

第一个优化是降低检测分辨率。用cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)和cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240),把输入帧缩小一半。人脸检测在 320x240 上耗时大幅下降,识别精度在近距离场景下几乎不受影响。如果你需要画面的可视化展示,可以用最终输出的窗口给cv2.resize(frame, None, fx=1.5, fy=1.5)放大,展示效果基本不掉。

第二个优化是调整 Haar 检测器的scaleFactor。这个参数控制图像金字塔的缩放步长。取值越接近 1,检测越精细但耗时越长;取值太大,可能会漏检。我的实测经验是在1.1~1.2之间是平衡点。

第三个优化是跳帧处理。人脸检测比较耗时,识别也不轻,可以设定每隔一帧做一次完整检测识别,中间那一帧直接用上一帧的人脸框画框显示。这种策略特别适合不需要每帧都精确检测的场景。

第四个优化是用CvVideoCapture的缓冲区设置解决画面延迟。树莓派摄像头模块默认缓冲区可能积累好几帧旧画面,导致预览画面有滞后感。可以通过以下代码调整:

cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)

至于远程查看,一个轻量的做法是使用 MJPEG 流。OpenCV 自带的VideoWriter配合video4linux2后端可以把处理后的画面实时输出为本地 http 流。更简单的方案是使用flask写一个十几行的视频流服务,把处理后的帧编码成 JPEG 推给浏览器。如果你是在局域网内做调试,这个方法非常方便,不用跑 HDMI 线到树莓派上。

from flask import Flask, Response import cv2 app = Flask(__name__) cap = cv2.VideoCapture(0) def generate_frames(): while True: ret, frame = cap.read() if not ret: break # 在这里插入人脸识别、画框等处理 ret, jpeg = cv2.imencode(".jpg", frame) if not ret: continue yield (b"--frame\r\n" b"Content-Type: image/jpeg\r\n\r\n" + jpeg.tobytes() + b"\r\n") @app.route("/video") def video_feed(): return Response(generate_frames(), mimetype="multipart/x-mixed-replace; boundary=frame") if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, threaded=True)

浏览器访问http://树莓派IP:5000/video就能看到实时画面。这个方案在实际使用中很稳,且不会给树莓派带来额外负担。

4. 常见问题排查与性能调优实录

4.1 帧率低于预期、画面卡顿明显怎么办

帧率低的核心瓶颈在 Haar 人脸检测。可以先做一次基准测试:只跑detectMultiScale,打印cv2.getTickCount()测出每帧检测耗时。如果单帧检测耗时超过 80ms,就得按上一节提到的降低分辨率方案处理。

还有一个容易被忽略的点:树莓派的风扇降温策略。CPU 过热降频后性能会剧烈下降,识别帧率会出现忽高忽低的现象。检查 CPU 温度:

vcgencmd measure_temp

如果温度超过 80 度,务必加装散热片和风扇,并在config.txt中确认avoid_warnings=1不会掩盖电压不足的问题。我用的是某款带风扇的铝壳,树莓派满载时温度能压在 60 度以内,帧率稳定性比裸板好很多。

4.2 识别不准、把陌生人识别成自己人

这种情况十有八九是置信度阈值设得过大,或者训练样本质量太差。

第一步先打印不同人脸的 confidence 值,画出分布情况。比较自己人和陌生人的距离区间,如果两者重叠严重,说明训练样本区分度不够。解决办法是增加样本覆盖角度和光照变化,尤其是侧面和戴眼镜/不戴眼镜两种情况。

第二步检查grid_x和grid_y参数。LBPH 默认 8x8 分块在大多数人脸数据集上表现良好,但如果你的人脸区域裁剪后包含太多背景,分块统计就会被背景信息干扰。建议在采集阶段就用 Haar 检测器裁好人脸,裁完后检查图片是否只包含额头到下巴、脸颊两侧不外扩。如果背景占比大,可以稍微收紧裁剪框。

第三步是检查训练集和识别阶段是否使用了相同的预处理流程。很多人训练时直接读dataset里的原始裁剪图,识别时又用detectMultiScale输出的框去resize,两者如果尺寸、灰度化方式不一致,识别率会受影响。我在代码中统一为 200x200 的灰度图,训练和识别都用同一套变换,这一点必须严格保持一致。

4.3 摄像头打不开,或者反复自动断开

这个是树莓派上最常见也最恼人的问题。如果是 CSI 摄像头,排查顺序是:

# 查看摄像头是否被系统识别 dmesg | grep camera # 查看视频设备节点 ls -l /dev/video*

如果video0存在但 OpenCV 打不开,先检查当前用户是否在video组中:

sudo usermod -a -G video 当前用户名

如果是 USB 摄像头,问题通常出在电流上。部分移动硬盘、大功率 USB 设备同时插入时,USB 口供电不足会导致摄像头反复掉线。我后来给树莓派单独配了一个 5V 3A 的电源适配器,问题基本消失。如果 USB 口供电仍然紧张,买一个带外部供电的 USB HUB 是最省心的解法。

4.4 常见问题速查表

现象可能原因解决措施
ModuleNotFoundError: cv2未安装 OpenCVpip3 install opencv-python opencv-contrib-python
cv2.face不存在缺少 contrib 包安装opencv-contrib-python
摄像头无法打开设备节点被占用或权限不足检查/dev/video*,加入video组
画面卡顿检测分辨率过高降到 320x240,跳帧处理
识别总是 unknown阈值过低或样本不够降低阈值,增加训练样本覆盖
误把陌生人识别成熟人阈值过高或样本区分度不够打印 confidence 分布,重新调阈值和样本
CPU 温度高、帧率波动散热不足加装风扇散热片
模型文件读取失败路径错误或文件损坏检查训练生成的trainer.yml路径
VIDEOIOC_QUERYV4L2 failed摄像头格式不支持换cv2.CAP_DSHOW或使用 USB 摄像头

4.5 性能调优实录:我的最终运行参数

最后分享一下我在树莓派 4B(4GB 版本)上实测稳定的参数组合:

  • 输入分辨率:640x480
  • 人脸检测分辨率:320x240(将帧缩放到 320 后再检测,画框时坐标乘回缩放比例)
  • Haar 参数:scaleFactor=1.15, minNeighbors=5, minSize=(60, 60)
  • LBPH 参数:radius=1, neighbors=8, grid_x=8, grid_y=8
  • 置信度阈值:根据实际打印结果设为 60~70 之间
  • 跳帧策略:检测帧间隔 2 帧

将该组合实测下来的结果是:检测环节单帧耗时约 45ms,识别预测耗时约 8ms,整体帧率稳定在 16 FPS 左右。这个表现在室内光照下,距离摄像头 0.5~1.5 米时识别准确率可以达到 95% 以上(视频流连续识别,非单张图片测试)。

如果你希望识别范围更远,可以升级到分辨率更高的摄像头模块,并将人脸最小检测尺寸调大到 120x120。但请注意,检测范围变大的同时,误检率也会上升,需要配合minNeighbors参数做平衡。

5. 基于这个项目的扩展方向与经验沉淀

树莓派 OpenCV 人脸识别项目做到这一步,已经是一个可演示、可扩展的原型。顺着这个基础,有很多值得继续深入的路径。

一个方向是接入摄像头云台追踪。通过人脸框的中心坐标与画面中心的偏差,用 PID 控制舵机旋转,让摄像头始终对准人脸。这个功能做出来后,才是真正的“跟随机器人”雏形,比单纯的静态识别有意思得多。

另一个方向是结合语音播报模块做交互闭环。识别到特定人以语音打招呼,识别到陌生人播报警告。这样系统就不只是一个算法 demo,而是能应付实际场景的小设备。

第三个方向是数据管理升级。目前用的是本地文件夹存储样本和 yml 模型文件,可以改成将人脸特征向量存入 SQLite 或者远程数据库,训练和识别进程解耦,支持更多人的注册和注销。我在后续的版本中就是这样做的,实际使用体验比每次重新训练整个模型方便许多。

第四个方向是模型升级。如果对识别精度有更高要求,可以把 OpenCV 的 Haar 检测换成基于深度学习的轻量检测模型,或者把 LBPH 替换为支持向量机分类器。不过这些方案在树莓派上的算力消耗会比当前方案高很多,建议优先考虑带 NPU 的边缘设备。

从我自己踩过的坑来说,最想分享的经验有三条:

  • 所有环境问题都可以通过打印中间结果来定位。不要凭感觉猜,尤其是摄像头节点、帧尺寸、检测框坐标,全部打印出来对比。
  • 样本采集阶段宁可少而精,也不要多而杂。LBPH 对样本噪声比较敏感,几张模糊或裁剪不完整的样本就可能拖低整个人的识别率。
  • 阈值调参不要怕麻烦,一定要针对自己的实际光照和摄像头去测。网上所有推荐的阈值都只能当起点,不能直接照搬。

做完整个项目之后你会发现,树莓派真正教给你的不是某个算法本身,而是如何在有限算力下做工程取舍。衡量一个方案是否可行的标准永远不是“理论上精度多高”,而是“在硬件条件下能跑得动、跑得稳”。这套经验用在后续任何嵌入式视觉项目上,都非常值钱。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进