news 2026/9/11 23:51:54

树莓派人脸识别系统实战:Haar锁定人脸、百度云识别与MySQL入库

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
树莓派人脸识别系统实战:Haar锁定人脸、百度云识别与MySQL入库

简介:基于树莓派的人脸识别系统,是一套面向毕业设计、课程项目与入门级人工智能开发者的完整Python工程。工程围绕树莓派摄像头完成人脸采集、本地存储与云端识别闭环,包含五个可运行脚本、一个Markdown说明及一份Word教程。其中五个脚本分别承担独立运行、数据库连接验证、OpenCV安装与摄像头测试、人脸拍摄锁定以及照片上传百度云并解析返回结果等功能。压缩包约1.53MB,共7个文件,内容已经过本地编译验证,按文档配置环境即可运行,难度适中,适合用来快速搭建人脸识别原型机或理解树莓派+OpenCV+云API的基础流程。资料目前已有185人学习,作为高分毕业设计,源码结构清晰,配套文档对运行逻辑与配置步骤做了说明,能够减少环境搭建和排错时间。

1. 树莓派上做“本地抓拍 + 云端识别”的人脸系统,代码怎么拆

第一次在树莓派上做人脸识别时,我直接试过在板子上跑 MTCNN,结果 4B 的 CPU 被吃满,帧率不到 2。后来把思路改成“本地 Haar 检测人脸 → 拍照保存 → 上传百度云识别 → 结果写 MySQL”,整套流程在树莓派 4B 上跑得很稳。这套毕业设计源码用的就是这种架构:OpenCV 只负责打开摄像头、锁定人脸、保存照片,真正的人脸属性识别由百度云完成。压缩包里包含 face.py 主程序、faceDetection.py、uploadDetection.py、mysql_test.py、testopencv_camera.py,以及一份操作说明 docx。如果你需要做门禁机原型、课设或毕设演示,这套代码比端上跑深度学习模型更实用,答辩也更容易说清楚“数据从哪来、结果存到哪”。

2. 环境搭建:先跑通摄像头和 MySQL,再做识别

人脸识别项目拿到手,先别急着改算法,环境没通后面全是坑。树莓派上的 Python/OpenCV/MySQL 组合看起来简单,实际会因为系统源、摄像头驱动、认证插件折腾半天。下面按testopencv_camera.pymysql_test.py两个文件,把环境验证讲透。

2.1 系统、Python 与 OpenCV 版本选型

我测试用的树莓派是 4B,系统是 Raspberry Pi OS Bullseye,内核 5.10,Python 3.9,OpenCV 4.6。如果你用树莓派 5 或者 Ubuntu Server,同样适用,但 OpenCV 的安装方式会有差别。

组件推荐版本说明
系统Raspberry Pi OS Bullseye / Bookworm对 CSI/USB 摄像头支持好
Python3.9+源码里的f-string语法需要 3.6+
OpenCV4.x自带 Haar 级联模型,够做人脸检测
PyMySQL1.x纯 Python MySQL 驱动
requests2.x调用百度云 API 用

安装命令我一般这样执行:

sudo apt update sudo apt install python3-opencv python3-pip -y pip3 install pymysql requests

简单解释一下:python3-opencv直接装树莓派源里预编译好的 OpenCV,省去自己编译几百分钟的时间;版本虽然不是最新,但 4.5 以上做毕业设计演示完全够用。pymysql是纯 Python 实现的 MySQL 驱动,装起来比mysqlclient轻松。如果遇到 apt 源下载慢,先换清华或阿里镜像源再 update,能省不少时间。

2.2 用 testopencv_camera.py 验证 OpenCV 和摄像头

testopencv_camera.py的用途很直接:确认 OpenCV 能打开摄像头并读出一帧图像。很多人在这个环节卡住,是因为树莓派的摄像头接口还需要额外驱动配置。最简验证脚本长这样:

import cv2 cap = cv2.VideoCapture(0) # 0 对应 /dev/video0 if not cap.isOpened(): print("cannot open camera") exit(1) ret, frame = cap.read() print("frame shape:", frame.shape) # (480, 640, 3) cv2.imwrite("camera_check.jpg", frame) cap.release()

