File size: 3,813 Bytes
f8c3406
 
 
 
 
 
 
 
 
 
 
 
b04cf7c
f8c3406
b04cf7c
f8c3406
 
 
 
b04cf7c
f8c3406
b04cf7c
f8c3406
b04cf7c
 
 
 
8cef4d5
f8c3406
b04cf7c
 
f8c3406
 
 
 
b04cf7c
 
8cef4d5
b04cf7c
f8c3406
55048e0
 
b04cf7c
 
 
 
 
f8c3406
b04cf7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f8c3406
b04cf7c
f8c3406
 
b04cf7c
 
8cef4d5
f8c3406
b04cf7c
 
 
 
 
 
8cef4d5
b04cf7c
 
 
8cef4d5
 
 
f8c3406
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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()