克里斯蒂亚诺高手 f1315092000
suisuisui
关注数: 9 粉丝数: 16 发帖数: 1,857 关注贴吧数: 19
大佬们为啥我这个代码得出的置信度0.9几啊我每个类别弄了5个图片 # main.py from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import JSONResponse import face_recognition # 人脸识别核心库 import numpy as np # 数值计算 from pathlib import Path # 路径处理 from PIL import Image # 图像验证 import io # 二进制流处理 # 初始化FastAPI应用 app = FastAPI(title="人脸识别服务", description="基于FastAPI和face_recognition的人脸识别API") # ---------------------------- # 本地人脸库初始化模块 # ---------------------------- def load_known_faces(faces_dir="faces"): """ 加载本地人脸库并提取特征编码 Args: faces_dir (str): 人脸库目录路径,默认"faces" Returns: dict: {人物名称: [特征编码列表]} """ known_faces = {} try: # 遍历faces目录下的所有子目录(每个人物一个目录) for person_dir in Path(faces_dir).iterdir(): if person_dir.is_dir(): name = person_dir.name # 目录名作为人物名称 encodings = [] # 遍历该人物的所有图片 for image_path in person_dir.glob("*"): try: # 加载图片并提取人脸特征 image = face_recognition.load_image_file(image_path) face_locations = face_recognition.face_locations(image) face_encs = face_recognition.face_encodings(image,face_locations,num_jitters=8) if face_encs: enc=face_encs[0] enc_normalized=enc/np.linalg.norm(enc)#新增标准化 encodings.append(enc_normalized) else: print(f"[WARN] {image_path} 未检测到人脸,已跳过") except Exception as e: print(f"[ERROR] 加载 {image_path} 失败: {str(e)}") # 保存该人物的所有特征编码 if encodings: known_faces[name] = encodings else: print(f"[WARN] 人物 {name} 无有效图片,已跳过") print(f"[INFO] 人脸库加载完成,已注册 {len(known_faces)} 人") return known_faces except FileNotFoundError: raise RuntimeError(f"人脸库目录 {faces_dir} 不存在!") # 全局加载已知人脸库 known_faces = load_known_faces() # ---------------------------- # API接口实现 # ---------------------------- @app.post("/api/recognize") async def recognize_face(image: UploadFile = File(...)): """ 人脸识别接口 - 支持单张图片上传 - 返回检测到的人脸位置、名称和置信度 """ # ---------------------------- # 1. 文件验证阶段 # ---------------------------- # 验证文件类型 if image.content_type not in ["image/jpeg", "image/png"]: return JSONResponse( status_code=400, content={"success": False, "message": "仅支持JPG/PNG格式"} ) # 验证文件内容 try: contents = await image.read() img = Image.open(io.BytesIO(contents)) img.verify() # 校验图片完整性 image_stream = io.BytesIO(contents) # 重置流指针 except Exception as e: return JSONResponse( status_code=400, content={"success": False, "message": "无效的图像文件"} ) # ---------------------------- # 2. 人脸处理阶段 # ---------------------------- try: # 将图片转换为numpy数组 image_np = face_recognition.load_image_file(image_stream) # 检测所有人脸位置(格式:top, right, bottom, left) face_locations = face_recognition.face_locations(image_np) if not face_locations: return JSONResponse( content={"success": True, "faces": [], "message": "未检测到人脸"} ) # 提取所有人脸特征编码 face_encodings = face_recognition.face_encodings(image_np, face_locations,num_jitters=8) # ---------------------------- # 3. 人脸比对逻辑 # ---------------------------- faces_result = [] for i, (face_encoding, location) in enumerate(zip(face_encodings, face_locations)): max_similarity = -1 best_name = "unknown" second_similarity=-1#新增:记录次高相似度 # 与本地人脸库逐一比对 for name, encodings in known_faces.items(): for enc in encodings: #标准化当前检测的人脸特征 face_encoding_normalized=face_encoding/np.linalg.norm(face_encoding) #标准化已知人脸特征 enc_normalized=enc/np.linalg.norm(enc) similarity=np.dot(face_encoding_normalized,enc_normalized) if similarity>max_similarity: second_similarity=max_similarity max_similarity=similarity best_name=name elif similarity>second_similarity: second_similarity=similarity # 置信度计算(将相似度映射到[0,1]) if max_similarity>second_similarity+0.1: confidence = round((max_similarity + 1) / 2, 2) else: best_name="unknown" confidence=0.0 # 设置阈值(0.7对应置信度0.85) if max_similarity < 0.7: best_name = "unknown" confidence = 0.0 # 记录人脸信息 face_info = { "location": list(location), # 转换为列表格式 "name": best_name, "confidence": confidence, "max_similarity":max_similarity, "second_similarity":second_similarity } faces_result.append(face_info) # ---------------------------- # 4. 返回最终结果 # ---------------------------- return JSONResponse( content={ "success": True, "faces": faces_result, "message": f"检测到 {len(faces_result)} 张人脸" } ) except Exception as e: # 捕获未处理的异常 return JSONResponse( status_code=500, content={"success": False, "message": f"服务器内部错误: {str(e)}"} ) # ---------------------------- # 服务启动指令 # ---------------------------- if __name__ == "__main__": import uvicorn uvicorn.run(app="Cv:app", host="127.0.0.1", port=8000, reload=True)
1 下一页