这段代码的关键点有两处。VideoCapture(0)在树莓派上对应/dev/video0,USB 摄像头插上后一般就是这个设备;如果用 CSI 接口的官方摄像头,需要在/boot/config.txt里启用摄像头 overlay,新系统还要先跑一次libcamera-hello初始化。cap.read()返回retframeret为 False 时,先检查设备节点是否存在,或者拔插一次 USB 摄像头。

提示:如果cap.isOpened()返回 False,先敲ls /dev/video*;没有设备就装sudo apt install libcamera-apps,再用libcamera-hello测试 CSI 摄像头。

在树莓派 4B 上,USB 摄像头默认分辨率往往是 640x480,对人脸检测足够。有的摄像头支持 1280x720,建议在 read 前加一句cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480),降低分辨率能明显提升 Haar 检测帧率。

2.3 mysql_test.py:树莓派连接 MySQL 的测试脚本

压缩包里的mysql_test.py单独用来测试数据库连接。项目演示为了方便,一般在树莓派本地装 MariaDB/MySQL,然后再让识别结果落库。测试脚本核心逻辑类似这样:

import pymysql conn = pymysql.connect( host="127.0.0.1", # 本地 MySQL user="pi", # 数据库用户 password="123456", # 数据库密码 database="face_demo" ) with conn.cursor() as cur: cur.execute("SELECT VERSION()") version = cur.fetchone() print("MySQL version:", version) conn.close()

参数含义按顺序说明:host如果填localhost,PyMySQL 会走 socket 连接,在某些系统上会与 TCP 连接冲突,建议统一写127.0.0.1userpassword是 MySQL 账户,需要提前创建并授权;database必须已经存在,否则连接会报Unknown database

如果运行报Authentication plugin 'caching_sha2_password' cannot be loaded,是因为 MySQL 8 默认用了新认证插件,而 PyMySQL 版本太老。解决办法是升级 PyMySQL 到 1.0 以上,或者在创建用户时指定mysql_native_password

CREATE USER 'pi'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456'; GRANT ALL PRIVILEGES ON face_demo.* TO 'pi'@'localhost'; FLUSH PRIVILEGES;

这样mysql_test.py就能顺利读到face_demo库了。把环境跑通,后面face.py里的结果写入才不至于在答辩现场报错。

3. faceDetection.py 深度拆解:Haar 级联做人脸锁定与本地拍照

3.1 为什么在树莓派上选 Haar 级联而不是深度学习模型

人脸检测的常见方案有 OpenCV Haar、OpenCV DNN、MTCNN、YOLO 等。在树莓派 4B 这种算力受限的边缘设备上,Haar 级联的优势是纯 CPU 计算、模型文件小、没有过多依赖,单帧 640x480 图像检测一两个人脸通常能跑在 15-20ms 级别。MTCNN 准确率高,但板子上跑一次推理需要几百毫秒,实时视频流会明显卡顿。源码里faceDetection.py用的就是 OpenCV 自带的haarcascade_frontalface_default.xml

另一个选它的理由是数据集通用。这个 xml 文件由 OpenCV 官方用大量正脸样本训练,覆盖不同肤色、眼镜、光照条件,不需要你额外准备训练集。毕设场景下,只要保证摄像头正对来访人员,检测效果是够用的。如果后面要扩展成“人脸识别门禁机”,可以在这一层先做锁定拍照,再交给云端做人脸比对,边缘端不做大量数据训练。

3.2 从 VideoCapture 到锁定人脸拍照

faceDetection.py的流程是:打开摄像头 → 每帧转灰度 → Haar 检测人脸框 → 连续多帧稳定后截取人脸区域保存到本地。下面是带“锁定”逻辑的代码:

import cv2 import time face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + "haarcascade_frontalface_default.xml" ) cap = cv2.VideoCapture(0) stable_frames = 0 last_box = None 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) ) if len(faces) == 1: (x, y, w, h) = faces[0] if last_box is not None: old_x, old_y, old_w, old_h = last_box # 人脸框偏移小于 10 像素,认为画面基本稳定 if abs(x - old_x) < 10 and abs(y - old_y) < 10: stable_frames += 1 else: stable_frames = 0 last_box = (x, y, w, h) if stable_frames >= 5: face_img = frame[y:y + h, x:x + w] path = f"captured_{int(time.time())}.jpg" cv2.imwrite(path, face_img) print("saved", path) stable_frames = 0 # 保存后重置,避免连续写入 else: stable_frames = 0 last_box = None cap.release()

