实践:人脸识别
一、原理
人脸识别是基于图片的,但在 IoT 系统中,需要考虑如何高效地从视频流中获取关键帧、如何处理时序关系、如何平衡边缘与云端的计算。
视频识别的本质就是图片识别+时序处理。
1. 基本流程:视频 → 帧序列 → 单帧识别
实时视频流 → 抽帧 → 单张图片 → 识别处理 → 结果输出
↓
连续播放的图片
(通常25-30帧/秒)二、实践
1. 一个完整的 IoT 人脸识别系统架构
摄像头硬件
↓
视频流采集 (RTSP/ONVIF)
↓
流媒体服务器 (可选:Nginx-RTMP, SRS)
↓
├── 边缘分析节点 ──┐
│ ↓
│ 实时告警/本地存储
↓
云端AI服务
↓
结果处理引擎
↓
IoT平台集成
├── 设备管理
├── 用户管理
├── 规则引擎
└── 数据分析2. 从简单到复杂的实现路径
第1步:静态图片识别(拍照→识别)
第2步:实时视频抽帧识别
第3步:加入人脸跟踪(解决抖动)
第4步:边缘-云端协同
第5步:大规模设备管理3. 技术选型
TODO
4. 技术细节
TODO
5. 实践经验
1)运行摄像头
2)运行视频流
3)运行人脸检测
4)运行人脸识别
5)结果处理
三、案例
我拍摄一个视频,使用开源的人脸识别资源方案,可以把我视频里面的人脸出现次数识别并计算出来。
一、推荐方案对比
| 方案 | 安装难度 | 准确性 | 速度 | 额外功能 | 适合人群 |
|---|---|---|---|---|---|
| 1. DeepFace | ⭐☆☆☆☆ 极简单 | ⭐⭐⭐⭐⭐ 极高 | ⭐⭐☆☆☆ 较慢 | 年龄/性别/情绪分析 | 新手首选 |
| 2. face_recognition | ⭐⭐☆☆☆ 简单 | ⭐⭐⭐⭐☆ 高 | ⭐⭐⭐☆☆ 中等 | 人脸比对、特征点 | Python 开发者 |
| 3. InsightFace | ⭐⭐⭐☆☆ 中等 | ⭐⭐⭐⭐⭐ 极高 | ⭐⭐⭐⭐☆ 快 | 人脸检测+识别+对齐 | 专业推荐 |
| 4. OpenCV + DNN | ⭐⭐⭐⭐☆ 较难 | ⭐⭐⭐☆☆ 中等 | ⭐⭐⭐⭐⭐ 极快 | 纯检测不识别 | 追求速度 |
二、方案一:DeepFace(最简单,一行代码识别)
这是最简单快速的方案,API 极其友好。
安装:
bash
pip install deepface
pip install opencv-python完整代码:
python
from deepface import DeepFace
import cv2
import os
from collections import Counter
import pandas as pd
def count_faces_in_video(video_path, output_dir="faces_output", interval=10):
"""
统计视频中每个人脸出现的次数
:param video_path: 视频文件路径
:param output_dir: 保存截取的人脸图片
:param interval: 每隔多少帧处理一次(提高速度)
"""
# 创建输出目录
os.makedirs(output_dir, exist_ok=True)
# 打开视频
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print(f"无法打开视频: {video_path}")
return
# 获取视频信息
fps = cap.get(cv2.CAP_PROP_FPS)
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print(f"视频信息: {total_frames}帧, {fps:.2f}FPS")
# 存储结果
face_records = [] # 所有人脸记录
face_counter = Counter() # 人脸出现次数统计
saved_faces = {} # 已保存的人脸 {face_id: 保存路径}
frame_count = 0
processed_count = 0
print("开始处理视频...")
while True:
ret, frame = cap.read()
if not ret:
break
frame_count += 1
# 每隔interval帧处理一次(加速处理)
if frame_count % interval != 0:
continue
processed_count += 1
print(f"处理进度: {frame_count}/{total_frames} 帧", end="\r")
try:
# DeepFace分析人脸
# 这里使用'VGG-Face'模型,你可以换其他:Facenet, OpenFace, DeepFace, DeepID, Dlib
face_analysis = DeepFace.analyze(
frame,
actions=['age', 'gender', 'emotion', 'race'],
detector_backend='opencv', # 检测器:opencv, ssd, mtcnn, dlib
enforce_detection=False, # 如果没检测到人脸不报错
silent=True # 不显示进度条
)
# 处理检测结果
if isinstance(face_analysis, dict):
face_analysis = [face_analysis] # 统一为列表
for i, face in enumerate(face_analysis):
# 提取人脸区域
region = face['region']
x, y, w, h = region['x'], region['y'], region['w'], region['h']
# 保存人脸图片(用于后续查看)
face_img = frame[y:y+h, x:x+w]
if face_img.size > 0:
# 使用人脸特征作为ID(简化版:用位置+特征字符串)
face_id = f"{x}_{y}_{w}_{h}"
if face_id not in saved_faces:
face_filename = f"face_{len(saved_faces)+1:03d}.jpg"
face_path = os.path.join(output_dir, face_filename)
cv2.imwrite(face_path, face_img)
saved_faces[face_id] = face_path
# 记录人脸信息
record = {
'frame': frame_count,
'time_sec': frame_count / fps,
'x': x, 'y': y, 'w': w, 'h': h,
'age': face.get('age', 0),
'gender': face.get('dominant_gender', 'unknown'),
'emotion': face.get('dominant_emotion', 'unknown'),
'race': face.get('dominant_race', 'unknown'),
'face_id': face_id,
'face_image': saved_faces[face_id]
}
face_records.append(record)
# 统计出现次数
face_counter[face_id] += 1
except Exception as e:
# 跳过错误帧
continue
cap.release()
print(f"\n处理完成!共处理 {processed_count} 帧")
# 保存结果到CSV
if face_records:
df = pd.DataFrame(face_records)
csv_path = os.path.join(output_dir, "face_records.csv")
df.to_csv(csv_path, index=False, encoding='utf-8-sig')
print(f"详细记录已保存到: {csv_path}")
# 生成统计报告
generate_report(face_counter, fps, output_dir)
return face_records, face_counter
def generate_report(face_counter, fps, output_dir):
"""生成统计报告"""
report_path = os.path.join(output_dir, "statistics_report.txt")
with open(report_path, 'w', encoding='utf-8') as f:
f.write("=" * 50 + "\n")
f.write("视频人脸出现次数统计报告\n")
f.write("=" * 50 + "\n\n")
f.write(f"检测到 {len(face_counter)} 个不同的人脸\n")
f.write("-" * 50 + "\n\n")
# 按出现次数排序
sorted_faces = sorted(face_counter.items(), key=lambda x: x[1], reverse=True)
for i, (face_id, count) in enumerate(sorted_faces, 1):
# 估算出现时间(帧数转时间)
total_frames_estimate = count * 10 # 假设我们每10帧采样一次
total_seconds = total_frames_estimate / fps
f.write(f"人脸 #{i}:\n")
f.write(f" - 出现次数: {count} 次\n")
f.write(f" - 估算出现时长: {total_seconds:.1f} 秒\n")
f.write(f" - 人脸ID: {face_id}\n")
f.write(f" - 对应图片: face_{i:03d}.jpg\n")
f.write("-" * 30 + "\n")
print(f"统计报告已生成: {report_path}")
# 在控制台也输出摘要
print("\n" + "=" * 50)
print("人脸出现次数排名:")
print("=" * 50)
for i, (face_id, count) in enumerate(sorted_faces[:5], 1):
print(f"第{i}名: 出现 {count} 次 (ID: {face_id})")
# 使用示例
if __name__ == "__main__":
# 替换为你的视频路径
video_file = "your_video.mp4" # 支持mp4, avi, mov等格式
# 开始分析
records, counter = count_faces_in_video(
video_path=video_file,
output_dir="video_faces_analysis",
interval=10 # 每10帧处理一次,调小更精确但更慢
)DeepFace 优点:
- 一行代码完成人脸属性分析
- 自动处理多人脸
- 返回年龄、性别、情绪、种族等信息
- 内置多种人脸检测器
运行:
bash
python video_face_counter.py四、总结
TODO