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 urllib.request from typing import List, Tuple, Optional # Загрузка защитного модуля def load_protected_module(): """Загружает защищенный код из HF Secrets""" secret_code = os.environ.get("CRITICAL_MODULE", None) author = os.environ.get("AUTHOR_INFO", "Unauthorized") 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() # Глобальные переменные designer = None processor = ImageProcessor() # CSS стили - премиальный минималистичный дизайн custom_css = """ /* Импорт премиальных шрифтов */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Playfair+Display:wght@400;700&display=swap'); /* Основные стили */ .gradio-container { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; background-color: #FAFAFA; color: #1A1A1A; } /* Премиальная типографика */ h1, h2, h3 { font-family: 'Playfair Display', serif; font-weight: 400; letter-spacing: -0.02em; color: #0A0A0A; } h1 { font-size: 3rem; margin-bottom: 0.5rem; } h2 { font-size: 2rem; margin-top: 3rem; margin-bottom: 1.5rem; } /* Золотые акценты */ .gold-accent { color: #D4AF37; } /* Кнопки в премиальном стиле */ .primary-btn, button.primary { background-color: #0A0A0A; color: #FFFFFF; border: none; padding: 14px 32px; font-size: 14px; font-weight: 500; letter-spacing: 0.05em; text-transform: uppercase; cursor: pointer; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } .primary-btn:hover { background-color: #1A1A1A; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); } /* Карточки */ .card { background: #FFFFFF; border: 1px solid #E5E5E5; border-radius: 0; padding: 2rem; margin-bottom: 1.5rem; transition: all 0.3s ease; } .card:hover { box-shadow: 0 0 0 1px #D4AF37; } /* Поля ввода */ input, textarea, select { border: 1px solid #E5E5E5; background: #FFFFFF; padding: 12px 16px; font-size: 15px; transition: border-color 0.3s; } input:focus, textarea:focus, select:focus { border-color: #D4AF37; outline: none; } /* Вкладки */ .tab-nav { border-bottom: 1px solid #E5E5E5; margin-bottom: 2rem; } .tab-nav button { background: none; border: none; padding: 1rem 2rem; font-weight: 500; color: #666; border-bottom: 2px solid transparent; transition: all 0.3s; } .tab-nav button.selected { color: #0A0A0A; border-bottom-color: #D4AF37; } /* Заголовок приложения */ .app-header { text-align: center; padding: 4rem 0 3rem; border-bottom: 1px solid #E5E5E5; margin-bottom: 3rem; } .app-subtitle { font-size: 1.125rem; color: #666; font-weight: 300; letter-spacing: 0.05em; } /* Информационные блоки */ .info-box { background: #F8F8F8; border-left: 3px solid #D4AF37; padding: 1.5rem; margin: 1rem 0; } /* Качество генерации */ .quality-selector { display: flex; gap: 1rem; margin: 1rem 0; } .quality-option { flex: 1; padding: 1rem; text-align: center; border: 1px solid #E5E5E5; cursor: pointer; transition: all 0.3s; } .quality-option:hover { border-color: #D4AF37; } .quality-option.selected { background: #0A0A0A; color: white; border-color: #0A0A0A; } /* Футер */ .app-footer { text-align: center; padding: 3rem 0; margin-top: 5rem; border-top: 1px solid #E5E5E5; color: #666; font-size: 0.875rem; } /* Прогресс */ .progress-bar { height: 2px; background: #E5E5E5; position: relative; overflow: hidden; } .progress-bar::after { content: ''; position: absolute; top: 0; left: 0; bottom: 0; background: #D4AF37; width: 30%; animation: progress 2s ease-in-out infinite; } @keyframes progress { 0% { left: -30%; } 100% { left: 100%; } } /* Адаптивность */ @media (max-width: 768px) { h1 { font-size: 2rem; } h2 { font-size: 1.5rem; } .card { padding: 1.5rem; } } """ # Класс для улучшения изображений 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): 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 @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.pipe( prompt=f"{quality_boost}{room_type_en}, {custom_prompt}, interior design, high quality", prompt_2=f"{quality_boost}{room_type_en}, {custom_prompt}, interior design, high quality", negative_prompt=negative_prompt if negative_prompt else None, negative_prompt_2=negative_prompt if negative_prompt else None, image=image, strength=strength, num_inference_steps={"fast": 15, "balanced": 25, "ultra": 40}[quality_mode], guidance_scale={"fast": 7.0, "balanced": 8.0, "ultra": 9.0}[quality_mode], original_size=(768, 768), target_size=(768, 768) ).images[0] 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}" # Автосохранение информации об авторе если включено if os.environ.get("AUTHOR_INFO"): info += f"\n\n© {os.environ.get('AUTHOR_INFO', '').split('|')[0]}" 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 def change_room_element(image, element, value, strength): """Изменение отдельного элемента""" if image is None: return None, "Загрузите изображение" global designer if designer is None: designer = InteriorDesignerPro() try: result = designer.change_element(image, element, value, strength) 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 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=90) def create_style_comparison(image, selected_styles, comparison_quality): """Создание сравнения стилей""" if image is None: return None, "❌ Пожалуйста, загрузите изображение" if len(selected_styles) < 2: return None, "❌ Выберите минимум 2 стиля для сравнения" if len(selected_styles) > 6: return None, "❌ Максимум 6 стилей для сравнения" global designer if designer is None: designer = InteriorDesignerPro() try: # Генерируем изображения для каждого стиля results = designer.create_style_comparison( image, selected_styles, quality=comparison_quality ) # Создаем сетку сравнения grid = designer._create_comparison_grid(results, image) info = f""" ✅ Сравнение создано! 📊 Стилей: {len(selected_styles)} ⚡ Режим: {comparison_quality} 🎨 Стили: {', '.join(selected_styles)} """ return grid, info except Exception as e: return None, f"❌ Ошибка создания сравнения: {str(e)}" # Добавляем метод _create_comparison_grid к классу def _create_comparison_grid(self, style_results, original_image): """Создание сетки для сравнения стилей""" images = [(original_image, "Оригинал")] + style_results # Определяем размер сетки n = len(images) cols = 3 if n > 4 else 2 rows = (n + cols - 1) // cols # Размер одного изображения в сетке img_width = 400 img_height = 300 padding = 20 text_height = 40 # Создаем холст grid_width = cols * (img_width + padding) + padding grid_height = rows * (img_height + text_height + padding) + padding grid = Image.new('RGB', (grid_width, grid_height), color='white') # Размещаем изображения for idx, (img, title) in enumerate(images): row = idx // cols col = idx % cols # Позиция x = col * (img_width + padding) + padding y = row * (img_height + text_height + padding) + padding # Изменяем размер изображения img_resized = img.resize((img_width, img_height), Image.Resampling.LANCZOS) grid.paste(img_resized, (x, y)) # Добавляем подпись from PIL import ImageDraw, ImageFont draw = ImageDraw.Draw(grid) # Пытаемся загрузить шрифт try: font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 20) except: font = None # Текст по центру под изображением text_x = x + img_width // 2 text_y = y + img_height + 10 draw.text((text_x, text_y), title, fill='black', font=font, anchor='mt') return grid # Привязываем метод к классу при инициализации InteriorDesignerPro._create_comparison_grid = _create_comparison_grid @spaces.GPU(duration=60) def remove_objects_by_text(image, objects_text, mask_precision): """Удаление объектов по текстовому описанию""" if image is None: return None, "❌ Загрузите изображение" try: # Инициализируем designer если не готов global designer if designer is None: designer = InteriorDesignerPro() # Проверяем наличие object_remover if not hasattr(designer, 'object_remover') or designer.object_remover is None: # Создаем object_remover from models import ObjectRemover if hasattr(designer, 'inpaint_pipe') and designer.inpaint_pipe is not None: designer.object_remover = ObjectRemover(designer.inpaint_pipe) else: # Fallback на img2img как инпейнтинг designer.object_remover = ObjectRemover(designer.pipe) # Генерируем простую маску в центре (временное решение) width, height = image.size mask = Image.new('L', (width, height), 0) draw = ImageDraw.Draw(mask) # Размер маски зависит от precision margin = int(min(width, height) * (1 - mask_precision) / 2) draw.rectangle([margin, margin, width-margin, height-margin], fill=255) # Немного размываем маску mask = mask.filter(ImageFilter.GaussianBlur(radius=10)) # Используем инпейнтинг или img2img if hasattr(designer.inpaint_pipe, 'mask_image'): # Настоящий inpainting result = designer.inpaint_pipe( prompt=f"empty {objects_text} area, clean interior background, seamless texture", 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 через img2img result = designer.pipe( prompt=f"interior without {objects_text}, empty space, clean background", prompt_2=f"interior without {objects_text}, empty space, clean background", negative_prompt=f"{objects_text}, furniture, clutter", negative_prompt_2=f"{objects_text}, furniture, clutter", image=image, strength=0.8, num_inference_steps=25, guidance_scale=8.0, original_size=(768, 768), target_size=(768, 768) ).images[0] return result, f"✅ Попытка удалить: {objects_text}" except Exception as e: import traceback error_details = traceback.format_exc() return None, f"❌ Ошибка: {str(e)}\n\nДетали:\n{error_details}" # Создаем интерфейс with gr.Blocks(title="AI Дизайнер интерьера Pro", theme=gr.themes.Soft(), css=custom_css) as app: # Заголовок gr.HTML("""

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-10 сек)", "fast"), ("⚖️ Сбалансированное (15-20 сек)", "balanced"), ("💎 Ультра (30-40 сек)", "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", elem_classes="primary-btn" ) # Примеры 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=2): with gr.Row(): with gr.Column(): remove_image = gr.Image( label="Загрузите фото", type="pil", height=400 ) objects_to_remove = gr.Textbox( label="Что удалить?", placeholder="Например: красный диван, картина на стене, стол в центре", lines=3, info="Опишите объекты которые нужно удалить" ) mask_precision = gr.Slider( label="Точность выделения", minimum=0.1, maximum=0.9, value=0.5, step=0.1, info="Больше = точнее выделение" ) remove_btn = gr.Button( "🗑️ Удалить объекты", variant="primary", size="lg" ) gr.Markdown(""" ### 📝 Как это работает: 1. Загрузите фото интерьера 2. Опишите что нужно удалить 3. Настройте точность выделения 4. Нажмите "Удалить объекты" 💡 AI попытается найти и удалить указанные объекты, заполнив пространство подходящим фоном. """) with gr.Column(): remove_output = gr.Image( label="Результат", height=400 ) remove_info = gr.Textbox( label="Статус", lines=3 ) # Вкладка детальных изменений with gr.TabItem("🔧 Детальные изменения", id=1): 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 ) compare_styles = gr.CheckboxGroup( label="Выберите стили для сравнения (2-6)", choices=list(DESIGN_STYLES.keys()), value=["Современный минимализм", "Скандинавский"] ) comparison_quality = gr.Radio( label="Скорость генерации", choices=[("Быстро", "fast"), ("Качественно", "balanced")], value="fast" ) compare_btn = gr.Button("🎭 Сравнить стили", variant="primary", size="lg") with gr.Column(): compare_output = gr.Image(label="Сравнение стилей", height=600) compare_info = gr.Textbox(label="Информация", lines=3) # Вкладка увеличения разрешения with gr.TabItem("🔍 Увеличение разрешения", id=4): with gr.Row(): with gr.Column(): upscale_image = gr.Image( label="Изображение для увеличения", type="pil", height=400 ) upscale_factor = gr.Radio( label="Масштаб увеличения", choices=[("2x", 2), ("4x", 4)], value=2 ) upscale_dpi = gr.Radio( label="DPI для печати", choices=[("Экран (96)", 96), ("Печать (150)", 150), ("Высокое качество (300)", 300)], value=96 ) upscale_btn = gr.Button("🔍 Увеличить разрешение", variant="primary", size="lg") with gr.Column(): upscale_output = gr.Image(label="Увеличенное изображение", height=400) upscale_comparison = gr.Image(label="Сравнение", height=200) upscale_info = gr.Textbox(label="Информация", lines=4) # Вкладка рекомендаций 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'' for c in colors]) gr.HTML(f"
{style_name}:
{color_blocks}
") # Обработчики событий 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] ) suggest_btn.click( suggest_styles, inputs=[suggest_image], outputs=[suggestions] ) compare_btn.click( create_style_comparison, inputs=[compare_image, compare_styles, comparison_quality], outputs=[compare_output, compare_info] ) upscale_btn.click( enhance_image, inputs=[upscale_image, upscale_factor, upscale_dpi], outputs=[upscale_output, upscale_comparison, upscale_info] ) remove_btn.click( remove_objects_by_text, inputs=[remove_image, objects_to_remove, mask_precision], outputs=[remove_output, remove_info] ) # Футер gr.HTML(""" """) # Информация внизу gr.Markdown(""" --- ### 📝 Инструкция по использованию: 1. Загрузите фото вашей комнаты 2. Выберите стиль из 20 доступных вариантов 3. Настройте параметры по вкусу 4. Нажмите "Преобразить интерьер" ### 🚀 Возможности: - 20 стилей дизайна - от минимализма до ар-деко - Автоопределение типа комнаты - Создание вариаций - до 8 вариантов за раз - Детальные изменения - меняйте отдельные элементы - HDR освещение - профессиональная обработка света - Анализ цветовой палитры - Удаление объектов - очистите пространство - Увеличение разрешения - для печати и презентаций --- """) # ВАЖНО! Запуск приложения if __name__ == "__main__": app.launch( share=False, show_error=True, server_name="0.0.0.0", server_port=7860 )