逻辑说明:先用cvtColor把 BGR 帧转成灰度,因为 Haar 特征基于灰度计算,能减少颜色通道的干扰并提速。detectMultiScale返回所有检测到的人脸框(x, y, w, h)。这里我加了一个锁定条件:只有画面里恰好一张脸,且人脸框中心连续 5 帧几乎不变,才认为“锁定”成功,然后截图保存。这样做的好处是避免人刚走进画面时脸还没摆正,拍到模糊或侧面照,导致上传百度云后识别不出人脸。

3.3 影响漏检和误检的核心参数

detectMultiScale的几个参数直接决定检测效果,改差一步就会要么框不住脸,要么满屏乱框。下表是常用配置和调整方向:

参数含义常见取值调大/调小的影响
scaleFactor每次缩放图像的比例1.1越接近 1,计算越慢,检测越准
minNeighbors每个候选框需要满足的邻居数5调大减少误检,但可能漏掉侧面脸
minSize最小人脸尺寸(80, 80)比它小的脸直接忽略,提升速度
maxSize最大人脸尺寸不设置限制过大的框,防止误检整张照片

在实际项目中,我一般先把minSize设成(80, 80),这样摄像头离人脸 1 米内都能框住。如果现场光照不均匀,把scaleFactor调整到 1.05,误检会明显下降,但树莓派 4B 的 CPU 占用会升高。监视器上做演示时,不要开一堆窗口,否则 CPU 占用率很高,人脸框反应变慢。另外,faceDetection.py单独运行时保存的照片路径在项目根目录,后续uploadDetection.py会去这些路径下读取。

4. uploadDetection.py:把照片交给百度云,拿到年龄、性别和颜值

4.1 百度云人脸识别 API 的调用流程

照片拍好后,识别动作交给百度云。这套 API 的逻辑很清晰:先在百度智能云控制台创建人脸识别应用,拿到 API Key 和 Secret Key;然后用这两个 Key 换取 access_token;最后把本地照片 base64 编码,POST 到v3/detect接口,返回年龄、性别、颜值、表情等字段。免费额度对毕设演示够用,但 QPS 限制通常在 2 左右,频繁调用需要加退避重试。

整个过程用 requests 库实现,比直接用 SDK 更容易看清请求结构,也方便把逻辑挪到其他设备上。要注意上传的图片必须是人脸正面的清晰照片,faceDetection.py里的锁定逻辑就是为这一步服务的。

4.2 获取 access_token 与发送检测请求

核心代码可以整理成两个函数:

import requests import base64 def get_access_token(ak, sk): url = "https://aip.baidubce.com/oauth/2.0/token" params = { "grant_type": "client_credentials", "client_id": ak, "client_secret": sk, } resp = requests.post(url, params=params, timeout=10) return resp.json()["access_token"] def detect_face(image_path, token): with open(image_path, "rb") as f: img_base64 = base64.b64encode(f.read()).decode("utf-8") body = { "image": img_base64, "image_type": "BASE64", "face_field": "age,gender,beauty,expression,face_shape", "max_face_num": 1, } url = "https://aip.baidubce.com/rest/2.0/face/v3/detect" headers = {"Content-Type": "application/json"} params = {"access_token": token} resp = requests.post(url, json=body, params=params, headers=headers, timeout=10) return resp.json()

参数说明:image_type必须与请求方式匹配,这里传BASE64,所以image字段是 base64 字符串;如果传图片 URL,则image_type要改成URLface_field决定返回哪些字段,字段越多响应越大,默认只返回face_tokenlocation和基础人脸概率,因此需要显式声明需要的属性。max_face_num限制最大检测脸数,门禁场景一般设 1,避免照片里有多人时返回不可控。

4.3 返回 JSON 的解析与容错

百度云返回结构是{ "error_code": 0, "error_msg": "SUCCESS", "result": { "face_num": 1, "face_list": [...] } }。解析时先判断error_code,再读取face_list

data = detect_face("captured_1699999999.jpg", token) if data.get("error_code") == 0: face = data["result"]["face_list"][0] age = face["age"] gender = face["gender"]["type"] # male / female beauty = face["beauty"] emotion = face["expression"]["type"] # none / smile / laugh 等 print(age, gender, beauty, emotion) else: print(data["error_msg"])

