Раскраска по номерам: как её собирает программа

Из цветной картинки получается страница с контурами и номерами, а затем программа сама проверяет, можно ли её раскрасить. Ниже устройство конвейера, его функции и сравнение с ручной вёрсткой.

Прототип, ноябрь 2026. Один сюжет для сравнения, второй для проверки.

Что получается

Слева страница, свёрстанная вручную по старому процессу. Справа та же картинка, пропущенная через конвейер. Обе закрашены одним способом: цвет каждой области берётся из цветного образца.

Таймлапс закрашивания двух страниц рядом
Закрашивание идёт от крупных областей к мелким, обе страницы в одном темпе. Белые области это бумага, их не красят.
Чёрно-белые страницы до и после рядом
Печатный вид. Слева цифры разных размеров и шрифтов, часть серые. Справа один шрифт, цифры не мельче 1,2 мм, все чёрные.

Что было и что изменилось

Обе страницы измерены одним скриптом: он находит замкнутые области по линиям и чернила цифр по странице, включая бледные. Поле задания 193,7 на 274,7 мм, как в печатной книге.

ПоказательДоПосле
Закрашиваемых областей без цифры80
Цифр мельче 1,2 мм, не прочитать на печати80
Бледных цифр, штрих не доходит до чёрного160
Самая мелкая цифра1,02 мм1,23 мм
Зазор цифры до линии, минимум0,25 мм0,18 мм
Узких осколков шириной 0,5–2,4 мм3224
Областей от 1 мм²161146
Толщина линии, медиана0,25 мм0,25 мм
Шрифт цифрдва, «I» бледнаяодин, без I и O

Главное отличие в последней проверке. На странице для сравнения дефекты остались в печати, значит их никто не поймал. Здесь готовую страницу проверяет программа по растру и отмечает подозрительные места. Человек всё равно смотрит весь рисунок: выражение лица, тени и форму программа оценить не умеет.

Почему областей стало меньше

Было 161, стало 146. Пятнадцать областей ушли, но на закрашенной картинке их не видно: обе страницы после закраски отличаются друг от друга на 12 мм² из 48 тысяч, это шесть пятен размером 1–4 мм².

Откуда берутся пороги

Грифель заточенного карандаша 0,5–1 мм, след на бумаге 1–1,5 мм. Полоса шириной 1,5 мм закрашивается одним штрихом без права на ошибку, участок 3 мм² это примерно 1,5 на 2 мм, то есть одно-два касания.

Закрасить такое можно, но попасть в контур и не задеть соседа сложно, а результата на картинке не видно: эти участки того же оттенка, что сосед. Обе закрашенные страницы отличаются друг от друга на 12 мм² из 48 тысяч.

Крупных областей шире 2,4 мм почти столько же: 122 против 128. Расхождение закрашенной страницы с оригиналом даже меньше, чем раньше: средняя разница цвета 0,9 против 1,0, потому что крошки красились неточно.

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

Дефекты на странице до

Тот же скрипт обводит на странице всё, что нашёл. Цвет рамки или кружка говорит, какой это дефект, легенда под картой.

Страница до с обведёнными дефектами
Страница до. Красная заливка: области без цифры. Оранжевые кружки: цифры мельче 1,2 мм. Серые: бледные цифры. Синие: цифры у края листа. Зелёные: осколки уже 1,5 мм. Счётчики под картой.
Крупные вырезки дефектов
Те же места крупно, по два примера на вид дефекта.

Что это значит для человека с карандашом

Что из этого убрано и каким шагом

ДефектДоПослеШаг конвейера
Область без цифры80/numberer ставит цифру по каждой замкнутой области и каждой толстой доле, /inspector проверяет. Самые большие пустые области до: 161 и 77 мм²
Цифра мельче 1,2 мм80/fitter: цифра не уменьшается ниже 1,2 мм, вместо этого поворот или расширение области
Бледная цифра160/coder: один шрифт, все цифры чёрные, буквы I и O убраны
Цифра у края листа22не убрано: обе страницы ставят цифру по центру области, у края он и остаётся; нужен отступ от рамки
Осколок уже 1,5 мм20/merger отдаёт полосу соседу того же оттенка

Для сравнения та же карта на странице после: обведены только две цифры у края.

