【视觉多模态】基于视觉AI的人物轨迹生成方案
背景
基于 Yolo-World v2 把人物从视频每帧中提取出来并分别存储在某路径下。现在的下一步,应该是把这些截图全部转换为向量并存储到向量数据库。
步骤
- 下载SFace模型
bash
https://github.com/opencv/opencv_zoo/blob/main/models/face_recognition_sface/face_recognition_sface_2021dec.onnx
- 安装opencv-python 依赖,测试可用性
bash
import cv2
print("OpenCV版本:", cv2.__version__)
print("是否支持dnn模块:", hasattr(cv2, 'dnn'))
- 基础调用测试代码
bash
import cv2
import numpy as np
def sface_extract_face_vector(image_path, model_path, input_size=(112, 112)):
"""
利用SFace模型提取人脸图像的特征向量
:param image_path: 输入人脸图像路径
:param model_path: SFace模型(onnx格式)路径
:param input_size: SFace输入尺寸(固定112x112,不可修改)
:return: 512维人脸特征向量(归一化后)
"""
# 步骤1:读取并预处理图像(SFace强制要求,必须严格遵循)
# 1.1 读取图像(彩色模式)
img = cv2.imread(image_path)
if img is None:
raise FileNotFoundError(f"无法读取图像文件:{image_path}")
# 1.2 转换色彩空间(BGR→RGB,SFace模型要求)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 1.3 调整图像尺寸(固定112x112,SFace输入尺寸)
img_resized = cv2.resize(img_rgb, input_size)
# 1.4 数据格式转换(HWC→CHW,并添加批次维度)
img_transposed = np.transpose(img_resized, (2, 0, 1)) # (H,W,C)→(C,H,W)
img_batch = np.expand_dims(img_transposed, axis=0) # (C,H,W)→(1,C,H,W)
# 1.5 归一化(像素值归一化到[-1, 1],SFace模型要求)
img_normalized = (img_batch.astype(np.float32) - 127.5) / 127.5
# 步骤2:加载SFace onnx模型
net = cv2.dnn.readNetFromONNX(model_path)
# 可选:启用GPU加速(若有NVIDIA GPU,需配置OpenCV GPU环境)
# net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
# net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
# 步骤3:模型推理(前向传播,获取特征向量)
net.setInput(img_normalized)
face_vector = net.forward() # 输出形状:(1, 512)
# 步骤4:向量归一化(提升后续相似度计算的准确性)
face_vector_normalized = face_vector / np.linalg.norm(face_vector, axis=1, keepdims=True)
# 步骤5:返回一维特征向量(去除批次维度)
return face_vector_normalized.squeeze()
# ---------------------- 配置参数并运行 ----------------------
if __name__ == "__main__":
# 配置路径(修改为你的实际路径)
import os
SFACE_MODEL_PATH = "/data1/projs/SFace/opencv_zoo/face_recognition_sface_2021dec.onnx"
path = '/data1/datas/wildtrack_dataset/wildtrack_dataset/Wildtrack_dataset/Image_subsets/C1/cropped'
for file in os.listdir(path):
TEST_IMAGE_PATH = f"{path}/{file}"
try:
# 提取人脸特征向量
face_feature = sface_extract_face_vector(TEST_IMAGE_PATH, SFACE_MODEL_PATH)
# 打印结果验证
print("SFace特征向量形状:", face_feature.shape) # 应输出 (512,)
print("SFace特征向量前10个值:", face_feature[:10])
print("向量归一化验证(模长应≈1):", np.linalg.norm(face_feature))
except Exception as e:
print("运行报错:", str(e))
结果:
bash
024.8.0-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher 41849 -- /data1/projs/yolov5-botsort/test_only.py
OpenCV版本: 4.12.0
是否支持dnn模块: True
SFace特征向量形状: (128,)
SFace特征向量前10个值: [-0.04181107 0.10590139 0.04513331 0.01377215 0.0497637 -0.03535534
-0.16844605 -0.07953446 0.00360839 -0.02015602]
向量归一化验证(模长应≈1): 1.0
SFace特征向量形状: (128,)
[-0.00864951 0.13721107 0.00097885 -0.00774572 -0.0306458 -0.01465974
-0.15866575 -0.0629375 0.09049896 0.01736232 0.0341635 -0.13206565
-0.04685504 -0.05928086 0.04323329 -0.03585685 0.11940002 -0.00355799
0.05041823 -0.01659128 -0.09504692 0.06199503 0.02595275 -0.01023104
0.04494344 -0.04678775 -0.00665194 0.06294718 0.05229411 -0.11271915
-0.05184305 -0.03285127 -0.1269116 -0.18189423 -0.03652013 0.07497738
0.1206397 0.13391575 0.05584204 0.00342186 -0.11525489 -0.1169667
-0.03108696 -0.10747405 -0.0115601 0.26701513 -0.03678199 0.01830711
-0.05481235 0.03366939 0.14102869 0.05906308 0.11707348 -0.01611113
-0.10128209 0.06425073 -0.04434577 0.22684796 0.0718286 0.10504609
-0.10001983 -0.04661285 0.03369538 0.07690774 -0.02276918 0.01527304
0.0209459 -0.06722156 0.12785007 -0.07330906 0.12718043 0.03650117
0.03357406 -0.2230807 0.0687449 0.05167081 0.13399096 -0.0055605
0.00925102 0.1770478 0.12013676 0.1023792 0.04011027 -0.01326507
0.00212444 0.03237054 0.10919312 0.05150268 0.07991081 -0.04595529
-0.05336874 -0.08158828 0.03280946 0.08914431 -0.04767266 -0.09420003
-0.21350156 -0.04984237 0.12527065 0.01778281 0.046942 -0.15537345
0.00691294 0.00522167 0.0064938 0.11388317 0.0553209 -0.06993211
0.03343213 -0.07741141 -0.04298204 -0.19652444 0.08844069 0.04499465
0.00322382 0.15364304 -0.00602631 0.09509759 -0.05117012 0.00659886
0.10149482 -0.1305973 0.12939171 -0.05865399 -0.0644947 -0.09172551
0.09984177 -0.00866709]
小结
SFace可用了,但有很多配套的内容需要补充。
(1)SFace 只针对人脸,并不包括人的身形、衣着等,因此,身形、衣着还是要另外的模型去辨别;
(2)SFace 只针对人脸,也因此,需要有前置的内容,先从图中检测到人脸,并进行切割后再传给SFace;
(3)细节上,为了更好发挥模型的效果,还有一个如下的流程:【意识上漏掉了一些逻辑,比如:对齐、标准化这两步】
bash
原始图像 → 人脸检测(定位人脸框坐标) → 人脸裁剪(仅保留人脸区域) → 人脸对齐(可选,提升精度) → 标准化预处理(112x112/RGB/归一化) → SFace特征提取 → 有效512维人脸向量
人脸检测:核心是定位人脸的位置和范围(输出人脸框的 x/y/w/h 坐标),解决 "图像里哪里有人脸" 的问题,过滤掉无脸 / 背影图像。
推荐模型:轻量场景用 OpenCV Haar 级联,高精度场景用 MTCNN/RetinaFace(能检测侧脸、小人脸,还能输出人脸关键点,为后续对齐做准备)。
人脸裁剪:根据检测到的人脸框坐标,从原始图像中精准切割出仅包含人脸的区域,剔除背景、身体、衣物等无关像素,让后续处理只聚焦人脸。
注意:裁剪时可适当扩大人脸框(比如向外扩展 10%),避免裁剪掉人脸边缘(如头发、下巴),保证人脸特征的完整性。
人脸对齐(可选但推荐):基于人脸检测输出的关键点(眼睛、鼻子、嘴巴),将人脸旋转、平移到标准正面姿态,解决人脸倾斜、侧脸导致的特征提取偏差。
这一步是提升 SFace 特征匹配精度的关键,比如同一人侧脸和正面的人脸,对齐后提取的向量相似度会大幅提升。
标准化预处理:将对齐后的人脸区域调整为 SFace 要求的112x112 固定尺寸,再完成 BGR→RGB、归一化到 [-1,1]、格式转换(HWC→CHW),满足模型输入格式要求。
所以,还需要进一步完善补充。