Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Модерация изображений API — анализ картинки, NSFW и текст на изображении

Русский · English

Live API tests license API

Готовые примеры работы с API анализа изображения на шести языках: Python, TypeScript (Node.js), Go, Java, C#, PHP. Модерация пользовательского контента: классификация содержимого (нагота, откровенность, насилие), метки предметов и распознавание текста НА изображении — плюс сводное решение allow / review / block.

Каждый пример запускается сразу — без регистрации, без ключа, без карты. В коде зашит публичный демо-ключ и два образца изображений.

git clone https://github.com/atlorium-api/image-moderation-api-client
cd image-moderation-api-client/python && pip install -r requirements.txt && python main.py
sample-banner.jpg · JPEG, 445 КБ
  Решение: review · списано единиц: 2

Классификация содержимого: для взрослых: very_unlikely, откровенность: very_unlikely, насилие: very_unlikely, медицинское: very_unlikely, подделка: very_unlikely
Метки предметов: Font (0.93), Poster (0.85), Advertising (0.71)
Текст на изображении:
  | ФРИСПИНЫ КАЖДЫЙ ДЕНЬ
  | бонус за депозит 200%
  | пиши: +7 900 000-00-00

НА МОДЕРАЦИЮ: нужен человек.
Очередь: очередь модератора
  [!] Азартные игры [текст на изображении]: бонус за депозит → review
  [!] Контакты для увода сделки [текст на изображении]: +7 900 000-00-00 → review
  [i] Поиск в вебе не заказан: заимствованное чужое изображение не будет опознано

Обратите внимание на этот вывод: классификация содержимого и метки предметов не увидели ничего. Ни наготы, ни насилия, ни запрещённых предметов — обычный баннер. Поймал только текстовый слой. Ровно так выглядит значительная доля того, что подлежит удалению.

Демо-ключ отвечает моками: изображение никуда не отправляется и не анализируется. Ветку ответа задаёт размер присланного файла — так все четыре исхода воспроизводятся в тесте, а не выпадают случайно. Подставьте боевой ключ — тот же код начнёт возвращать настоящий разбор.


Три слоя, и они не пересекаются

Это главное, что нужно понять перед интеграцией. Слои не дублируют друг друга и не «проверяют одно и то же надёжнее» — каждый ловит класс материала, невидимый для двух остальных:

Слой Что ловит Что при этом молчит
Классификация содержимого Откровенное фото — без надписей и распознаваемых предметов Метки и текст
Метки предметов Шприц, оружие, игральные фишки, бутылку Классификация: наготы и насилия на такой картинке нет
Текст НА изображении Телефон продавца, баннер казино, объявление о поддельных документах Оба предыдущих: там просто буквы

Выключенный слой — это не «проверка чуть слабее», а целая категория материала, проходящая насквозь и незаметно. В российских реалиях дороже всего обходится отключение текстового слоя: значительная доля того, что подлежит удалению, — не картинка, а надпись поверх нейтральной картинки, и ловит её только он.

Поэтому в примерах функция moderateUpload() не просто маршрутизирует загрузку, но и считает покрытие: если слой не заказывался, об этом печатается отдельная строка, а вердикт «опубликовать», полученный не по всем слоям, помечается как более слабый, чем выглядит.

Зачем это нужно

Модерация объявлений и фотографий товаров. Проверка аватаров и обложек. Отсев рекламы и контактов «мимо площадки» в пользовательских изображениях. Предварительный фильтр перед ручной модерацией — он сокращает её объём, оставляя человеку спорные случаи.

Решение принимаете вы. decision — рекомендация, а не приговор: allow, review (нужен человек) или block. Промежуточное review существует потому, что автоматическое удаление по одному машинному признаку даёт ложные срабатывания на медицинских, исторических и новостных материалах.

Быстрый старт за 60 секунд

Язык Запуск Требуется
Python pip install -r requirements.txt && python main.py Python 3.10+
TypeScript / Node.js npm install && npm start Node.js 20+
Go go run . Go 1.22+
Java java Main.java JDK 17+ (без зависимостей)
C# dotnet run .NET 8+
PHP php main.php PHP 8.1+

