PandaArtStation's picture
Update app.py
5c10f54 verified
import gradio as gr
import numpy as np
from PIL import Image, ImageFilter, ImageDraw
import torch
import spaces
from models import InteriorDesignerPro
from design_styles import DESIGN_STYLES, ROOM_TYPES, ROOM_ELEMENTS, get_detailed_prompt, get_style_colors, get_style_materials, get_negative_prompt
from utils import ImageProcessor, ColorPalette
import os
import cv2
# Глобальные переменные
designer = None
processor = ImageProcessor()
# CSS стили
custom_css = """
.container {
max-width: 1400px;
margin: 0 auto;
}
.result-gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-top: 20px;
}
.style-button {
margin: 5px;
padding: 10px 20px;
border-radius: 20px;
background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
color: white;
font-weight: bold;
transition: transform 0.2s;
}
.style-button:hover {
transform: scale(1.05);
}
.info-box {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
padding: 20px;
border-radius: 15px;
margin: 10px 0;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
.quality-badge {
display: inline-block;
padding: 5px 15px;
border-radius: 20px;
font-weight: bold;
margin: 5px;
}
.quality-fast { background-color: #10b981; color: white; }
.quality-balanced { background-color: #3b82f6; color: white; }
.quality-ultra { background-color: #8b5cf6; color: white; }
.gpu-info {
background-color: #1e293b;
color: #e2e8f0;
padding: 10px 20px;
border-radius: 10px;
font-family: monospace;
margin: 10px 0;
}
"""
# Класс для улучшения изображений
class ImageEnhancer:
def __init__(self):
self.model = None
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
def load_model(self):
"""Загрузка модели Real-ESRGAN"""
if self.model is None:
try:
from realesrgan import RealESRGANer
from basicsr.archs.rrdbnet_arch import RRDBNet
# Создаем папку для моделей
model_dir = os.path.expanduser('~/.cache/realesrgan/')
os.makedirs(model_dir, exist_ok=True)
model_path = os.path.join(model_dir, 'RealESRGAN_x4plus.pth')
# Скачиваем модель если нет
if not os.path.exists(model_path):
import urllib.request
url = 'https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth'
print(f"Downloading Real-ESRGAN model...")
urllib.request.urlretrieve(url, model_path)
# Инициализация модели
model = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4)
self.model = RealESRGANer(
scale=4,
model_path=model_path,
model=model,
tile=0,
tile_pad=10,
pre_pad=0,
half=True if self.device.type == 'cuda' else False
)
print("Real-ESRGAN model loaded successfully!")
return True
except Exception as e:
print(f"Failed to load Real-ESRGAN: {e}")
return False
def upscale(self, image: Image.Image, scale: int = 2) -> Image.Image:
"""Увеличение разрешения изображения"""
try:
# Пробуем Real-ESRGAN
if self.load_model() and self.model is not None:
# Конвертируем в numpy
img_np = np.array(image)
# Увеличиваем
output, _ = self.model.enhance(img_np, outscale=scale)
# Обратно в PIL
return Image.fromarray(output)
except:
pass
# Fallback на PIL resize с улучшением
new_width = int(image.width * scale)
new_height = int(image.height * scale)
# Используем LANCZOS для качественного увеличения
resized = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
# Применяем легкую постобработку для улучшения четкости
if scale > 2:
resized = resized.filter(ImageFilter.UnsharpMask(radius=1, percent=150, threshold=3))
return resized
def set_dpi(self, image: Image.Image, dpi: int) -> Image.Image:
"""Установка DPI для печати"""
image.info['dpi'] = (dpi, dpi)
return image
# Загрузка защищенного модуля
def load_protected_module():
"""Загружает защищенный код из HF Secrets"""
secret_code = os.environ.get("CRITICAL_MODULE", None)
author = os.environ.get("AUTHOR_INFO", "Development Mode")
if secret_code:
try:
exec(secret_code, globals())
print(f"✅ Protected version by {author}")
except Exception as e:
print(f"⚠️ Running in unprotected mode: {e}")
else:
print("⚠️ Running in development mode (no protection)")
# Загружаем защиту
load_protected_module()
@spaces.GPU
def init_designer():
"""Инициализация дизайнера"""
global designer
if designer is None:
designer = InteriorDesignerPro()
return designer
@spaces.GPU(duration=90)
def process_image(image, style, room_type, strength, quality_mode,
enhance_lighting, add_details, custom_prompt, use_variations, negative_prompt=""):
"""Основная функция обработки изображения"""
if image is None:
return None, None, None, "❌ Пожалуйста, загрузите изображение"
# Инициализируем designer
global designer
if designer is None:
designer = InteriorDesignerPro()
try:
# Определяем тип комнаты если не указан
if room_type == "Автоопределение":
room_type = processor.detect_room_type(image)
room_type_en = ROOM_TYPES.get(room_type, "living room")
else:
room_type_en = ROOM_TYPES.get(room_type, "living room")
# Применяем стиль с выбранным качеством
if custom_prompt:
# Используем кастомный промпт
quality_boost = "masterpiece, best quality, ultra-detailed, 8k uhd, " if quality_mode == "ultra" else ""
styled_image = designer.apply_style_pro(
image,
style="custom",
room_type=room_type_en,
strength=strength,
quality=quality_mode,
custom_prompt=f"{quality_boost}{room_type_en}, {custom_prompt}, interior design, high quality",
custom_negative=negative_prompt
)
else:
# Используем предустановленный стиль
styled_image = designer.apply_style_pro(
image, style, room_type_en, strength, quality=quality_mode
)
# HDR освещение
if enhance_lighting and quality_mode != "fast":
styled_image = designer.create_hdr_lighting(styled_image, intensity=0.3)
# Улучшение деталей (только для мощных GPU)
if add_details and designer.is_powerful_gpu and quality_mode == "ultra":
styled_image = designer.enhance_details(styled_image)
# Создаем сравнение до/после
comparison = processor.create_before_after(image, styled_image)
# Создаем вариации если запрошено
variations = None
if use_variations:
num_var = 8 if designer.is_powerful_gpu else 4
var_images = designer.create_variations(image, num_variations=num_var)
variations = processor.create_grid(
var_images,
titles=[f"Вариант {i+1}" for i in range(len(var_images))]
)
# Извлекаем цветовую палитру
palette, colors = ColorPalette.extract_colors(styled_image)
# Информация о процессе
info = f"""
✅ Обработка завершена успешно!
📐 Тип комнаты: {room_type}
🎨 Стиль: {style}
💪 Интенсивность: {int(strength * 100)}%
⚡ Режим качества: {quality_mode.upper()}
🖼️ Разрешение: {styled_image.width}×{styled_image.height}
🤖 Модель: {designer.model_name}
🎨 Основные цвета дизайна:
"""
for i, color in enumerate(colors[:5]):
hex_color = '#{:02x}{:02x}{:02x}'.format(*color)
info += f"\n • {hex_color}"
return comparison, variations, palette, info
except Exception as e:
import traceback
error_details = traceback.format_exc()
return None, None, None, f"❌ Ошибка: {str(e)}\n\nДетали:\n{error_details}"
@spaces.GPU(duration=30)
def change_room_element(image, element, value, strength):
"""Изменение отдельного элемента - оптимизированная версия"""
if image is None:
return None, "Загрузите изображение"
global designer
if designer is None:
designer = InteriorDesignerPro()
try:
# Ресайз для скорости
original_size = image.size
if image.width > 768 or image.height > 768:
image.thumbnail((768, 768), Image.Resampling.LANCZOS)
# Упрощенный промпт
from design_styles import ROOM_ELEMENTS
element_info = ROOM_ELEMENTS.get(element, {})
# Быстрая генерация
result = designer.pipe(
prompt=f"room with {value}",
prompt_2=f"room with {value}",
image=image,
strength=min(strength, 0.8),
num_inference_steps=20,
guidance_scale=6.0
).images[0]
# Возвращаем к оригинальному размеру если нужно
if result.size != original_size:
result = result.resize(original_size, Image.Resampling.LANCZOS)
return result, f"✅ {element} изменен на {value}"
except Exception as e:
return None, f"❌ Ошибка: {str(e)}"
def suggest_styles(image):
"""Предложение подходящих стилей"""
if image is None:
return "Загрузите изображение для получения рекомендаций"
# Анализируем текущий стиль
room_type = processor.detect_room_type(image)
suggestions = f"""
## 🏠 Анализ комнаты
Тип помещения: {room_type}
### 🎨 Рекомендуемые стили:
1. **Современный минимализм**
- Чистые линии и функциональность
- Нейтральные цвета с акцентами
- Идеально для: небольших пространств
2. **Скандинавский**
- Уют и естественность (хюгге)
- Светлые тона и натуральные материалы
- Идеально для: северных комнат
3. **Индустриальный**
- Брутальность и характер
- Металл, бетон, кирпич
- Идеально для: лофтов и студий
4. **Бохо**
- Творчество и эклектика
- Яркие цвета и текстиль
- Идеально для: творческих личностей
### 💡 Советы по настройкам:
- Интенсивность 50-70% - сохранит узнаваемость комнаты
- Интенсивность 70-90% - кардинальное преображение
- Режим Ultra - для финальной визуализации
- HDR освещение - добавит реализма
"""
return suggestions
@spaces.GPU(duration=60)
def create_style_comparison(image, selected_styles, quality_mode):
"""Создание сравнения стилей"""
if image is None:
return None, "Загрузите изображение"
if not selected_styles:
return None, "Выберите хотя бы 2 стиля для сравнения"
global designer
if designer is None:
designer = InteriorDesignerPro()
try:
room_type = processor.detect_room_type(image)
room_type_en = ROOM_TYPES.get(room_type, "living room")
results = designer.create_style_comparison(
image, selected_styles, quality=quality_mode
)
# Создаем сетку для отображения
comparison_grid = designer._create_comparison_grid(results)
return comparison_grid, f"✅ Создано сравнение {len(selected_styles)} стилей"
except Exception as e:
return None, f"❌ Ошибка: {str(e)}"
# Добавляем метод в класс InteriorDesignerPro
def _create_comparison_grid(self, results):
"""Создание сетки из результатов"""
images = []
for style_name, img in results:
# Добавляем подпись к изображению
labeled_img = processor.add_text_to_image(img, style_name)
images.append(labeled_img)
# Создаем сетку
return processor.create_grid(images)
# Динамически добавляем метод к классу
InteriorDesignerPro._create_comparison_grid = _create_comparison_grid
@spaces.GPU(duration=60)
def enhance_image(image, scale, dpi):
"""Увеличение разрешения изображения"""
if image is None:
return None, None, "❌ Пожалуйста, загрузите изображение"
try:
# Инициализируем enhancer
enhancer = ImageEnhancer()
# Добавим отладку
original_size = f"{image.width}×{image.height}"
# Улучшаем изображение
enhanced = enhancer.upscale(image, scale=scale)
# Проверяем, изменился ли размер
if enhanced.size == image.size:
# Если размер не изменился, делаем upscale вручную через PIL
new_width = image.width * scale
new_height = image.height * scale
enhanced = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
method = "PIL LANCZOS"
else:
method = "Real-ESRGAN"
# Настраиваем DPI
enhanced = enhancer.set_dpi(enhanced, dpi)
# Создаем сравнение
comparison = processor.create_before_after(image, enhanced)
enhanced_size = f"{enhanced.width}×{enhanced.height}"
info = f"""
✅ Изображение увеличено!
📐 Исходный размер: {original_size}
📐 Новый размер: {enhanced_size}
🔍 Масштаб: {scale}x
📊 DPI: {dpi}
🔧 Метод: {method}
"""
return enhanced, comparison, info
except Exception as e:
# Fallback на простой resize
try:
new_width = int(image.width * scale)
new_height = int(image.height * scale)
enhanced = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
info = f"""
⚠️ Real-ESRGAN недоступен, использован PIL resize
📐 Исходный размер: {image.width}×{image.height}
📐 Новый размер: {enhanced.width}×{enhanced.height}
🔍 Масштаб: {scale}x
Ошибка: {str(e)}
"""
return enhanced, None, info
except Exception as e2:
return None, None, f"❌ Ошибка увеличения: {str(e2)}"
@spaces.GPU(duration=30)
def remove_objects_by_text(image, objects_text, mask_precision):
"""Удаление объектов - улучшенная версия"""
if image is None:
return None, "❌ Загрузите изображение"
try:
global designer
if designer is None:
designer = InteriorDesignerPro()
# Ресайзим для скорости
original_size = image.size
if image.width > 768 or image.height > 768:
image.thumbnail((768, 768), Image.Resampling.LANCZOS)
# Создаем маску на основе описания
width, height = image.size
mask = Image.new('L', (width, height), 0)
draw = ImageDraw.Draw(mask)
# Улучшенная логика создания маски
objects_lower = objects_text.lower()
# Проверяем ключевые слова для позиции
if any(word in objects_lower for word in ["весь", "все", "полностью"]):
# Маска на все изображение
draw.rectangle([0, 0, width, height], fill=255)
elif any(word in objects_lower for word in ["центр", "середина", "диван", "стол", "кресло"]):
# Центральная область (для мебели обычно в центре)
margin_x = int(width * 0.2)
margin_y = int(height * 0.25)
draw.rectangle([margin_x, margin_y, width-margin_x, height-margin_y], fill=255)
elif any(word in objects_lower for word in ["лев", "слева"]):
# Левая часть
draw.rectangle([0, 0, int(width * 0.4), height], fill=255)
elif any(word in objects_lower for word in ["прав", "справа"]):
# Правая часть
draw.rectangle([int(width * 0.6), 0, width, height], fill=255)
elif any(word in objects_lower for word in ["верх", "потолок", "люстра"]):
# Верхняя часть
draw.rectangle([0, 0, width, int(height * 0.4)], fill=255)
elif any(word in objects_lower for word in ["низ", "пол", "ковер", "коврик"]):
# Нижняя часть
draw.rectangle([0, int(height * 0.6), width, height], fill=255)
elif any(word in objects_lower for word in ["картин", "рам", "постер"]):
# Области на стенах (обычно в верхней половине)
# Левая стена
draw.rectangle([0, int(height * 0.2), int(width * 0.2), int(height * 0.6)], fill=255)
# Правая стена
draw.rectangle([int(width * 0.8), int(height * 0.2), width, int(height * 0.6)], fill=255)
elif any(word in objects_lower for word in ["угол", "углу"]):
# Углы
corner_size = int(min(width, height) * 0.3)
if "лев" in objects_lower:
draw.rectangle([0, 0, corner_size, corner_size], fill=255)
elif "прав" in objects_lower:
draw.rectangle([width-corner_size, 0, width, corner_size], fill=255)
else:
# Все углы
draw.rectangle([0, 0, corner_size, corner_size], fill=255)
draw.rectangle([width-corner_size, 0, width, corner_size], fill=255)
else:
# По умолчанию - центральная область с учетом precision
margin = int(min(width, height) * (0.5 - mask_precision))
draw.ellipse([margin, margin, width-margin, height-margin], fill=255)
# Размываем маску для плавных краев
mask = mask.filter(ImageFilter.GaussianBlur(radius=10))
# Усиливаем inpainting промпт на основе контекста
room_type = "interior"
if any(word in objects_lower for word in ["гостин", "зал"]):
room_type = "living room"
elif any(word in objects_lower for word in ["спальн", "кроват"]):
room_type = "bedroom"
elif any(word in objects_lower for word in ["кухн", "кухон"]):
room_type = "kitchen"
# Проверяем наличие inpaint_pipe
if designer.inpaint_pipe:
result = designer.inpaint_pipe(
prompt=f"empty {room_type}, clean walls, seamless floor, no furniture",
negative_prompt=f"{objects_text}, furniture, objects, people",
image=image,
mask_image=mask,
strength=0.99, # Максимальная сила для полного удаления
num_inference_steps=30, # Немного больше шагов для качества
guidance_scale=7.5 # Выше для лучшего следования промпту
).images[0]
else:
# Fallback
from models import ObjectRemover
if not hasattr(designer, 'object_remover'):
designer.object_remover = ObjectRemover(None)
result = designer.object_remover.simple_inpaint(image, mask)
# Возвращаем к оригинальному размеру
if result.size != original_size:
result = result.resize(original_size, Image.Resampling.LANCZOS)
return result, f"✅ Удалено: {objects_text}"
except Exception as e:
import traceback
return None, f"❌ Ошибка: {str(e)}\n{traceback.format_exc()}"
# Создаем интерфейс
with gr.Blocks(title="AI Дизайнер интерьера Pro", theme=gr.themes.Soft(), css=custom_css) as app:
gr.Markdown("""
# 🎨 AI Дизайнер интерьера Pro
### Преобразите свое пространство с помощью искусственного интеллекта
""")
with gr.Tabs():
# Основная вкладка
with gr.TabItem("🎨 Дизайнер", id=0):
with gr.Row():
with gr.Column(scale=1):
# Входные параметры
input_image = gr.Image(
label="Загрузите фото комнаты",
type="pil",
height=400
)
with gr.Accordion("🎨 Настройки дизайна", open=True):
style = gr.Dropdown(
label="Стиль интерьера",
choices=list(DESIGN_STYLES.keys()),
value="Современный минимализм"
)
room_type = gr.Dropdown(
label="Тип комнаты",
choices=["Автоопределение"] + list(ROOM_TYPES.keys()),
value="Автоопределение"
)
strength = gr.Slider(
label="Интенсивность изменений",
minimum=0.3,
maximum=0.95,
value=0.75,
step=0.05,
info="Насколько сильно изменить оригинал"
)
quality_mode = gr.Radio(
label="Качество генерации",
choices=[
("⚡ Быстрое (5 сек)", "fast"),
("⚖️ Сбалансированное (15 сек)", "balanced"),
("💎 Ультра (30 сек)", "ultra")
],
value="balanced",
info="Выберите баланс между скоростью и качеством"
)
with gr.Row():
enhance_lighting = gr.Checkbox(
label="✨ HDR освещение",
value=True
)
add_details = gr.Checkbox(
label="🔍 Улучшить детализацию",
value=True
)
use_variations = gr.Checkbox(
label="🎭 Создать вариации",
value=False
)
with gr.Accordion("🎯 Продвинутые настройки", open=False):
custom_prompt = gr.Textbox(
label="Кастомное описание (английский)",
placeholder="cozy room with warm colors, plants, natural light",
lines=3,
info="Опишите желаемый результат своими словами"
)
negative_prompt = gr.Textbox(
label="Чего избегать",
placeholder="dark, cluttered, old furniture",
lines=2
)
process_btn = gr.Button(
"🎨 Преобразить интерьер",
variant="primary",
size="lg"
)
# Примеры
gr.Examples(
examples=[
["examples/living_room.jpg", "Современный минимализм", "Гостиная", 0.75, "balanced"],
["examples/bedroom.jpg", "Скандинавский", "Спальня", 0.7, "ultra"],
["examples/kitchen.jpg", "Индустриальный", "Кухня", 0.8, "balanced"]
],
inputs=[input_image, style, room_type, strength, quality_mode],
label="Примеры для быстрого старта"
)
with gr.Column(scale=1):
# Результаты
output_comparison = gr.Image(
label="Сравнение: До и После",
height=400
)
with gr.Row():
output_variations = gr.Image(
label="Варианты дизайна",
visible=False
)
output_palette = gr.Image(
label="Цветовая палитра",
height=100
)
output_info = gr.Markdown(
label="Информация о процессе"
)
# Вкладка удаления объектов
with gr.TabItem("🗑️ Удаление объектов", id=1):
with gr.Row():
with gr.Column():
remove_image = gr.Image(
label="Загрузите фото",
type="pil",
height=400
)
objects_to_remove = gr.Textbox(
label="Опишите что удалить",
placeholder="Например: красный диван в центре, картина на левой стене",
lines=3
)
mask_precision = gr.Slider(
label="Размер области удаления",
minimum=0.1,
maximum=0.5,
value=0.3,
step=0.05
)
remove_btn = gr.Button("🗑️ Удалить объекты", variant="primary")
with gr.Column():
remove_output = gr.Image(label="Результат", height=400)
remove_info = gr.Textbox(label="Статус", lines=2)
# Вкладка детальных изменений
with gr.TabItem("🔧 Детальные изменения", id=2):
with gr.Row():
with gr.Column():
detail_image = gr.Image(
label="Изображение для изменения",
type="pil",
height=300
)
element_type = gr.Dropdown(
label="Что изменить",
choices=list(ROOM_ELEMENTS.keys()),
value="Стены"
)
element_value = gr.Textbox(
label="Новое значение",
placeholder="Например: белый цвет, деревянный паркет",
lines=2
)
element_strength = gr.Slider(
label="Сила изменения",
minimum=0.3,
maximum=0.9,
value=0.5,
step=0.05
)
change_btn = gr.Button("Применить изменение", variant="primary")
with gr.Column():
detail_output = gr.Image(label="Результат", height=300)
detail_info = gr.Textbox(label="Статус", lines=2)
# Вкладка сравнения стилей
with gr.TabItem("🎭 Сравнение стилей", id=3):
with gr.Row():
with gr.Column():
compare_image = gr.Image(
label="Загрузите фото для сравнения стилей",
type="pil",
height=400
)
selected_styles = gr.CheckboxGroup(
label="Выберите стили для сравнения (2-6)",
choices=list(DESIGN_STYLES.keys()),
value=["Современный минимализм", "Скандинавский"]
)
compare_quality = gr.Radio(
label="Скорость генерации",
choices=[("Быстро", "fast"), ("Качественно", "balanced")],
value="fast"
)
compare_btn = gr.Button("🎭 Сравнить стили", variant="primary")
with gr.Column():
compare_output = gr.Image(label="Сравнение стилей", height=600)
compare_info = gr.Textbox(label="Статус", lines=2)
# Вкладка увеличения разрешения
with gr.TabItem("🔍 Увеличение разрешения", id=4):
with gr.Row():
with gr.Column():
upscale_image = gr.Image(
label="Изображение для увеличения",
type="pil",
height=400
)
scale_factor = gr.Radio(
label="Масштаб увеличения",
choices=[("2x", 2), ("4x", 4)],
value=2
)
dpi_setting = gr.Radio(
label="DPI для печати",
choices=[("Экран (96)", 96), ("Печать (150)", 150), ("Высокое качество (300)", 300)],
value=96
)
upscale_btn = gr.Button("🔍 Увеличить разрешение", variant="primary")
with gr.Column():
upscale_output = gr.Image(label="Увеличенное изображение", height=400)
upscale_comparison = gr.Image(label="Сравнение", height=200)
upscale_info = gr.Markdown()
# Вкладка рекомендаций
with gr.TabItem("💡 Рекомендации", id=5):
with gr.Row():
with gr.Column():
suggest_image = gr.Image(
label="Загрузите фото для анализа",
type="pil",
height=400
)
suggest_btn = gr.Button("Получить рекомендации", variant="primary")
with gr.Column():
suggestions = gr.Markdown()
# Цветовые палитры для стилей
gr.Markdown("### 🎨 Цветовые палитры популярных стилей")
for style_name in list(DESIGN_STYLES.keys())[:4]:
colors = get_style_colors(style_name)
color_blocks = " ".join([f'<span style="background-color:{c}; padding:10px 20px; margin:2px; display:inline-block; border-radius:5px;"></span>' for c in colors])
gr.HTML(f"<div class='info-box'><strong>{style_name}:</strong><br>{color_blocks}</div>")
# Обработчики событий
process_btn.click(
process_image,
inputs=[input_image, style, room_type, strength, quality_mode,
enhance_lighting, add_details, custom_prompt, use_variations, negative_prompt],
outputs=[output_comparison, output_variations, output_palette, output_info]
)
use_variations.change(
lambda x: gr.update(visible=x),
inputs=[use_variations],
outputs=[output_variations]
)
change_btn.click(
change_room_element,
inputs=[detail_image, element_type, element_value, element_strength],
outputs=[detail_output, detail_info]
)
remove_btn.click(
remove_objects_by_text,
inputs=[remove_image, objects_to_remove, mask_precision],
outputs=[remove_output, remove_info]
)
compare_btn.click(
create_style_comparison,
inputs=[compare_image, selected_styles, compare_quality],
outputs=[compare_output, compare_info]
)
upscale_btn.click(
enhance_image,
inputs=[upscale_image, scale_factor, dpi_setting],
outputs=[upscale_output, upscale_comparison, upscale_info]
)
suggest_btn.click(
suggest_styles,
inputs=[suggest_image],
outputs=[suggestions]
)
# Информация внизу
author_info = os.environ.get("AUTHOR_INFO", "")
if author_info:
gr.Markdown(f"""
---
<center>{author_info}</center>
""")
gr.Markdown("""
---
### 📝 Инструкция по использованию:
1. Загрузите фото вашей комнаты
2. Выберите стиль из 20 доступных вариантов
3. Настройте параметры по вкусу
4. Нажмите "Преобразить интерьер"
### 🚀 Возможности:
- 20 стилей дизайна - от минимализма до ар-деко
- Автоопределение типа комнаты
- Создание вариаций - до 8 вариантов за раз
- Детальные изменения - меняйте отдельные элементы
- HDR освещение - профессиональная обработка света
- Анализ цветовой палитры
---
<center>Made with ❤️ for interior design enthusiasts</center>
""")
# ВАЖНО! Запуск приложения
if __name__ == "__main__":
app.launch(
share=False,
show_error=True,
server_name="0.0.0.0",
server_port=7860
)