Реалізація Outpainting (розширення меж зображення)

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Реалізація Outpainting (розширення меж зображення)
Середній
~3-5 днів
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    901
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1119
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    853

Розробка AI-аутпейнтингу для розширення зображень

Аутпейнтинг розширює зображення за його вихідні границі, органічно заповнюючи нову область змістом, що відповідає оригіналу. Застосовується для створення широкоформатних банерів з квадратних фото, розширення простору навколо об'єкта, створення панорам.

diffusers аутпейнтинг

from diffusers import StableDiffusionXLInpaintPipeline
from PIL import Image, ImageOps
import torch
import numpy as np
import io

class OutpaintingService:
    def __init__(self):
        self.pipe = StableDiffusionXLInpaintPipeline.from_pretrained(
            "diffusers/stable-diffusion-xl-1.0-inpainting-0.1",
            torch_dtype=torch.float16
        ).to("cuda")

    def extend_image(
        self,
        image_bytes: bytes,
        extend_left: int = 0,
        extend_right: int = 0,
        extend_top: int = 0,
        extend_bottom: int = 0,
        prompt: str = "seamless continuation of the scene",
        steps: int = 40
    ) -> bytes:
        original = Image.open(io.BytesIO(image_bytes)).convert("RGB")
        orig_w, orig_h = original.size

        # Новий розмір холста
        new_w = orig_w + extend_left + extend_right
        new_h = orig_h + extend_top + extend_bottom

        # Вирівнюємо до кратного 8
        new_w = (new_w // 8) * 8
        new_h = (new_h // 8) * 8

        # Створюємо розширений холст
        canvas = Image.new("RGB", (new_w, new_h), (128, 128, 128))
        canvas.paste(original, (extend_left, extend_top))

        # Маска: білий = розширена зона, чорний = оригінал
        mask = Image.new("L", (new_w, new_h), 255)
        mask_draw_area = Image.new("L", (orig_w, orig_h), 0)
        mask.paste(mask_draw_area, (extend_left, extend_top))

        result = self.pipe(
            prompt=prompt,
            image=canvas,
            mask_image=mask,
            height=new_h,
            width=new_w,
            num_inference_steps=steps,
            guidance_scale=8.0,
            strength=0.99
        ).images[0]

        buf = io.BytesIO()
        result.save(buf, format="PNG")
        return buf.getvalue()

Конвертація форматів

class AspectRatioConverter:
    """Конвертуємо квадрат у 16:9 або 9:16 через аутпейнтинг"""

    def __init__(self, outpainting_service: OutpaintingService):
        self.service = outpainting_service

    def square_to_landscape(self, image_bytes: bytes, prompt: str = "") -> bytes:
        """1:1 → 16:9 (додаємо по бокам)"""
        img = Image.open(io.BytesIO(image_bytes))
        target_w = int(img.height * 16 / 9)
        extend_each = (target_w - img.width) // 2

        return self.service.extend_image(
            image_bytes,
            extend_left=extend_each,
            extend_right=extend_each,
            prompt=prompt or "seamless background extension, same scene"
        )

    def square_to_portrait(self, image_bytes: bytes, prompt: str = "") -> bytes:
        """1:1 → 9:16 (додаємо зверху і знизу)"""
        img = Image.open(io.BytesIO(image_bytes))
        target_h = int(img.width * 16 / 9)
        extend_each = (target_h - img.height) // 2

        return self.service.extend_image(
            image_bytes,
            extend_top=extend_each,
            extend_bottom=extend_each,
            prompt=prompt or "seamless extension, matching environment"
        )

Тайловий аутпейнтинг для великих розширень

def extend_large(
    image_bytes: bytes,
    total_extension: int,
    direction: str = "right",
    tile_size: int = 512,
    overlap: int = 128
) -> bytes:
    """Розширюємо великі області тайлами з перекриттям"""
    current_image = image_bytes
    steps = (total_extension - overlap) // (tile_size - overlap)

    for i in range(steps):
        extension = min(tile_size, total_extension - i * (tile_size - overlap))
        if direction == "right":
            current_image = outpainting_service.extend_image(
                current_image,
                extend_right=extension,
                prompt="seamless continuation"
            )
        # Аналогічно для інших напрямків

    return current_image

Застосування

Завдання Вихідний формат Цільовий формат
Instagram → YouTube banner 1:1 16:9
Продуктове фото → лендинг 4:5 21:9
Портрет → обкладинка книги 3:4 2:3 з простором для тексту
Пейзаж → панорама 16:9 32:9

Терміни: базовий аутпейнтинг API — 2–3 дні. Інструмент конвертації форматів з попереглядом — 1–2 тижні.