Реализация Inpainting (заполнение областей изображения)

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
Реализация Inpainting (заполнение областей изображения)
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

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

Инпейнтинг заменяет выделенную маской область изображения новым содержимым, органично вписывая его в окружающий контекст. Применяется для удаления объектов, замены фонов, реставрации, изменения элементов дизайна.

diffusers инпейнтинг

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

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

    def inpaint(
        self,
        image_bytes: bytes,
        mask_bytes: bytes,      # белый = заменить, чёрный = сохранить
        prompt: str,
        negative_prompt: str = "low quality, blurry, artifacts",
        strength: float = 0.99,
        steps: int = 30,
        guidance_scale: float = 8.0
    ) -> bytes:
        image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
        mask = Image.open(io.BytesIO(mask_bytes)).convert("L")

        # Размеры должны совпадать и быть кратны 8
        w, h = image.size
        w, h = (w // 8) * 8, (h // 8) * 8
        image = image.resize((w, h))
        mask = mask.resize((w, h))

        result = self.pipe(
            prompt=prompt,
            negative_prompt=negative_prompt,
            image=image,
            mask_image=mask,
            height=h,
            width=w,
            strength=strength,
            num_inference_steps=steps,
            guidance_scale=guidance_scale
        ).images[0]

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

Автоматическое создание маски

from transformers import pipeline
import numpy as np

class AutoMaskGenerator:
    def __init__(self):
        # SAM (Segment Anything) для точной сегментации
        self.sam = pipeline("mask-generation", model="facebook/sam-vit-huge", device="cuda")

    def mask_by_text(self, image: Image.Image, text_query: str) -> Image.Image:
        """Создаём маску через CLIP + SAM по текстовому описанию"""
        from transformers import CLIPSegProcessor, CLIPSegForImageSegmentation

        processor = CLIPSegProcessor.from_pretrained("CIDAS/clipseg-rd64-refined")
        seg_model = CLIPSegForImageSegmentation.from_pretrained("CIDAS/clipseg-rd64-refined")

        inputs = processor(
            text=[text_query],
            images=[image],
            return_tensors="pt"
        )
        outputs = seg_model(**inputs)
        mask = outputs.logits.squeeze().sigmoid().detach().numpy()

        # Бинаризуем
        mask_binary = (mask > 0.5).astype(np.uint8) * 255
        return Image.fromarray(mask_binary).resize(image.size)

    def mask_by_coords(self, image: Image.Image, bbox: tuple) -> Image.Image:
        """Маска по bounding box"""
        x1, y1, x2, y2 = bbox
        mask = Image.new("L", image.size, 0)
        draw = ImageDraw.Draw(mask)
        draw.rectangle([x1, y1, x2, y2], fill=255)
        return mask

Типичные сценарии

class InpaintingUseCases:
    async def remove_object(self, image: bytes, object_mask: bytes) -> bytes:
        """Удаляем объект, заполняем фоном"""
        return self.pipe.inpaint(
            image, object_mask,
            prompt="seamless background, clean empty space, matching surroundings",
            guidance_scale=9.0
        )

    async def replace_background(self, image: bytes, subject_mask_inverted: bytes, new_background: str) -> bytes:
        """Меняем фон при удержании субъекта"""
        return self.pipe.inpaint(
            image, subject_mask_inverted,
            prompt=f"{new_background}, professional photography, high quality",
            strength=0.95
        )

    async def change_product_color(self, product_image: bytes, product_mask: bytes, color: str) -> bytes:
        """Меняем цвет товара для каталога"""
        return self.pipe.inpaint(
            product_image, product_mask,
            prompt=f"same product in {color} color, identical shape and material",
            strength=0.7,  # слабый strength сохраняет форму
            guidance_scale=10.0
        )

API endpoint

from fastapi import FastAPI, File, UploadFile, Form

app = FastAPI()
inpainting = InpaintingService()

@app.post("/inpaint")
async def inpaint_image(
    image: UploadFile = File(...),
    mask: UploadFile = File(...),
    prompt: str = Form(...),
    strength: float = Form(0.99)
):
    image_bytes = await image.read()
    mask_bytes = await mask.read()

    result = inpainting.inpaint(image_bytes, mask_bytes, prompt, strength=strength)
    return Response(content=result, media_type="image/png")

Сроки: базовый API инпейнтинга — 2–3 дня. Сервис с автосегментацией по клику/тексту и веб-интерфейсом — 2–3 недели.