feature:加入功能,小朋友人脸识别与分类。
This commit is contained in:
@@ -101,13 +101,34 @@ class FaceAnalyzer:
|
||||
return None
|
||||
|
||||
# 提取人脸特征向量用于后续比对
|
||||
embedding = DeepFace.represent(
|
||||
embedding_result = DeepFace.represent(
|
||||
img_path=image_path,
|
||||
model_name='Facenet',
|
||||
enforce_detection=False,
|
||||
detector_backend='opencv' # 使用更快的opencv检测器
|
||||
)
|
||||
|
||||
# 处理embedding结果,确保它是一个数值数组
|
||||
embedding = None
|
||||
if isinstance(embedding_result, list) and len(embedding_result) > 0:
|
||||
if isinstance(embedding_result[0], dict) and 'embedding' in embedding_result[0]:
|
||||
embedding = embedding_result[0]['embedding']
|
||||
else:
|
||||
embedding = embedding_result[0]
|
||||
elif isinstance(embedding_result, dict) and 'embedding' in embedding_result:
|
||||
embedding = embedding_result['embedding']
|
||||
else:
|
||||
embedding = embedding_result
|
||||
|
||||
# 确保embedding是数值列表
|
||||
if embedding is not None:
|
||||
try:
|
||||
# 尝试转换为浮点数列表
|
||||
embedding = [float(x) for x in embedding]
|
||||
except (TypeError, ValueError):
|
||||
self.logger.error(f"无法将嵌入向量转换为浮点数列表: {image_path}")
|
||||
return None
|
||||
|
||||
self.logger.info(f"成功提取人脸特征向量: {image_path}")
|
||||
|
||||
# 如果使用了临时文件,删除它
|
||||
@@ -142,7 +163,6 @@ class FaceGrouper:
|
||||
self.min_samples = min_samples # 形成核心点所需的最小样本数
|
||||
self.logger = logging.getLogger("Plugin.KidPhotoExtractor.FaceGrouper")
|
||||
|
||||
# 在 FaceGrouper 类的 cluster_faces 方法中,优化性能和错误处理
|
||||
def cluster_faces(self, face_embeddings):
|
||||
"""对人脸特征向量进行聚类"""
|
||||
if not face_embeddings:
|
||||
@@ -153,14 +173,36 @@ class FaceGrouper:
|
||||
return [0] * len(face_embeddings)
|
||||
|
||||
try:
|
||||
# 将特征向量转换为numpy数组
|
||||
embeddings_array = np.array(face_embeddings)
|
||||
# 将特征向量转换为numpy数组,确保是浮点数类型
|
||||
# 首先提取实际的嵌入向量数据
|
||||
processed_embeddings = []
|
||||
for emb in face_embeddings:
|
||||
# DeepFace.represent() 可能返回字典或列表,需要提取实际的向量
|
||||
if isinstance(emb, dict) and 'embedding' in emb:
|
||||
processed_embeddings.append(emb['embedding'])
|
||||
elif isinstance(emb, list) and len(emb) > 0:
|
||||
# 如果是列表,取第一个元素
|
||||
if isinstance(emb[0], dict) and 'embedding' in emb[0]:
|
||||
processed_embeddings.append(emb[0]['embedding'])
|
||||
else:
|
||||
processed_embeddings.append(emb)
|
||||
else:
|
||||
processed_embeddings.append(emb)
|
||||
|
||||
# 检查数据有效性
|
||||
if np.isnan(embeddings_array).any() or np.isinf(embeddings_array).any():
|
||||
self.logger.error("特征向量包含无效值(NaN或Inf)")
|
||||
# 清理无效值
|
||||
embeddings_array = np.nan_to_num(embeddings_array)
|
||||
# 转换为numpy数组并确保是浮点数类型
|
||||
embeddings_array = np.array(processed_embeddings, dtype=np.float64)
|
||||
|
||||
# 安全地检查无效值
|
||||
try:
|
||||
has_nan = np.isnan(embeddings_array).any()
|
||||
has_inf = np.isinf(embeddings_array).any()
|
||||
if has_nan or has_inf:
|
||||
self.logger.error("特征向量包含无效值(NaN或Inf)")
|
||||
# 清理无效值
|
||||
embeddings_array = np.nan_to_num(embeddings_array)
|
||||
except TypeError:
|
||||
# 如果仍然无法检查NaN/Inf,记录警告并继续
|
||||
self.logger.warning("无法检查特征向量中的无效值,将直接进行聚类")
|
||||
|
||||
# 使用DBSCAN进行聚类
|
||||
clustering = DBSCAN(eps=self.eps, min_samples=self.min_samples, metric='euclidean').fit(embeddings_array)
|
||||
@@ -654,9 +696,21 @@ class KidPhotoExtractorPlugin(MessagePluginInterface):
|
||||
person_folder = os.path.join(output_dir, f"person_{person_id}")
|
||||
os.makedirs(person_folder, exist_ok=True)
|
||||
|
||||
# 复制照片
|
||||
# 复制照片 - 修改为只复制原始照片,不复制人脸区域
|
||||
copied_photos = []
|
||||
processed_paths = set() # 用于跟踪已处理的照片路径,避免重复复制
|
||||
|
||||
for image_path, _ in faces:
|
||||
# 跳过临时文件
|
||||
if ".temp." in image_path:
|
||||
continue
|
||||
|
||||
# 避免重复复制同一张照片
|
||||
if image_path in processed_paths:
|
||||
continue
|
||||
|
||||
processed_paths.add(image_path)
|
||||
|
||||
if self.photo_classifier.copy_photo(image_path, person_folder):
|
||||
copied_photos.append(os.path.basename(image_path))
|
||||
# 保存照片映射关系
|
||||
|
||||
Reference in New Issue
Block a user