import gradio as gr
import spaces
import torch
import numpy as np
from PIL import Image, ImageDraw
import json
import base64
import io
from typing import List, Dict, Tuple, Optional
import warnings
try:
from dream_renderer import DreamRendererPipeline
except ImportError:
print("Warning: dream_renderer 模块未找到。将使用演示模式。")
# raise
warnings.filterwarnings("ignore")
# 全局变量
pipeline = None
current_bbox_data = []
@spaces.GPU
def initialize_pipeline():
"""初始化DreamRenderer管道"""
global pipeline
try:
if pipeline is None:
pipeline = DreamRendererPipeline()
# 预加载模型以节省时间
success = pipeline.load_model()
if success:
return "✅ DreamRenderer管道已成功初始化并加载模型!"
else:
return "⚠️ DreamRenderer管道已初始化,但模型加载失败。将使用演示模式。"
else:
return "✅ DreamRenderer管道已经初始化完成!"
except Exception as e:
return f"❌ 初始化失败: {str(e)}"
def load_bbox_component():
"""加载边界框绘制组件"""
try:
with open('bbox_component.html', 'r', encoding='utf-8') as f:
content = f.read()
return content
except FileNotFoundError:
# 返回简化的HTML内容
return """
',
'
🎯 边界框描述编辑
'
]
for i, bbox in enumerate(bbox_data, 1):
x = bbox.get('x', 0)
y = bbox.get('y', 0)
width = bbox.get('width', 0)
height = bbox.get('height', 0)
label = bbox.get('label', f'区域{i}')
prompt = bbox.get('prompt', '') # 获取已有的提示词
info_lines.extend([
f"🎯 边界框 {i}:",
f" 📍 位置: ({x:.3f}, {y:.3f})",
f" 📏 大小: {width:.3f} × {height:.3f}",
f" 🏷️ 标签: {label}",
f" 💬 描述: {prompt or '(请在下方输入描述)'}",
""
])
# 为每个边界框生成编辑界面
color = f"hsl({(i-1) * 60}, 70%, 50%)"
edit_html_lines.extend([
f'
',
f'
',
f'
',
f'
边界框 {i} - {label}',
f'
({x:.2f}, {y:.2f}) {width:.2f}×{height:.2f}',
f'
',
f'
',
f' ',
f' ',
f'
',
f'
',
f' ',
f' ',
f'
',
f'
',
f' ',
f'
',
f'
'
])
edit_html_lines.extend([
'
',
'
',
'
',
f' ✅ 共 {len(bbox_data)} 个边界框',
'
修改描述后会自动保存',
'
',
'
',
'
',
'
',
'
'
])
info_lines.extend([
"💡 使用说明:",
"• 在画布上拖拽绘制新的边界框",
"• 在右侧为每个框输入具体描述",
"• 每个框可以有不同的生成内容",
"• 描述越详细,生成效果越好"
])
print(f"DEBUG: 边界框数据已更新: {len(current_bbox_data)}个") # 调试信息
return "\n".join(info_lines), "\n".join(edit_html_lines)
except json.JSONDecodeError:
current_bbox_data = []
return f"❌ 边界框数据格式错误\n\n原始数据: {bbox_json[:200]}...", ""
except Exception as e:
current_bbox_data = []
return f"❌ 处理边界框数据时出错: {str(e)}", ""
@spaces.GPU
def generate_image_with_bbox(prompt: str, negative_prompt: str,
num_inference_steps: int, guidance_scale: float,
width: int, height: int, seed: int, use_seed: bool):
"""使用边界框生成图像"""
global pipeline, current_bbox_data
if pipeline is None:
return None, "❌ 请先初始化DreamRenderer管道!"
if not prompt.strip():
return None, "❌ 请输入提示词!"
try:
# 设置种子
actual_seed = seed if use_seed else None
# 生成图像
image = pipeline.generate_image(
prompt=prompt,
bbox_data=current_bbox_data,
negative_prompt=negative_prompt,
num_inference_steps=num_inference_steps,
guidance_scale=guidance_scale,
width=width,
height=height,
seed=actual_seed
)
info = f"✅ 图像生成成功!\n"
info += f"🔸 使用边界框: {len(current_bbox_data)}个\n"
info += f"🔸 推理步数: {num_inference_steps}\n"
info += f"🔸 引导强度: {guidance_scale}\n"
info += f"🔸 图像尺寸: {width}×{height}\n"
if actual_seed is not None:
info += f"🔸 随机种子: {actual_seed}"
return image, info
except Exception as e:
return None, f"❌ 生成图像时出错: {str(e)}"
def create_interface():
"""创建Gradio界面"""
# 自定义CSS
css = """
.main-container {
max-width: 1400px;
margin: 0 auto;
}
.bbox-container {
border: 2px solid #e1e5e9;
border-radius: 12px;
padding: 20px;
margin: 15px 0;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
}
.generate-btn {
background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
border: none;
border-radius: 25px;
padding: 15px 35px;
color: white;
font-weight: bold;
font-size: 18px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
transition: all 0.3s ease;
}
.generate-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0,0,0,0.3);
}
.init-btn {
background: linear-gradient(45deg, #667eea, #764ba2);
border: none;
border-radius: 20px;
color: white;
font-weight: bold;
padding: 12px 25px;
}
"""
with gr.Blocks(css=css, title="DreamRenderer - Multi-Instance Control", theme=gr.themes.Soft()) as demo:
gr.HTML("""