常用返回字段含义如下:

字段类型说明
ageint年龄估算
gender.typestringmale / female
beautyfloat0-100 颜值分
expression.typestringnone / smile / laugh

解析时最常踩的坑有两个。一是error_code为 216201,表示图片中没有人脸,这时候不要继续写入数据库,直接保存原图等下一帧。二是 token 过期,百度云的 access_token 有效期默认 30 天,只要程序不是常年不重启,通常不用做 token 刷新;如果做成服务,建议把 token 存到本地文件,每天定时重新获取。uploadDetection.py在源码里承担的就是这个环节,它和faceDetection.py同时运行时,前者会持续监听新照片并上传。

提示:免费版 QPS 超过限制会返回error_code: 1718,最简单的处理是捕获到错误后time.sleep(1)再重试,而不是循环狂发。

5. face.py 主程序与 MySQL 结果入库

5.1 face.py 在整套代码里的定位

压缩包里的说明文档写着“face.py 可以单独运行”。我的理解是,它把前三步整合成一条链路:打开摄像头、检测人脸、保存照片、上传百度云、拿到结果后写入 MySQL。单独运行它,相当于一个简化版的人脸识别门禁记录程序。这个文件比faceDetection.py多出来的部分就是数据库写入,所以先要把第 2 章的 MySQL 环境准备好。

在整合代码里,我会用面向过程的方式把步骤写清楚,不上类包装,这样答辩时逐行解释更方便。

5.2 结果表设计与人脸识别记录写入

MySQL 里建议先建一张日志表,记录每一次识别的人脸属性,方便后面统计客流或展示:

CREATE TABLE IF NOT EXISTS face_log ( id INT AUTO_INCREMENT PRIMARY KEY, photo_path VARCHAR(255) NOT NULL, age INT, gender VARCHAR(10), beauty FLOAT, expression VARCHAR(20), created_at DATETIME DEFAULT CURRENT_TIMESTAMP );

字段说明:photo_path保存本地照片的相对路径,方便和原始图片对应;agegenderbeautyexpression来自百度云返回结果;created_at由 MySQL 自动生成,不需要 Python 手工传时间。后续如果扩展成“人脸识别门禁机”,可以再加person_name字段,把每次检测到的 face_token 和注册用户表做关联。

Python 写入可以用下面这段:

import pymysql def save_to_mysql(path, age, gender, beauty, expression): conn = pymysql.connect( host="127.0.0.1", user="pi", password="123456", database="face_demo" ) with conn.cursor() as cur: sql = "INSERT INTO face_log (photo_path, age, gender, beauty, expression) VALUES (%s, %s, %s, %s, %s)" cur.execute(sql, (path, age, gender, beauty, expression)) conn.commit() conn.close()

这段代码把photo_path和识别结果一起写入,execute用占位符%s而不是字符串拼接,能避免 SQL 注入。写入频率按“人出现一次写一条”来控制,如果蹲在摄像头前不动,faceDetection.py会持续拍照,需要在上层限制同一个人 10 秒内只写一条,否则数据库会瞬间多出一堆重复记录。

5.3 和文档配套的演示顺序

拿到整个压缩包,我的建议是不要急着跑face.py,先按下面的顺序验证每个模块:

脚本文件主要职责演示用途
face.py全流程整合一键演示
faceDetection.py人脸锁定拍照验证检测效果
uploadDetection.py百度云上传识别验证 API 返回
mysql_test.py数据库连接测试验证环境
testopencv_camera.py摄像头测试验证设备

对应步骤:

  1. testopencv_camera.py,确认 OpenCV 和摄像头正常。
  2. mysql_test.py,确认数据库连接正常且face_demo库存在。
  3. 运行faceDetection.py,对人脸拍一张照片,检查照片清晰度和人脸占比。
  4. 运行uploadDetection.py,让它把刚才的照片上传并打印返回 JSON。
  5. 最后运行face.py,把拍照、识别、入库放在一次演示里完成。

这个顺序也和目录里的 docx 教程基本一致。uploadDetection.pyfaceDetection.py同时运行时,我一般开两个 SSH 会话,一个前台跑摄像头,一个后台盯日志,看到“saved”紧接着出现“age”就说明链路通了。如果打算以后部署成服务,可以把这两个进程用 systemd 管起来,但毕设阶段用 nohup 就够了。

