File size: 5,396 Bytes
afb9dad
 
2955ae6
a64527c
afb9dad
 
5a474ac
17611a2
5a474ac
a9cec68
 
a64527c
a9cec68
afb9dad
4f37c46
a9cec68
afb9dad
9c2cb20
afb9dad
a9cec68
 
ccd7572
e69763d
afb9dad
a9cec68
ccd7572
a64527c
a9cec68
ccd7572
 
a9cec68
9c2cb20
17611a2
9c2cb20
a9cec68
7135735
 
a9cec68
7135735
a64527c
7135735
e69763d
a9cec68
e69763d
a9cec68
 
 
 
9c2cb20
a9cec68
a64527c
ca5f4b2
a9cec68
ca5f4b2
9c2cb20
e69763d
a9cec68
e69763d
a9cec68
ccd7572
9c2cb20
a64527c
 
ca5f4b2
 
a9cec68
ca5f4b2
a9cec68
ccd7572
a9cec68
ccd7572
 
a9cec68
 
ccd7572
 
 
 
a9cec68
ccd7572
a9cec68
 
a64527c
a9cec68
e69763d
ccd7572
e69763d
ccd7572
 
 
e69763d
 
 
 
 
a64527c
9c2cb20
e69763d
 
a9cec68
e69763d
a64527c
e69763d
ccd7572
e69763d
ccd7572
 
 
a64527c
ccd7572
e69763d
a9cec68
 
 
9c2cb20
afb9dad
a64527c
e69763d
a9cec68
a64527c
 
 
 
a9cec68
a64527c
9c2cb20
afb9dad
 
9c2cb20
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import gradio as gr
import os
import json
import time
from dotenv import load_dotenv

from google import genai
from google.genai import types

# Import the optimized DINO functions
from dino_processor import load_dino_model, process_video_with_dino

# --- Configuration and Initialization ---
load_dotenv()
try:
    GEMINI_CLIENT = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
except KeyError:
    raise gr.Error("FATAL: GEMINI_API_KEY not found. Please set it in your Hugging Face Space secrets.")

DINO_MODEL, DINO_DEVICE = load_dino_model()

# --- Main Gradio Generator Function ---
def full_analysis(video_file_path, user_observations):
    if not video_file_path:
        yield "Please upload a video first.", "", "", None
        return

    # Stage 1: Gemini Analysis
    print("--- Starting Device Analysis ---")
    device_type, condition, reason = "Processing...", "Processing...", "Processing..."
    yield device_type, condition, reason, None

    uploaded_file = None
    try:
        uploaded_file = GEMINI_CLIENT.files.upload(file=video_file_path)
        while uploaded_file.state.name == "PROCESSING":
            time.sleep(5)
            uploaded_file = GEMINI_CLIENT.files.get(name=uploaded_file.name)
        if uploaded_file.state.name != "ACTIVE":
            raise Exception(f"File processing failed for Gemini. State: {uploaded_file.state.name}")
        
        prompt = f"""
        Analyze the provided video and user observations. Respond ONLY with a valid JSON object.
        User Observations: "{user_observations if user_observations else 'None'}"
        Logic:
        1. Is the object an electronic device or white good?
        2. If YES: respond with JSON keys "device_type", "condition" (from "unusable", "poor", "functional", "good", "excellent"), and "reason".
        3. If NO: respond with JSON key "device_type" starting with "Invalid: ".
        """
        model_name = "gemini-1.5-flash-latest" # Using a reliable public model
        config = types.GenerateContentConfig(temperature=0.2, response_mime_type="application/json")
        contents = [uploaded_file, prompt]
        response = GEMINI_CLIENT.models.generate_content(model=f"models/{model_name}", contents=contents, config=config)
        parsed_json = json.loads(response.text)
        device_type = parsed_json.get("device_type", "N/A")
        if "Invalid:" in device_type:
            condition, reason = "N/A", "Object is not a valid device."
        else:
            condition, reason = parsed_json.get("condition", "N/A"), parsed_json.get("reason", "N/A")
        print("--- Device Analysis Complete ---")
    except Exception as e:
        print(f"ERROR during Gemini processing: {e}")
        device_type, condition, reason = f"Error in Gemini processing: {e}", "", ""
    finally:
        if uploaded_file:
            GEMINI_CLIENT.files.delete(name=uploaded_file.name)

    yield device_type, condition, reason, None

    # Stage 2: DINO Analysis
    print("--- Starting DINO Analysis ---")
    try:
        # OPTIMIZATION: This now returns a simple list of overlay image paths
        overlay_images = process_video_with_dino(video_file_path, DINO_MODEL, DINO_DEVICE)
        print("--- DINO Analysis Complete ---")
    except Exception as e:
        print(f"ERROR during DINO processing: {e}")
        reason += f" | DINO Error: {e}"
        overlay_images = None

    # OPTIMIZATION: Final yield with only 4 items
    yield device_type, condition, reason, overlay_images

# --- Gradio Interface (Simplified) ---
theme = gr.themes.Soft(
    primary_hue="green", secondary_hue="emerald"
).set(
    body_background_fill="#E0F2F1", block_background_fill="white",
    block_border_width="1px", block_shadow="*shadow_drop_lg",
    button_primary_background_fill="*primary_500", button_primary_text_color="white",
)

with gr.Blocks(theme=theme) as demo:
    gr.Markdown("# 🧊 KIKERP: AI Assessment Tool")
    gr.Markdown("Upload a video of a device or white good for a complete visual and AI-driven analysis.")
    
    with gr.Row():
        with gr.Column(scale=1):
            video_input = gr.Video(label="Upload or Record Video", sources=["upload", "webcam"], format="mp4")
            observations_input = gr.Textbox(label="Optional: User Observations", placeholder="e.g., Device overheats...")
            submit_button = gr.Button("Run Full Analysis", variant="primary")
        
        with gr.Column(scale=2):
            gr.Markdown("## Device Condition Analysis")
            with gr.Row():
                device_type_output = gr.Textbox(label="Device Type", interactive=False)
                condition_output = gr.Textbox(label="Condition", interactive=False)
                reason_output = gr.Textbox(label="Reason / Details", interactive=False)
    
    gr.Markdown("---")
    
    # OPTIMIZATION: Simplified DINO output section
    gr.Markdown("## Overlayed Heatmaps on Key Frames")
    overlay_gallery = gr.Gallery(label="Overlayed Heatmaps", elem_id="gallery", columns=3)

    submit_button.click(
        fn=full_analysis,
        inputs=[video_input, observations_input],
        # OPTIMIZATION: Updated outputs list to have only 4 items
        outputs=[
            device_type_output, 
            condition_output, 
            reason_output, 
            overlay_gallery
        ],
        show_progress='full'
    )

demo.launch(debug=True)