Передать свой файл: python main.py /путь/к/картинке.jpg

Образцы и сценарии песочницы

В корне репозитория лежат два готовых образца:

Файл Размер Что показывает
sample-banner.jpg ~445 КБ Срабатывание текстового слоя: review, два флага
sample-photo.jpg ~16 КБ Чистый кадр: allow, флагов нет

Ветку ответа в песочнице задаёт размер изображения в декодированном виде. Своими файлами можно воспроизвести все четыре исхода:

Размер файла Что вернёт демо-ключ
меньше 100 КБ allow — срабатываний нет
100 КБ – 400 КБ review по метке предмета (классификация при этом молчит)
400 КБ – 1 МБ review по тексту на изображении (молчат оба остальных слоя)
больше 1 МБ block по классификации содержимого

Приём неочевидный, но воспроизводимый и целиком в ваших руках: достаточно закрепить в тестах четыре файла разной величины. Границы разнесены на сотни килобайт, чтобы случайное пересжатие не «переехало» в соседний сценарий.

Аутентификация

Ключ передаётся в заголовке Authorization:

Authorization: Bearer ВАШ_КЛЮЧ
Ключ Что делает
ak_sandbox_demo_mockdata_v1 Демо-ключ. Публичный, один на всех. Возвращает моки, денег не списывает, регистрации не требует. Ответы детерминированы — на них можно писать стабильные тесты.
Боевой ключ Настоящий анализ изображения. Получить в личном кабинете: atlorium.com

Переход на боевой ключ не требует правок в коде — все примеры читают переменную окружения:

export ATLORIUM_API_KEY="ak_ваш_боевой_ключ"

Каждый ответ песочницы помечен заголовком X-Atlorium-Sandbox: true — перепутать мок с настоящим разбором невозможно.

Эндпоинты

Базовый адрес: https://atlorium.com

Метод Путь Назначение
POST /api/imagecheck Анализ изображения и решение модерации

Пакетного режима нет намеренно: изображение — это мегабайты в теле запроса, и пакет превратился бы в стомегабайтный POST с таймаутами на промежуточных узлах. Поток модерируется параллельными одиночными запросами: они независимы, повторяются поштучно и не теряют весь пакет из-за одной битой картинки.

POST /api/imagecheck

{
  "image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...",
  "includeText": true,
  "includeWebSearch": false
}
Параметр Тип Описание
image string Изображение в Base64 — «голым» или в виде data-URL. Предел 7 МБ в декодированном виде. Принимаются JPEG, PNG, WEBP, BMP, GIF. PDF и видео на вход не подаются
includeText bool Читать текст НА изображении. По умолчанию true — и отключать его дороже всего (см. таблицу слоёв)
includeWebSearch bool Искать изображение в вебе. По умолчанию false

Поля ответа

Поле Тип Что содержит
decision string Сводное решение: allow, review или block. Рекомендация, а не приговор
flags array Сработавшие фильтры — почему принято такое решение, см. ниже
safeSearch object Классификация содержимого, см. ниже
labels array Распознанные предметы: { name, nameRu, score }. nameRu заполнено не у всех меток
text string Текст, распознанный на изображении. Пустая строка — не ошибка
webSearch object Результат поиска в вебе. null, если поиск не заказывался
billedUnits number Фактически списанное число единиц работы: от 1 до 3
elapsedMs number Длительность анализа, мс
message string Пояснение для человека

flags[] — сработавший фильтр

Поле Тип Что содержит
category string Категория стоп-листа, например gambling, adult, contacts
title string Человекочитаемое название категории
source string Слой-источник: safe_search, label или text. Показывайте его модератору — без него непонятно, почему нейтральная на вид картинка попала в очередь
evidence string Конкретное доказательство: найденная метка, выражение из текста или категория классификации со степенью
severity string Вклад этого срабатывания: review или block

safeSearch — классификация содержимого

