File size: 4,410 Bytes
eb9f1ec
4c7a58c
c4d7db7
c12cc1c
 
c4d7db7
c12cc1c
0b2272e
c12cc1c
a70eb27
c12cc1c
a70eb27
c12cc1c
 
 
 
 
 
 
 
 
a70eb27
 
c12cc1c
 
c4d7db7
c12cc1c
 
 
4c7a58c
a70eb27
c12cc1c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a70eb27
 
 
 
c12cc1c
 
a70eb27
c12cc1c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a70eb27
c12cc1c
 
eb9f1ec
c12cc1c
 
 
 
a70eb27
c12cc1c
 
 
c4d7db7
c12cc1c
eb9f1ec
 
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
import gradio as gr
import google.generativeai as genai
import os
import json
import re

# 配置 API
api_key = os.getenv("MY_API_KEY")
genai.configure(api_key=api_key)

# --- 定义 CSS 样式 ---
custom_css = """
body { background-color: #0b0f14; }
.report-container { background: #111827; border: 1px solid #1f2937; border-radius: 12px; padding: 20px; color: #e5e7eb; font-family: 'Inter', sans-serif; }
.header-row { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #374151; padding-bottom: 15px; margin-bottom: 20px; }
.score-circle { background: radial-gradient(circle, #3b82f6, #1d4ed8); width: 60px; height: 60px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: bold; color: white; box-shadow: 0 0 15px rgba(59, 130, 246, 0.5); }
.section-title { color: #60a5fa; font-size: 16px; font-weight: bold; margin: 15px 0 10px 0; display: flex; align-items: center; gap: 8px; }
.card { background: #1f2937; border-radius: 8px; padding: 12px; margin-bottom: 10px; border-left: 4px solid #3b82f6; }
.tag-container { display: flex; gap: 8px; margin-top: 10px; }
.tag { background: #374151; padding: 4px 10px; border-radius: 4px; font-size: 12px; color: #9ca3af; border: 1px solid #4b5563; }
.suggestion { background: #064e3b; border-left: 4px solid #10b981; padding: 10px; border-radius: 6px; margin-top: 8px; font-size: 14px; }
"""

def parse_and_format(ai_response):
    """提取 JSON 并渲染 HTML"""
    try:
        # 尝试从回复中找到 JSON 部分
        json_str = re.search(r'\{.*\}', ai_response, re.DOTALL).group()
        data = json.loads(json_str)
        
        html = f"""
        <div class="report-container">
            <div class="header-row">
                <div>
                    <h2 style="margin:0; color:white;">灯光分析报告</h2>
                    <div class="tag-container">
                        <span class="tag">UE5.4</span><span class="tag">Lumen</span><span class="tag">Cinema_Light</span>
                    </div>
                </div>
                <div class="score-circle">{data.get('score', '??')}</div>
            </div>
            
            <div class="section-title">🎨 色彩与氛围</div>
            <div class="card">{data.get('atmosphere', '')}</div>
            
            <div class="section-title">⚙️ 技术优化分析</div>
            <div class="card" style="border-left-color: #f59e0b;">
                <p style="margin:0; font-size:14px;">{data.get('technical', '')}</p>
            </div>
            
            <div class="section-title">🚀 灯光优化建议</div>
            {" ".join([f'<div class="suggestion">💡 {s}</div>' for s in data.get('suggestions', [])])}
        </div>
        """
        return html
    except:
        # 如果解析 JSON 失败,回退到 Markdown 显示
        return f"<div class='report-container'>{ai_response}</div>"

def analyze_lighting(image):
    if image is None: return "请上传图片"
    try:
        model = genai.GenerativeModel('gemini-3-flash-preview')
        # 强制 AI 输出 JSON 格式
        prompt = """
        你是一位顶级游戏灯光艺术总监。请分析这张 UE5 截图,并严格按以下 JSON 格式输出(不要有其他废话):
        {
          "score": "评分数字",
          "atmosphere": "分析色温对比、氛围感",
          "technical": "分析曝光、死黑、体积雾、GI表现",
          "suggestions": ["建议1", "建议2", "建议3"]
        }
        请用专业中文。
        """
        response = model.generate_content([prompt, image])
        return parse_and_format(response.text)
    except Exception as e:
        return f"<div style='color:red;'>错误: {str(e)}</div>"

# --- 构建 UI ---
with gr.Blocks(css=custom_css) as demo:
    with gr.Row():
        with gr.Column(scale=1):
            gr.Markdown("### 📷 场景画面上传")
            input_img = gr.Image(label=None, type="pil")
            btn = gr.Button("生成专业灯光分析报告", variant="primary")
            
        with gr.Column(scale=1):
            gr.Markdown("### 📊 分析结果预览")
            output_html = gr.HTML("<div style='color:#666;'>等待分析数据...</div>")
            
    btn.click(analyze_lighting, inputs=[input_img], outputs=[output_html])

demo.launch()