树莓派4B+Miniconda环境下的OpenCV LBPH人脸识别实战(PyCharm开发指南)
1. 环境准备:树莓派4B基础配置
树莓派4B作为一款性价比极高的微型计算机,非常适合用来做人脸识别这类轻量级AI项目。我选择的是4GB内存版本,这个配置跑OpenCV和人脸识别算法完全够用,实测下来很稳。
首先需要准备这些硬件:树莓派4B主板、官方电源适配器(一定要用5V/3A的,不然供电不足会出各种奇怪问题)、32GB以上的TF卡(建议Class10以上速度)、免驱USB摄像头(我用的罗技C920,720P够用,1080P效果更好)、树莓派官方显示屏或者通过HD线连接普通显示器。
软件方面,我推荐使用2022-09-06版本的Raspberry Pi OS Bullseye系统,这个版本对树莓派4B的兼容性最好。烧录系统我用的是Rufus工具,选择DD镜像模式写入,比普通模式更稳定。具体操作很简单:打开Rufus,插入TF卡,选择下载好的img镜像文件,点击开始等待完成就行。
系统烧录好后,第一次启动需要做一些基础配置。建议直接连接网线,这样安装软件会更稳定。如果你要用WiFi,可以在boot分区下新建一个wpa_supplicant.conf文件,里面配置好WiFi名称和密码,这样树莓派启动后就会自动连接无线网络。
我建议先安装中文输入法和VNC远程桌面,这样后续操作会方便很多。安装谷歌拼音输入法只需要几个命令:
sudo apt-get install fcitx fcitx-googlepinyin
安装完成后在系统设置里添加输入法就行。VNC的安装更简单,在raspi-config里启用VNC服务,然后在电脑上用VNC Viewer连接树莓派的IP地址就行,这样就不用一直接着显示器操作了。
2. Miniconda环境安装与配置
在树莓派上安装Miniconda比安装完整的Anaconda更省资源,而且完全够用。我选择的是Miniconda3-py37_4.9.2-Linux-aarch64这个版本,特别适配树莓派的ARM架构。
下载和安装Miniconda的一整套流程如下:
wget https://repo.anaconda.com/miniconda/Miniconda3-py37_4.9.2-Linux-aarch64.sh
bash Miniconda3-py37_4.9.2-Linux-aarch64.sh
安装过程中会问你是否初始化conda,一定要选yes,这样会自动配置环境变量。安装完成后需要重启终端或者执行source ~/.bashrc让配置生效。
我在这里踩过一个坑:如果安装过程中没有自动添加环境变量,需要手动在~/.bashrc文件末尾添加:
export PATH="/home/pi/miniconda3/bin:$PATH"
然后再次执行source ~/.bashrc。
验证安装是否成功可以用conda --version命令,如果显示版本号就说明安装成功了。我建议接下来创建一个专门的虚拟环境给人脸识别项目使用:
conda create -n face_recognition python=3.7
conda activate face_recognition
用虚拟环境的好处是依赖包不会和系统其他项目冲突,特别是树莓派存储空间有限,管理好环境很重要。
3. OpenCV和依赖库安装
在树莓派上安装OpenCV需要一些技巧,因为直接pip安装的版本可能不支持一些硬件加速功能。我推荐使用conda安装,这样会自动处理很多依赖关系。
在你的虚拟环境中执行:
conda install -c conda-forge opencv
这个命令会安装OpenCV和它依赖的numpy等科学计算库。安装完成后可以写个简单的测试脚本验证一下:
import cv2
print(cv2.__version__)
如果正常输出版本号,说明安装成功了。
除了OpenCV,我们还需要安装一些辅助库:
pip install pillow
pip install matplotlib
Pillow库用于图像处理,matplotlib用于显示图像,这些在人脸识别项目中都会用到。
我在这里又踩过一个坑:树莓派的内存有限,安装过程中可能会因为内存不足而失败。如果遇到这种情况,可以增加交换空间:
sudo nano /etc/dphys-swapfile
将CONF_SWAPSIZE改为1024,然后重启交换服务:
sudo /etc/init.d/dphys-swapfile restart
这样就能避免内存不足的问题了。
4. PyCharm安装与配置
在树莓派上安装PyCharm需要先安装JDK,因为PyCharm是基于Java开发的。我选择的是OpenJDK 11版本,这个版本与树莓派的兼容性最好。
安装JDK的步骤如下:
cd ~/Downloads
wget https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.26+4/OpenJDK11U-jdk_aarch64_linux_hotspot_11.0.26_4.tar.gz
sudo tar -xzf OpenJDK11U-jdk_aarch64_linux_hotspot_11.0.26_4.tar.gz -C /usr/lib/jvm
配置环境变量很重要,否则PyCharm找不到JDK:
sudo nano /etc/profile.d/jdk.sh
在文件中添加:
export JAVA_HOME=/usr/lib/jvm/jdk-11.0.26+4
export PATH=$JAVA_HOME/bin:$PATH
保存后执行source /etc/profile.d/jdk.sh让配置生效。
接下来下载和安装PyCharm:
wget https://download.jetbrains.com/python/pycharm-community-2020.2.5.tar.gz
tar -zxvf pycharm-community-2020.2.5.tar.gz
cd pycharm-community-2020.2.5/bin
./pycharm.sh
第一次运行会有一个安装向导,按照提示完成配置就行。
为了方便以后启动,可以创建桌面快捷方式:
sudo nano /usr/share/applications/pycharm.desktop
添加以下内容:
[Desktop Entry]
Version=1.0
Type=Application
Name=PyCharm
Icon=/home/pi/pycharm-community-2020.2.5/bin/pycharm.png
Exec=/home/pi/pycharm-community-2020.2.5/bin/pycharm.sh
Comment=Python IDE
Categories=Development;IDE;
Terminal=false
StartupWMClass=jetbrains-pycharm
5. LBPH人脸识别原理与实现
LBPH(Local Binary Patterns Histograms)是人脸识别中很经典的一个算法,特别适合在树莓派这种资源有限的设备上运行。它的原理是通过提取人脸的局部纹理特征来进行识别,计算量不大但效果不错。
LBPH的基本思想很简单:对图像中的每个像素,将其与周围的8个像素比较,如果周围像素值大于中心像素值,则该位置标记为1,否则为0。这样就会得到一个8位的二进制数,转换为十进制就是该点的LBP值。
在OpenCV中使用LBPH人脸识别器很简单:
import cv2
import numpy as np
# 创建LBPH人脸识别器
recognizer = cv2.face.LBPHFaceRecognizer_create()
# 准备训练数据
faces = []
labels = []
# 训练识别器
recognizer.train(faces, np.array(labels))
# 保存训练模型
recognizer.save('face_model.yml')
实际项目中,我们需要先收集人脸样本,然后训练模型,最后才能进行识别。我建议每个人至少收集20-30张不同角度和光照条件的照片,这样训练出来的模型才足够准确。
收集人脸样本的代码大概长这样:
import cv2
import os
# 创建保存目录
if not os.path.exists('dataset'):
os.makedirs('dataset')
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
camera = cv2.VideoCapture(0)
count = 0
while True:
ret, frame = camera.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
count += 1
cv2.imwrite(f"dataset/User.{id}.{count}.jpg", gray[y:y+h, x:x+w])
cv2.imshow('Collecting Faces', frame)
if cv2.waitKey(1) & 0xFF == ord('q') or count >= 30:
break
camera.release()
cv2.destroyAllWindows()
6. 完整项目开发与调试
在PyCharm中开发整个人脸识别项目时,我建议按照这样的目录结构来组织代码:
face_recognition_project/
├── dataset/ # 存放训练数据
├── trainer/ # 存放训练器
├── recognizer/ # 识别器代码
├── haarcascades/ # OpenCV级联分类器
└── main.py # 主程序
训练人脸识别模型的完整代码:
import cv2
import numpy as np
from PIL import Image
import os
def get_images_and_labels(path):
image_paths = [os.path.join(path, f) for f in os.listdir(path)]
face_samples = []
ids = []
for image_path in image_paths:
pil_image = Image.open(image_path).convert('L')
img_numpy = np.array(pil_image, 'uint8')
id = int(os.path.split(image_path)[-1].split(".")[1])
faces = face_cascade.detectMultiScale(img_numpy)
for (x, y, w, h) in faces:
face_samples.append(img_numpy[y:y+h, x:x+w])
ids.append(id)
return face_samples, ids
face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')
recognizer = cv2.face.LBPHFaceRecognizer_create()
faces, ids = get_images_and_labels('dataset')
recognizer.train(faces, np.array(ids))
recognizer.save('trainer/trainer.yml')
实际识别的代码:
import cv2
import numpy as np
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('trainer/trainer.yml')
face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')
font = cv2.FONT_HERSHEY_SIMPLEX
camera = cv2.VideoCapture(0)
while True:
ret, frame = camera.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
id, confidence = recognizer.predict(gray[y:y+h, x:x+w])
if confidence < 100:
cv2.putText(frame, f"ID: {id} {100-confidence:.0f}%",
(x+5, y-5), font, 1, (255, 255, 255), 2)
else:
cv2.putText(frame, "Unknown", (x+5, y-5), font, 1, (255, 255, 255), 2)
cv2.imshow('Face Recognition', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
camera.release()
cv2.destroyAllWindows()
在树莓派上运行这段代码时,我建议先关闭图形界面的其他程序,确保有足够的内存。如果发现识别速度慢,可以降低摄像头分辨率到640x480,这样处理速度会快很多。
7. 性能优化与实际问题解决
在树莓派上做人脸识别,性能优化很重要。我总结了几点实用经验:
首先是要合理设置摄像头分辨率,树莓派4B处理1080P视频流还是比较吃力,建议设置为640x480或者320x240,这样识别速度会快很多:
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
其次是使用多尺度检测时,可以调整检测参数来平衡精度和速度:
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
scaleFactor参数控制每次图像缩小的比例,minNeighbors控制检测的稳定性,minSize设置最小人脸尺寸。根据实际场景调整这些参数很重要。
我还发现一个常见问题:树莓派的USB摄像头有时候会被识别为video0有时候是video1,这会导致程序找不到设备。解决方法是在代码中自动检测可用的摄像头设备:
def find_working_camera():
for i in range(10):
cap = cv2.VideoCapture(i)
if cap.isOpened():
ret, frame = cap.read()
if ret:
cap.release()
return i
cap.release()
return -1
camera_index = find_working_camera()
if camera_index == -1:
print("找不到可用的摄像头")
else:
camera = cv2.VideoCapture(camera_index)
另外一个重要优化是使用线程来处理图像采集和识别,避免界面卡顿。我通常这样实现:
from threading import Thread
import time
class VideoStream:
def __init__(self, src=0):
self.stream = cv2.VideoCapture(src)
self.ret, self.frame = self.stream.read()
self.stopped = False
def start(self):
Thread(target=self.update, args=()).start()
return self
def update(self):
while not self.stopped:
self.ret, self.frame = self.stream.read()
time.sleep(0.01)
def read(self):
return self.ret, self.frame
def stop(self):
self.stopped = True
在实际部署时,树莓派可能会因为长时间运行而过热,建议安装散热风扇或者散热片。你可以通过命令vcgencmd measure_temp随时查看CPU温度。
最后,如果遇到识别准确率不高的问题,可以尝试这些方法:增加训练样本数量,确保在不同光照条件下采集照片;调整LBPH的参数,比如半径、邻域点数等;或者在识别时设置置信度阈值,低于阈值的结果视为识别失败。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)