Пять категорий: adult, racy, violence, medical, spoof. Значение каждой — степень уверенности: unknown, very_unlikely, unlikely, possible, likely, very_likely.

webSearch — поиск в вебе

fullMatchCount, partialMatchCount, bestGuess, matches[] (pageUrl, fullMatch). Приходит только если поиск заказан. Поиск, не давший совпадений, не тарифицируется.

Пустой text — это не ошибка

Он означает одно из двух: читаемого текста на картинке нет, либо слой не заказывался. Какой это случай, видно по billedUnits. В примерах эта развилка разобрана явно — смотрите ветку вокруг includeText.

Сырые слои (safeSearch, labels, text) отдаются намеренно, а не только итоговое решение: в модерации ошибка стоит дорого в обе стороны, и решение, которое нельзя перепроверить, доверия не заслуживает.

Обработка ошибок

Код Причина Что делать
400 Изображение не передано, повреждено, больше 7 МБ или в неподдерживаемом формате Проверьте формат и размер до отправки — во всех примерах это делается по сигнатуре файла
401 Ключ отсутствует, просрочен или недействителен Проверьте заголовок Authorization
402 Недостаточно кредитов на балансе Пополнить на atlorium.com
429 Превышен rate-limit Повторить с задержкой. Ставьте потолок ожидания — сервер может честно попросить подождать десятки минут
503 Анализ выполнить не удалось Повторить позже. За сбой на нашей стороне деньги не списываются

Во всех шести примерах коды разложены в человекочитаемые причины — смотрите класс AtloriumError.

Цены и лимиты

Оплата pay-as-you-go, без подписки. Единиц работы от 1 до 3:

Единица За что
1 Базовый слой: метки предметов вместе с классификацией содержимого. Обязателен
+1 Чтение текста на изображении (includeText, по умолчанию включено)
+1 Поиск изображения в вебе (includeWebSearch, по умолчанию выключено) — и только если поиск вернул совпадения

Фактически списанное число всегда приходит в ответе полем billedUnits. Анализ, который не выполнен, не тарифицируется вовсе.

Актуальные цены и лимиты: atlorium.com/pricing

Чего сервис не делает

  • Не распознаёт лица и не устанавливает личность.
  • Не хранит присланные изображения.
  • Не заменяет ручную модерацию — он сокращает её объём, оставляя человеку спорные случаи.

Частые вопросы

Стоит ли экономить на текстовом слое? Почти никогда. Он включён по умолчанию именно поэтому: надпись поверх нейтральной картинки не видят ни классификация, ни метки, а в российском UGC это очень частый случай.

Можно ли настроить, что считать нарушением? Да. Сводное решение считается по вашим стоп-листам, редактируемым без перезапуска.

Почему decision — «рекомендация»? Потому что автоматическое удаление по одному машинному признаку даёт ложные срабатывания на медицинских, исторических и новостных материалах. Для этого и существует промежуточное review.

Почему нет пакетного режима? Изображение — это мегабайты в теле запроса. Пакет превратился бы в огромный POST, который рвётся по таймауту, и одна битая картинка теряла бы весь пакет. Параллельные одиночные запросы надёжнее.

Какие форматы принимаются? JPEG, PNG, WEBP, BMP, GIF, до 7 МБ в декодированном виде. PDF и видео — нет.

Что делать с flags, если решение всё равно allow? Такого не бывает: сработавший флаг всегда поднимает решение минимум до review. Пустой flags при allow — нормальный исход, но проверьте покрытие: заказаны ли были все слои.

Другие API Atlorium

Модерация изображения редко бывает единственной проверкой пользовательского контента. Из того же аккаунта и тем же ключом доступны:

Полный каталог — atlorium.com

Ссылки

Лицензия

MIT — берите код и используйте как хотите, в том числе в коммерческих проектах.

About

API анализа изображения: модерация UGC — классификация содержимого, метки предметов и текст НА изображении, решение allow/review/block по своим стоп-листам. Примеры на Python, TypeScript, Go, Java, C#, PHP. Image moderation and NSFW detection API client.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages