3. 基于OpenVINO的人脸检测与识别

任务目标

在Intel NUC(集成Intel核显)上,使用OpenVINO工具套件加载人脸检测模型(face-detection-0200)与人脸识别模型(face-reidentification-retail-0095),对实时视频流(本地摄像头或视频文件)执行“检测→识别”流水线,并在画面中绘制识别结果。

环境与依赖

  • 硬件:Intel NUC(第8代或更新,集成UHD显卡)
  • 操作系统:Ubuntu 22.04 LTS
  • OpenVINO:2023.0或更新版本(pip install openvino openvino-dev)
  • 模型:从Open Model Zoo下载(omz_downloader --name face-detection-0200,face-reidentification-retail-0095)
  • Python库:opencv-python、numpy

实现代码

以下代码实现完整闭环:读取视频帧→人脸检测→人脸对齐裁剪→特征提取→与注册人脸库比对→显示结果。使用OpenVINO的CPU插件(自动利用Intel核显的GPU插件需额外配置,本案例以CPU推理保证可复现性)。

import cv2
import numpy as np
from openvino.runtime import Core

# ---------- 1. 初始化模型 ----------
core = Core()
det_model = core.read_model("face-detection-0200.xml")
rec_model = core.read_model("face-reidentification-retail-0095.xml")
det_compiled = core.compile_model(det_model, "CPU")
rec_compiled = core.compile_model(rec_model, "CPU")

# 获取输入输出信息
det_input = det_compiled.input(0)
det_output = det_compiled.output(0)
rec_input = rec_compiled.input(0)
rec_output = rec_compiled.output(0)

# ---------- 2. 注册已知人脸(单张示例) ----------
def extract_embedding(face_img):
    """输入BGR人脸图像,返回512维归一化特征向量"""
    resized = cv2.resize(face_img, (128, 128))  # 识别模型输入尺寸
    input_data = np.expand_dims(resized.transpose(2, 0, 1), 0).astype(np.float32)
    # 模型要求输入归一化到[0,1]
    input_data /= 255.0
    result = rec_compiled([input_data])[rec_output]
    emb = result[0].flatten()
    norm = np.linalg.norm(emb)
    return emb / norm if norm > 0 else emb

# 注册一个人脸(假设有已知人脸图片)
known_face_img = cv2.imread("known_person.jpg")
if known_face_img is None:
    raise FileNotFoundError("请提供 known_person.jpg 作为注册人脸")
known_emb = extract_embedding(known_face_img)
known_name = "Alice"

# ---------- 3. 视频处理主循环 ----------
cap = cv2.VideoCapture(0)  # 0=摄像头,或替换为视频文件路径
if not cap.isOpened():
    raise IOError("无法打开视频源")

while True:
    ret, frame = cap.read()
    if not ret:
        break

    h, w = frame.shape[:2]
    # 检测模型输入尺寸为 384x384
    resized = cv2.resize(frame, (384, 384))
    input_data = np.expand_dims(resized.transpose(2, 0, 1), 0).astype(np.float32)
    input_data /= 255.0

    det_result = det_compiled([input_data])[det_output]  # [1,1,N,7]
    detections = det_result[0][0]

    for det in detections:
        conf = det[2]
        if conf < 0.5:
            continue
        x1, y1, x2, y2 = det[3:7]
        # 映射回原图坐标
        x1, x2 = int(x1 * w / 384), int(x2 * w / 384)
        y1, y2 = int(y1 * h / 384), int(y2 * h / 384)
        x1, y1 = max(0, x1), max(0, y1)
        x2, y2 = min(w, x2), min(h, y2)
        if x2 - x1 < 10 or y2 - y1 < 10:
            continue

        face = frame[y1:y2, x1:x2]
        if face.size == 0:
            continue

        # 提取特征并与注册人脸比对
        face_emb = extract_embedding(face)
        similarity = np.dot(face_emb, known_emb)
        label = known_name if similarity > 0.7 else "Unknown"
        color = (0, 255, 0) if label == known_name else (0, 0, 255)

        cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2)
        cv2.putText(frame, f"{label} {similarity:.2f}", (x1, y1-10),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)

    cv2.imshow("Face Recognition", frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

运行与验证

  1. 下载模型并准备注册人脸:
    omz_downloader --name face-detection-0200,face-reidentification-retail-0095 --precisions FP16
    将一张包含单人正脸的清晰照片命名为 known_person.jpg 放在脚本同目录。
  2. 运行脚本:python face_recognition.py
  3. 验证通过条件:
    - 摄像头画面中,检测到的人脸被绿色或红色框标记;
    - 当画面中的人为注册的Alice时,显示绿色框及“Alice 0.7x”字样;
    - 其他人员显示红色框及“Unknown”;
    - 帧率不低于5 FPS(Intel NUC CPU推理可达到)。

关键说明

  • 检测模型输出格式为 [1,1,N,7],每行包含[batch, class, confidence, x1, y1, x2, y2],坐标已归一化到[0,1]。
  • 识别模型输入为128×128 RGB图像,输出512维特征向量;相似度阈值0.7为经验值,可根据实际场景调整。
  • 若需使用Intel核显GPU加速,将compile_model的设备参数改为"GPU",并确保已安装openvino的GPU运行时依赖。
  • 本案例仅注册单个已知人脸,扩展多人注册只需维护一个特征向量列表并遍历比对即可。
OpenVINO人脸检测与识别流水线 视频帧输入 人脸检测 face-detection-0200 人脸裁剪 对齐与缩放 特征提取 face-reidentification 识别 注册人脸库 已知人脸特征向量 余弦相似度 检测模型输出坐标 → 裁剪人脸区域 → 提取512维特征 → 与注册库比对 → 显示标签