FaceRecog_hf / routers /embed_v2.py
tjrlgns09's picture
.
02a7bf9
from fastapi import FastAPI
from fastapi import APIRouter
from fastapi.responses import JSONResponse
import os
import cv2
import faiss
import pickle
import numpy as np
import pandas as pd
from pathlib import Path
import insightface
import albumentations as A
# πŸ”§ 경둜 μ„€μ • (ν•˜λ“œμ½”λ”©)
data_folder = os.path.abspath("person")
save_path = os.path.abspath("embedding/person")
faiss_index_name="face_faiss_index_v2.index"
faiss_label_name="face_faiss_labels_v2.pkl"
traindf_name="train_df.pkl"
# βœ… FastAPI μΈμŠ€ν„΄μŠ€ 생성
router = APIRouter()
# πŸ”§ 증강 μ„€μ •
augment = A.Compose([
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.3),
A.Rotate(limit=15, p=0.3),
])
# πŸš€ λͺ¨λΈ μ΄ˆκΈ°ν™” ν•¨μˆ˜
def load_face_model(device: str = "cpu"):
providers = ["CPUExecutionProvider"] if device == "cpu" else ["CUDAExecutionProvider"]
model = insightface.app.FaceAnalysis(name='buffalo_l', providers=providers)
model.prepare(ctx_id=0 if device != "cpu" else -1)
return model
# πŸš€ μž„λ² λ”© μΆ”μΆœ ν•¨μˆ˜
def get_face_embedding(image_path: str, model, n_augment: int = 5):
img = cv2.imread(str(image_path))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
embeddings = []
# 원본
faces = model.get(img)
if faces:
embeddings.append(faces[0].embedding)
else:
print(f"❌ μ–Όκ΅΄ 인식 μ‹€νŒ¨ (원본): {image_path}")
# 증강
for i in range(n_augment):
augmented = augment(image=img)
img_aug = augmented['image']
faces = model.get(img_aug)
if faces:
embeddings.append(faces[0].embedding)
else:
print(f"❌ μ–Όκ΅΄ 인식 μ‹€νŒ¨ (증강 {i+1}): {image_path}")
if embeddings:
return np.mean(embeddings, axis=0)
else:
print(f"❌ λͺ¨λ“  μ‹œλ„ μ‹€νŒ¨: {image_path}")
return None
# πŸš€ 폴더 μŠ€μΊ” 및 μž„λ² λ”© μΆ”μΆœ
def process_folder(data_folder: str, model) -> pd.DataFrame:
data = []
data_path = Path(data_folder)
for person_dir in data_path.iterdir():
if not person_dir.is_dir():
continue
label = person_dir.name
print(f"β–Ά 폴더: {label}")
count = 0
for image_path in person_dir.glob("*"):
if image_path.suffix.lower() not in [".jpg", ".jpeg", ".png"]:
continue
emb = get_face_embedding(image_path, model)
if emb is not None:
data.append({
"label": label,
"image_path": str(image_path),
"embedding": emb
})
count += 1
print(f"βœ… μ–Όκ΅΄ 인식 성곡 수: {count}")
return pd.DataFrame(data)
# πŸš€ FAISS 인덱슀 생성 및 μ €μž₯
def build_and_save_faiss(train_df: pd.DataFrame, save_path: str):
embeddings = np.stack(train_df['embedding'].values).astype('float32')
embeddings /= np.linalg.norm(embeddings, axis=1, keepdims=True)
index = faiss.IndexFlatIP(embeddings.shape[1])
index.add(embeddings)
faiss.write_index(index, os.path.join(save_path, faiss_index_name))
labels = train_df['label'].tolist()
with open(os.path.join(save_path, faiss_label_name), "wb") as f:
pickle.dump(labels, f)
train_df.to_pickle(os.path.join(save_path, traindf_name))
print("βœ… FAISS 인덱슀 & 라벨 μ €μž₯ μ™„λ£Œ")
return index, labels, train_df
# πŸš€ 전체 μ‹€ν–‰ ν•¨μˆ˜
def run_pipeline(data_folder: str, save_path: str, device: str = "cpu"):
os.makedirs(save_path, exist_ok=True)
print("πŸš€ μ–Όκ΅΄ λͺ¨λΈ λΆˆλŸ¬μ˜€λŠ” 쀑...")
model = load_face_model(device)
print("πŸš€ μž„λ² λ”© μΆ”μΆœ μ‹œμž‘...")
train_df = process_folder(data_folder, model)
print("πŸš€ FAISS 인덱슀 생성 및 μ €μž₯ 쀑...")
index, labels, df = build_and_save_faiss(train_df, save_path)
return len(df)
# βœ… API μ—”λ“œν¬μΈνŠΈ
@router.post("/train")
def train_faces():
try:
count = run_pipeline(data_folder, save_path)
return {"status": "success", "count": count}
except Exception as e:
return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})
"""
# βœ… 둜컬 μ‹€ν–‰
if __name__ == "__main__":
import uvicorn
uvicorn.run("embed_v2:app", host="0.0.0.0", port=8000, reload=True)
"""