6. 调试经验:从“摄像头花屏”到“百度云限流”的几个真实坑

6.1 摄像头打不开或帧率不高

设备节点存在但cap.read()一直 False,多半是端口被占用或驱动没加载。USB 摄像头先执行sudo modprobe uvcvideo,再检查当前用户是否在video组里:sudo usermod -aG video pi。CSI 摄像头的花屏问题,通常是排线没插紧。帧率低时,优先把分辨率降到 640x480,再关掉显示窗口,只保存图片。

6.2 OpenCV 依赖缺失

树莓派上经常出现ImportError: libGL.so.1libjasper.so.1,这是opencv-python缺少系统库导致的。直接安装sudo apt install libgl1 libjasper1即可,不要重新编译。也可以用系统自带的python3-opencv,它不会出现这种依赖问题。

6.3 百度云 QPS 限制

免费配额并发很低,批量测试时经常返回 error_code 17/18。处理方式是 token 复用一次,请求间隔至少 0.5 秒。如果对文件夹里的几十张历史照片做识别,最好写一个循环,每次 sleep 1 秒,并记录已处理列表,失败后从断点续传。

6.4 给文件名加时间戳,方便后续扩展

人脸识别门禁机通常要保存进出的时间上下文。源码里的captured_时间戳.jpg是一种好习惯,但秒级时间戳在重复拍照时会覆盖。我一般会改成毫秒级并带上日期:

from datetime import datetime photo_path = f"captured_{datetime.now().strftime('%Y%m%d_%H%M%S_%f')}.jpg"

这样文件名本身就是一个唯一的流水号,写入 MySQL 后能直接按时间范围检索照片,不需要额外维护自增编号。配合face_log表里的created_at,可以很方便地画出一天内不同时间段的人流量曲线。

本文还有配套的精品资源,点击获取

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

1 分钟投屏 Android:scrcpy 投屏与操控速查教程

1 分钟投屏 Android&#xff1a;scrcpy 投屏与操控速查教程 【免费下载链接】scrcpy Display and control your Android device 项目地址: https://gitcode.com/GitHub_Trending/sc/scrcpy 给别人演示手机上刚做的 App 时&#xff0c;你是否也被手机那块小屏幕折磨过&am…

作者头像 李华
网站建设 2026/9/11 23:51:45

基于SpringBoot的充电桩管理系统:架构设计、部署与AOP优化

简介&#xff1a;基于SpringBoot的车辆充电桩设计与实现项目资料包&#xff0c;是一套面向计算机相关专业毕业设计或Java Web开发学习者的完整参考方案&#xff0c;覆盖充电桩管理系统的选题规划、代码实现、论文撰写与答辩准备等环节。资源内含项目源码、毕业论文及PPT答辩稿&…

作者头像 李华
网站建设 2026/9/11 23:51:15

基于HDFS的分布式云盘设计与实现:从架构原理到集群部署

简介&#xff1a;一份基于Hadoop实现的百度云盘项目&#xff0c;完整提供源代码与文档说明&#xff0c;主要面向大数据、计算机相关专业的学生、毕业设计者以及初入Hadoop生态的开发者。项目以分布式文件存储为核心&#xff0c;涉及文件上传、下载、目录管理等功能&#xff0c;…

作者头像 李华
网站建设 2026/9/11 23:48:06

COLMAP点云与6D位姿联合可视化工作流

简介&#xff1a;这是一款面向三维重建与点云处理初学者及进阶开发者的轻量级可视化工具&#xff0c;专为解决COLMAP重建结果难以直观查看、PCD/PLY点云缺乏交互式渲染、6D位姿&#xff08;R|t&#xff09;无法动态呈现等实际问题而设计。工具支持加载COLMAP完整的重建四要素&a…

作者头像 李华
网站建设 2026/9/11 23:47:47

SpringBoot垃圾分类系统开发指南与毕业设计实践

1. 项目背景与核心价值这个SpringBoot垃圾分类管理平台项目最初源于我在指导大学生毕业设计时的实际需求。每年毕业季&#xff0c;总会有学生苦恼于找不到既有实际意义又适合本科阶段实现的课题。而垃圾分类作为近年来城市管理的热点问题&#xff0c;恰好具备社会价值和技术实现…

作者头像 李华