Страница после с картой дефектов
Страница после. Два синих кружка у края листа, остальных дефектов нет. Нулевой счётчик означает «нет дефектов из этого списка», а не «страница безупречна».

Как устроен конвейер

Один скрипт на Python: на входе картинка, на выходе страница, цветной образец, палитра и отчёт проверки. Все пороги заданы в миллиметрах печати, поэтому результат не зависит от размера исходника.

Подготовка
1
/source исходникОбразец из векторного PDF, 3400 px по ширине, сетка 0,057 мм на пиксель.load
2
/palette цветаСглаживание и деление на заданное число цветов в пространстве Lab, близком к восприятию глаза.quantize
Области и линии
Параллельно: тонкие детали
/thinliner усы, спираль, улыбкаВсё тоньше 0,5 мм и контрастное к соседу уходит в отдельный слой до слияния, иначе слияние его съест. Печатается линией 0,13 мм без номера.thin_features, whisker_chains
3
/merger слияние мелкогоУчастки меньше 3,5 мм² или уже 1,5 мм отдаются соседу ближайшего цвета. Контрастная мелочь вроде заклёпок остаётся.merge_regions, smooth_argmax
4
/tracer контуры без щелейПолигоны с общими границами: линия между соседями одна на двоих, щелей и наложений нет по построению.polygonize, extract_arcs
5
/smoother гладкие линииКаждая общая дуга сглаживается один раз, острые кончики прядей остаются острыми. Толщина 0,2 мм.chaikin, render_lines
Цифры
6
/coder коды цветовБелый всегда 1 и не красится, чёрный всегда 2, остальные по площади. Без букв I и O.main
7
/fitter место под цифруЦифра проверяется как прямоугольник с зазором 0,15 мм. В узкой полосе поворачивается вдоль неё, если не влезает, полоса получает расширение под цифру.fit_digit, add_bulbстраница перерисовывается, до 7 раз
8
/numberer нумерация по готовой страницеНомера ставятся по замкнутым областям нарисованных линий, а не по полигонам. Область с перешейками получает цифру в каждой толстой доле.thick_lobes, place_digits
Контроль
9
/inspector проверкаПо растру готовой страницы: щели, области и доли без номера, цифры на линии или впритык. Дефекты на карте.qa_print, qa_map
10
/painter красительСтраница закрашивается от крупных областей к мелким: таймлапс и сравнение с оригиналом по цвету.colorize
Увеличенные фрагменты с повёрнутыми цифрами и расширениями под цифру
Увеличение в четыре раза. Две цифры повёрнуты вдоль узких полос, шесть расширений под цифру: пять на чёрных заклёпках повязки, одно в углу глаза.

Проверка страницы

Программа ищет четыре вида дефектов. У обоих сюжетов после сборки все счётчики по нулям. Важно, что считается областью: замкнутый участок от 1 мм² и толще 0,5 мм. Участки мельче этого цифру вместить не могут и проверяются отдельно, как слияния.

Щель в контуре

В одной замкнутой области оказались цифры разных кодов или два цвета исходника. Такую область человек закрасит одним цветом, и картинка сломается.

Область без номера

Замкнутый участок от 1 мм², толще 0,5 мм, внутри которого нет ни одной цифры. Отдельно проверяются толстые доли одной области.

Цифра на линии

Чернила цифры задевают линию границы или тонкую линию. Проверяется по реальной маске цифры с учётом поворота.

Цифра впритык

Зазор между цифрой и линией меньше 0,15 мм. На печати такая цифра сливается с контуром.

Проверка проверяется тоже. Если убрать на странице самую большую цифру, стереть кусок линии между двумя цветами или положить цифру поверх линии, каждый из дефектов находится.

Карта дефектов страницы
Карта дефектов после сборки. Кружки появляются там, где проверка что-то нашла. Здесь их нет.

Второй сюжет

Чтобы проверить, что конвейер не подогнан под одну картинку, тем же кодом собран мультфильм с чёрным контуром. Исходник растровый, 767 px по ширине, и конвейер растягивает его до рабочей сетки.

Оригинал и закрашенный результат для мультфильма
Слева оригинал, справа результат с контурами и цифрами. 96 областей, 12 цветов, все проверки по нулям. Чёрный контур стал областями с кодом 2, вложенные области внутри него сохранили свои цвета.

Третий сюжет: картинка конкурента

