Skip to content

实践:人脸识别

一、原理

人脸识别是基于图片的,但在 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