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()
运行与验证
- 下载模型并准备注册人脸:
omz_downloader --name face-detection-0200,face-reidentification-retail-0095 --precisions FP16
将一张包含单人正脸的清晰照片命名为known_person.jpg放在脚本同目录。 - 运行脚本:
python face_recognition.py - 验证通过条件:
- 摄像头画面中,检测到的人脸被绿色或红色框标记;
- 当画面中的人为注册的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运行时依赖。 - 本案例仅注册单个已知人脸,扩展多人注册只需维护一个特征向量列表并遍历比对即可。