Files
2025-01-23 09:05:45 +00:00

113 lines
4.0 KiB
Python

import cv2
import numpy as np
import os
from tqdm import tqdm
import json
from deepface import DeepFace
import redis
from config import REDIS_IDENTITY, PATH_CONFIG
class FaceFeatureExtractor:
def __init__(self):
"""
初始化特征提取器和Redis连接
"""
self.redis_client = REDIS_IDENTITY
def get_feature(self, img_path):
"""
获取人脸特征向量
Args:
img_path: 图片路径
Returns:
人脸特征向量或None(如果检测失败)
"""
try:
# 使用 DeepFace 提取特征
embedding_objs = DeepFace.represent(
img_path=img_path,
detector_backend="retinaface",
align=True,
model_name="Facenet512"
)
if embedding_objs and len(embedding_objs) > 0:
return embedding_objs[0]['embedding'] # 返回第一个人脸的特征向量
return None
except Exception as e:
print(f"处理图片 {img_path} 时出错: {str(e)}")
return None
def process_dataset(self, dataset_dir):
"""
处理数据集并保存特征到Redis
Args:
dataset_dir: 数据集根目录
"""
total_processed = 0
total_failed = 0
# 计算所有文件夹中的图片总数
total_images = sum(len([f for f in os.listdir(os.path.join(dataset_dir, d))
if f.lower().endswith(('.png', '.jpg', '.jpeg'))])
for d in os.listdir(dataset_dir)
if os.path.isdir(os.path.join(dataset_dir, d)))
with tqdm(total=total_images, desc="处理图片") as pbar:
# 处理所有文件夹
for person_name in sorted(os.listdir(dataset_dir)):
person_dir = os.path.join(dataset_dir, person_name)
if not os.path.isdir(person_dir):
continue
# 获取该人已有的特征向量列表
existing_features = []
if self.redis_client.exists(person_name):
existing_features = json.loads(self.redis_client.get(person_name))
person_features = existing_features
for img_name in os.listdir(person_dir):
if not img_name.lower().endswith(('.png', '.jpg', '.jpeg')):
continue
# 检查图片是否已处理
if any(item['image'] == img_name for item in existing_features):
pbar.update(1)
continue
img_path = os.path.join(person_dir, img_name)
feature = self.get_feature(img_path)
if feature is not None:
# 特征向量已经是列表格式,无需调用 tolist()
person_features.append({
'image': img_name,
'embedding': feature
})
total_processed += 1
else:
total_failed += 1
pbar.set_postfix({'成功': total_processed, '失败': total_failed})
pbar.update(1)
# 将该人的所有特征向量保存到Redis
if person_features:
self.redis_client.set(person_name, json.dumps(person_features))
print(f"\n处理完成!成功: {total_processed}, 失败: {total_failed}")
def main():
# 设置路径
DATASET_DIR = PATH_CONFIG['data']
# 创建特征提取器
extractor = FaceFeatureExtractor()
# 处理数据集
extractor.process_dataset(DATASET_DIR)
if __name__ == "__main__":
main()