Для проверки на чужом стиле взята картинка из карточки товара другого издателя раскрасок. Исходник растровый, 550 px по ширине, кадр со слайда карточки, а не печатный файл. Для продажи такая картинка не годится, здесь она только как тест.

Картинка конкурента и результат конвейера
Слева оригинал, справа результат с контурами и цифрами. 210 областей, 18 цветов, все проверки по нулям. 13 расширений под цифру и 12 повёрнутых цифр: сюжет плотный, много мелких окон и плакатов. Тонкие буквы на плакатах и усы ушли, цифры в окнах домов мелкие.

Это самый тяжёлый из трёх сюжетов: расхождение закрашенного результата с оригиналом 5,0 против 0,9 у аниме-портрета. Низкое разрешение исходника и россыпь мелочи, именно то, о чём требования ниже.

Требования к исходнику

Чем лучше исходник, тем меньше работы у конвейера и меньше слияний. Всё ниже вытекает из порогов, с которыми собраны эти страницы, в миллиметрах печатного поля шириной 193 мм.

ЧтоНормаПочему
Разрешениевектор или растр от 3000 px по ширинерабочая сетка 3400 px; растр 800 px даёт зубчатые линии и теряет детали
Заливкиплоские, без градиентов и текстурградиент режется на полосы, текстура на сотни крошек, всё это уходит в слияние
Число цветов12–20больше 20 цветов не различить на палитре, соседние оттенки сливаются
Самая мелкая детальот 1,5 мм шириной и от 3,5 мм²след карандаша 1–1,5 мм: уже полоса красится одним штрихом без права на ошибку, а цифра 1,2 мм не влезает
Тонкие штрихидопустимы, если тоньше 0,5 мм и длиннее 6 ммусы и складки становятся линиями без номера, а не областями
Контраст соседейсоседние области заметно разных цветовмелкий участок того же оттенка, что сосед, после закраски не виден, поэтому отдаётся соседу
Чёрный контурили толще 0,5 мм, или его неттолстый контур становится областями с кодом 2, тонкий превращается в линию
Белый и чёрныйчистый белый и почти чёрныйбелый становится кодом 1 «бумага», чёрный кодом 2; кремовый белый останется обычным цветом
Текст и россыпь мелочине нужныбуквы на вывесках и ряды окошек дают десятки областей без места под цифру

Если картинку рисует генератор

Просить плоский стиль с чёткими контурами, крупные формы, лицо и глаза покрупнее, ограниченную палитру, без теней с размытием, без фона с мелкой фактурой. Проверка простая: прогнать через конвейер и посмотреть, сколько областей ушло в слияние и сколько цифр мельче 1,6 мм.

Готовность к печати

Часть требований печати проверяется по файлу, часть видна только на бумаге. Что измерено на странице для сравнения:

ПроверкаРезультатНорма
Разрешение страницы при ширине 193,5 мм446 dpiот 300 dpi
Самая мелкая цифра1,23 ммне мельче 1,2 мм
Зазор между цифрой и линиейот 0,15 ммот 0,15 мм
Растекание краски 0,05 мм: знаков, слившихся с линией0 из 1810
Областей уже 0,3 мм, которые заплывут при печати00
Толщина линии на оттиске0,25 мм0,2–0,3 мм
PDF: формат, шрифтыA4, Arial встроенвстроенные шрифты

Растекание краски имитируется утолщением всех линий и цифр на 0,05 мм с повторной проверкой зазоров. Это грубая модель лазерного принтера на обычной бумаге, не замер.

Что видно только на бумаге

Для этого хватит одного распечатанного листа и тестовой полосы с цифрами от 1,0 до 1,6 мм и линиями от 0,1 до 0,3 мм. По ней пороги конвейера выставляются под конкретную печать.

Что ещё не сделано

Замечания к странице и что с ними

Как запустить

venv/bin/python pbn2.py src/nar_vec.png out/nar k=20 min_digit=1.6 print_w=193.5

k число цветов, min_digit нормальная высота цифры в мм, print_w ширина поля на бумаге. Ключи bulbs=0, rotate=0, merge_narrow=0 отключают расширения, повороты и слияние узких.

Одна страница собирается за одну-две минуты. Метрики против эталона считает cmp/metrics.py, PDF книги собирает build_pdf.py.