Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from deepface import DeepFace | |
| import cv2 | |
| import numpy as np | |
| import os | |
| import shutil | |
| # --- 設定 --- | |
| DB_PATH = "my_db" | |
| if not os.path.exists(DB_PATH): | |
| os.makedirs(DB_PATH, exist_ok=True) | |
| # 処理を間引くためのカウンター | |
| frame_count = 0 | |
| last_status = "Waiting..." | |
| # --- 関数定義 --- | |
| def register_face(image, name): | |
| """画像を1枚だけDBに保存する""" | |
| if image is None or name.strip() == "": | |
| return "名前を入力してください。" | |
| try: | |
| # DBを一度空にして、常に「最新の1枚」とだけ比較するようにする(超軽量化) | |
| for f in os.listdir(DB_PATH): | |
| os.remove(os.path.join(DB_PATH, f)) | |
| safe_name = "".join([c for c in name if c.isalnum()]) | |
| file_path = os.path.join(DB_PATH, f"{safe_name}.jpg") | |
| cv2.imwrite(file_path, cv2.cvtColor(image, cv2.COLOR_RGB2BGR)) | |
| return f"「{safe_name}」をターゲットに設定しました!" | |
| except Exception as e: | |
| return f"エラー: {str(e)}" | |
| def track_oshi(frame): | |
| """Webカメラの映像を解析(1対1の超軽量比較)""" | |
| if frame is None: return None | |
| global frame_count, last_status | |
| frame_count += 1 | |
| output_frame = frame.copy() | |
| # 画面に情報を表示 | |
| cv2.putText(output_frame, f"Frame: {frame_count}", (10, 30), | |
| cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 2) | |
| cv2.putText(output_frame, f"Status: {last_status}", (10, 60), | |
| cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 255), 2) | |
| # 30フレーム(数秒〜10秒に一度)だけ解析を行う | |
| if frame_count % 30 == 0: | |
| db_images = [f for f in os.listdir(DB_PATH) if f.endswith(".jpg")] | |
| if db_images: | |
| last_status = "Analyzing..." | |
| target_path = os.path.join(DB_PATH, db_images[0]) | |
| try: | |
| # findではなく、最も軽い「verify」を使用 | |
| result = DeepFace.verify( | |
| img1_path = frame, | |
| img2_path = target_path, | |
| enforce_detection = False, | |
| detector_backend = 'opencv', | |
| model_name = 'VGG-Face', # 最も標準的なモデル | |
| silent = True | |
| ) | |
| if result["verified"]: | |
| last_status = "TARGET FOUND!" | |
| # 画面中央に大きく表示 | |
| cv2.putText(output_frame, "MATCH!!!", (100, 200), | |
| cv2.FONT_HERSHEY_SIMPLEX, 2.0, (0, 255, 0), 5) | |
| else: | |
| last_status = "Not Match" | |
| except Exception as e: | |
| last_status = "Scan Error" | |
| return output_frame | |
| # --- UI構築 --- | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# 🎥 超軽量版・推し認識プロトタイプ") | |
| gr.Markdown("Hugging Faceの無料CPUでも動くよう、解析頻度を極限まで落としています。") | |
| with gr.Tabs(): | |
| with gr.TabItem("① ターゲット登録"): | |
| reg_in = gr.Image(label="あなたの顔写真") | |
| reg_name = gr.Textbox(label="名前(英数字)", value="Me") | |
| reg_btn = gr.Button("この人をターゲットに設定") | |
| reg_out = gr.Textbox(label="ログ") | |
| reg_btn.click(register_face, inputs=[reg_in, reg_name], outputs=reg_out) | |
| with gr.TabItem("② リアルタイム検証"): | |
| input_video = gr.Image(sources=["webcam"], streaming=True) | |
| output_video = gr.Image(label="解析結果(数秒に1回更新)") | |
| input_video.stream(track_oshi, inputs=[input_video], outputs=[output_video]) | |
| if __name__ == "__main__": | |
| demo.launch() |