Перейти к содержимому
Экосистема AI Vibe

Разборы

On-device ИИ в браузере: фоторедактор, который не отправляет снимок на сервер

Редакция 24 августа 2026 г.

On-device ИИ в браузере: фоторедактор, который не отправляет снимок на сервер

Три рабочих модели для удаления фона и объектов с фото: загрузка на чужой сервер, generative fill с облачным GPU и полностью клиентский стек в браузере. Автор APIC-Web проверяет третий путь: Canvas, WebAssembly и on-device ML без upload. Для соло-разработчика, который собирает ML-интерфейс и не хочет тащить пользовательские снимки на сервер, этот разбор показывает, где заканчивается «магия нейросети» и начинается инженерия масок и текстур.

Три модели: upload, diffusion в облаке, inference на устройстве

Типичный онлайн-сервис удаления фона или объектов устроен одинаково: вы загружаете изображение, модель крутится на сервере, результат скачивается обратно. Фото уже покинуло устройство. Это не метафора, а архитектурный выбор.

Generative «умный ластик» уровня Photoshop Generative Fill или Galaxy AI object eraser опирается на diffusion-модели, обученные на больших датасетах. Автор прямо ставит границу: такое нельзя бесплатно отдать в статической HTML-странице без сервера и без бюджета на GPU-инференс.

Третий путь — эксперимент «насколько далеко можно зайти, оставаясь client-side-only». APIC-Web заявляет, что всё остаётся на стороне клиента: удаление фона, удаление объектов, фильтры, конвертация форматов и сжатие. Демо доступно бесплатно; технический разбор в посте сосредоточен на двух самых сложных частях: сегментации и object removal.

On-device inference здесь не лозунг про приватность, а ограничение стека. Браузер даёт Canvas, WASM и нативные ML-модели; всё остальное приходится собирать из классических алгоритмов.

On-device сегментация: почему жёсткая маска ломает волосы

Для удаления фона используется MediaPipe ImageSegmenter. У модели два принципиально разных режима вывода:

  • outputCategoryMask: true — жёсткая маска 0/1 по пикселям, края «лесенкой»;
  • outputConfidenceMasks: true — float 0–1 на пиксель до порога, с неопределённостью на границе.

Жёсткая category mask не спасается постфактум blur'ом: мягкие края волос и плеч уже потеряны на этапе бинаризации. Confidence masks плюс постобработка дают заметно лучший край на той же модели, без смены весов, только за счёт пайплайна.

Постобработка выглядит так:

  1. smoothstep-контраст по маске;
  2. эрозия примерно на 1 px;
  3. separable box blur для feather.

Отдельный инженерный урок: число каналов confidence masks зависит от конкретной segmentation model. Нельзя хардкодить confidenceMasks[1]. Разные модели отдают background/foreground или единую foreground-probability.

При инициализации модели закладывается fallback: если GPU delegate не поднимается, переключение на CPU. Для любого client-side ML UI это обязательный сценарий, а не edge case на чужих машинах.

Удаление объектов без diffusion: exemplar fill вместо «магии»

Второй сложный блок — object removal. Здесь не используется generative/diffusion подход. Вместо этого — exemplar-based texture synthesis, content-aware fill «до эры генеративных моделей».

Алгоритм в общих чертах:

  1. Дыра в изображении режется на блоки 8×8.
  2. Заполнение идёт от границы внутрь: первым обрабатывается блок с максимумом уже известных соседей.
  3. Для каждого блока ищется патч в окрестности по SSD; копируются реальные пиксели текстуры, а не усреднение, иначе smear.

Сложность — O(размер_дыры × площадь_поиска). Оптимизации: padded bounding box вокруг маски, adaptive stride по размеру дыры. При ограниченной search area типичное заполнение укладывается well under a second — единственная количественная оценка скорости в материале, без сравнения с облачными сервисами.

Качество автор оценивает как «decent» для кожи, неба, ткани, стен, но это не замена generative fill.

Подводный камень, который легко пропустить при сборке UI: после background removal прозрачные пиксели (alpha = 0) могут хранить «мусорный» RGB. Наивная проверка is painted? ломает patch search. Решение — раздельные массивы isPainted и validSrc для прозрачных областей.

Паттерн: прозрачный пиксель ≠ «не закрашен»
         validSrc отслеживает пригодность источника текстуры отдельно

Что переносится в соло-workflow с локальным inference

Материал не про IDE-ассистентов: в первоисточнике нет упоминаний агентов или vibe-coding workflow. Зато четыре приёма из разбора применимы к любому браузерному ML-интерфейсу, который вы собираете без облачного upload:

Приём Зачем
Confidence masks вместо жёсткой бинаризации Сохранить мягкие края без смены модели
GPU → CPU fallback при инициализации Не падать на машинах без рабочего delegate
Не хардкодить индексы масок модели Разные segmentation models отдают разное число каналов
Разделять painted и valid source Прозрачность после BG removal ломает наивный patch search

WebGPU и Core ML в посте не названы, только GPU delegate у MediaPipe. Расширять стек за пределы источника не стоит.

Фильтры, конвертация форматов и сжатие в APIC-Web перечислены как часть «полного редактора», но без технического разбора в посте. Если вам нужен именно этот контур, смотрите демо и исходники по ссылке ниже.

Источники