Мы посмотрим и на Корбена Далласа и Лилу из фильма «Пятый элемент», на сюжет из фильма «Люди в черном» и другие интересные арты.
Генеративные модели могут создавать великолепные изображения и видео, особенно при правильном подходе и знаниях в написании промптов.
Но меня интересуют мультимодальные LLM, которые на входе принимают также изображения и видео, а на выходе производят текст. Теоретически они должны иметь хорошие представления о том, как выглядит окружающий мир и как он меняется со временем по законам физики.
То, что это так и есть, подтверждается способностью качественно описывать входные изображения с пониманием сюжета, композиции, деталей и смысла самого изображения, а также изображенного процесса.
Но это пассивное поведение.
И тут возникает вопрос. А что, если заставить модель проявить себя в активном действии, творческой самореализации? Пока не будем говорить о самых последних версиях GPT-4o и Gemini 2.0 Flash, которые нативно поддерживают непосредственную генерацию изображения по запросу, так же как и текст.
Приведу близкую аналогию. Допустим, мы художнику завязываем глаза, даем в руки кисть и краски и формулируем задание, согласно которому он должен на холсте всё это изобразить максимально точно.
То же самое мы можем проделать с LLM, дав инструкцию нарисовать заданный сюжет, а вместо кисти и красок будет код. Например, HTML5 и API canvas.
Насколько хорошо развит канал преобразования внутренних визуальных представлений в программную реализацию и представление на экране?
Некоторое время назад я уже писал статью на аналогичную тему «LLM и ее невозможный ASCII art», в которой обычная LLM создавала изображения в виде ASCII art, но делала это с очень большим трудом за несколько последовательных шагов улучшения.
Я предполагаю, что современные мультимодальные модели должны в разы, если не на порядок лучше рисовать на canvas.
Выясняется, что среди моделей есть как аутсайдеры, провалившие задание, так и гении, впрочем, как и среди людей. А одна из них, по сравнению с другими, ну просто Леонардо да Винчи.
Начинаем эксперимент
Deepseek и Qwen не справились.
GPT-4o не справились.
Llama 3.2 90B Vision Instruct не справились.
Gemini-2.0-Flash не справились.
ChatGPT не справились.
OpenAI o1-mini не справились.
Grok-2 не справились.
Claude 3.5 Haiku не справились.
Gemini-2.5-Pro подаёт хорошие надежды и переходит в разряд лидеров.
Но лучшая модель, безусловный лидер, оправдавший мои самые смелые надежды, это оказалась Claude 3.5 sonnet.
Её творчество и будет предметом данной статьи. Модель использовалась без опции доступа в интернет.
Самое впечатляющее в этих артах даже не само изображение, а его динамика. Да, на изображениях происходит процесс изменения композиции со временем, всё движется, меняется, перемещается и трансформируется в соответствии с сюжетом. Это, своего рода, короткие видеосюжеты, созданные программно по определённому замыслу, в котором есть выраженная идея.
Первый арт
Промпт:
Напиши HTML-код, который рисует изображение Малдера и Скалли из фильма «Секретные материалы» на canvas размером 1200×600 пикселей. Рисунок создается программно с использованием только нативного JavaScript и Canvas, без внешних библиотек и изображений.
Полученный код изображает агентов Малдера и Скалли на фоне звездного неба, по которому проплывает красивая летающая тарелка. Малдер держит в руке пистолет, а Скалли светит фонариком в разные стороны.
Важно отметить, что арты я создал не одним промптом сразу. Первый промпт создаёт начальный полный арт, который может быть не столь совершенным и детальным, но является хорошей основой для других шагов, направленных на совершенствование этого арта.
Поэтому вторым промптом я усовершенствовал Малдера и Скалли.
Корректировка арта.
У нас имеется следующий HTML код, рисующий Малдера и Скалли из фильма «Секретные материалы».(Здесь код функций рисования Малдера и Скалли).
Сделай Малдера и Скалли более реалистичными, детальными и красивыми.
Все картинки кликабельны.

После этого арт стал значительно более детальным и красивым.
Обратите внимание на прорисованные черты лица и мельчайшие детали персонажей.
Модель адекватно изменяет и детализирует код в соответствии с инструкциями в промптах. Таким методом, в принципе, можно создавать очень впечатляющие арты, насыщенные деталями и динамическими элементами и сценами.
Значения отдельных параметров кода я немного подправил вручную для исправления мелких огрехов.
Вместе с усовершенствованием Малдера и Скалли модель самостоятельно улучшила фон, добавив клубящийся туман и ночную луну.
В конце концов, и знаменитые художники порой многократно дорисовывали и перерисовывали детали своих картин. Например, Илья Репин дописывал свои картины, выставленные прямо в Третьяковской галерее, а Константин Савицкий дорисовал медведицу и трёх медвежат на картине Ивана Шишкина «Утро в сосновом лесу».
Посмотреть арт в динамике в песочнице. (на страничке нужно выбрать — Yes, proceed to preview).
Здесь, для примера, код функция рисования агента Малдера
function drawMulder() {
ctx.save();
ctx.translate(400, 500);
// Цвета для Малдера
const skinTone = "#e0c8b0";
const suitColor = "#333340";
const hairColor = "#3a2d1a";
// Ноги (под телом для правильного перекрытия)
ctx.fillStyle = suitColor;
// Левая нога
ctx.beginPath();
ctx.moveTo(-20, -30);
ctx.lineTo(-25, 40);
ctx.lineTo(-5, 40);
ctx.lineTo(-7, -30);
ctx.closePath();
ctx.fill();
// Правая нога
ctx.beginPath();
ctx.moveTo(7, -30);
ctx.lineTo(5, 40);
ctx.lineTo(25, 40);
ctx.lineTo(20, -30);
ctx.closePath();
ctx.fill();
// Обувь
ctx.fillStyle = "#111";
// Левый ботинок
ctx.beginPath();
ctx.moveTo(-25, 40);
ctx.lineTo(-30, 45);
ctx.lineTo(-5, 45);
ctx.lineTo(-5, 40);
ctx.closePath();
ctx.fill();
// Правый ботинок
ctx.beginPath();
ctx.moveTo(5, 40);
ctx.lineTo(5, 45);
ctx.lineTo(30, 45);
ctx.lineTo(25, 40);
ctx.closePath();
ctx.fill();
// Тело (пиджак)
ctx.fillStyle = suitColor;
ctx.beginPath();
ctx.moveTo(-5, -110);
ctx.lineTo(-22, -100);
ctx.lineTo(-24, -30);
ctx.lineTo(24, -30);
ctx.lineTo(25, -98);
ctx.lineTo(5, -110);
ctx.closePath();
ctx.fill();
// Белая рубашка и галстук
ctx.fillStyle = "#fff";
ctx.beginPath();
ctx.moveTo(-10, -100);
ctx.lineTo(-5, -30);
ctx.lineTo(5, -30);
ctx.lineTo(10, -100);
ctx.closePath();
ctx.fill();
// Галстук
ctx.fillStyle = "#a32f2f";
ctx.beginPath();
ctx.moveTo(0, -100);
ctx.lineTo(-4, -30);
ctx.lineTo(0, -35);
ctx.lineTo(4, -30);
ctx.closePath();
ctx.fill();
// Левая рука
ctx.fillStyle = suitColor;
ctx.beginPath();
ctx.moveTo(-20, -100);
ctx.lineTo(-45, -50);
ctx.lineTo(-40, -40);
ctx.lineTo(-15, -80);
ctx.closePath();
ctx.fill();
// Левая кисть
ctx.fillStyle = skinTone;
ctx.beginPath();
ctx.moveTo(-45, -50);
ctx.lineTo(-50, -35);
ctx.lineTo(-40, -35);
ctx.lineTo(-40, -40);
ctx.closePath();
ctx.fill();
// Правая рука с пистолетом
ctx.save();
const armAngle = Math.sin(frameCount * 0.02) * 0.1;
ctx.translate(17, -80);
ctx.rotate(Math.PI / 4 + armAngle*2);
// Рукав
ctx.fillStyle = suitColor;
ctx.beginPath();
ctx.moveTo(-10, -18);
ctx.lineTo(30, -8);
ctx.lineTo(32, 5);
ctx.lineTo(-5, -3);
ctx.closePath();
ctx.fill();
// Манжет
ctx.fillStyle = "#fff";
ctx.beginPath();
ctx.moveTo(25, -6);
ctx.lineTo(35, -4);
ctx.lineTo(36, 0);
ctx.lineTo(26, -2);
ctx.closePath();
ctx.fill();
// Кисть правой руки
ctx.fillStyle = skinTone;
ctx.beginPath();
ctx.moveTo(30, -4);
ctx.lineTo(38, -2);
ctx.lineTo(40, 3);
ctx.lineTo(32, 1);
ctx.closePath();
ctx.fill();
// Пистолет
ctx.fillStyle = "#111";
// Основная часть пистолета
ctx.beginPath();
ctx.moveTo(38, -2);
ctx.lineTo(65, 0);
ctx.lineTo(65, -5);
ctx.lineTo(35, -7);
ctx.closePath();
ctx.fill();
// Рукоять пистолета
ctx.beginPath();
ctx.moveTo(42, -3);
ctx.lineTo(42, 5);
ctx.lineTo(48, 5);
ctx.lineTo(48, -2);
ctx.closePath();
ctx.fill();
// Спусковой крючок
ctx.beginPath();
ctx.moveTo(48, 0);
ctx.lineTo(50, 2);
ctx.lineTo(52, 0);
ctx.closePath();
ctx.fill();
ctx.restore();
// Голова
ctx.fillStyle = skinTone;
ctx.beginPath();
ctx.ellipse(0, -130, 16, 20, 0, 0, Math.PI * 2);
ctx.fill();
// Волосы
ctx.fillStyle = hairColor;
ctx.beginPath();
ctx.moveTo(-20, -150);
ctx.quadraticCurveTo(15, -157, 20, -142);
ctx.lineTo(-17, -135);
ctx.quadraticCurveTo(-10, -100, -25, -130);
ctx.closePath();
ctx.fill();
// Детали лица
// Глаза
ctx.fillStyle = "#fff";
ctx.beginPath();
ctx.ellipse(-6, -131, 5, 2, 0, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.ellipse(8, -131, 5, 2, 0, 0, Math.PI * 2);
ctx.fill();
// Зрачки
ctx.fillStyle = "#222";
ctx.beginPath();
ctx.ellipse(-6, -131, 2, 2, 0, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.ellipse(8, -131, 2, 2, 0, 0, Math.PI * 2);
ctx.fill();
// Брови
ctx.strokeStyle = hairColor;
ctx.lineWidth = 1.5;
ctx.beginPath();
ctx.moveTo(-12, -136);
ctx.quadraticCurveTo(-6, -139, -2, -136);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(13, -136);
ctx.quadraticCurveTo(6, -139, 4, -136);
ctx.stroke();
// Нос
ctx.strokeStyle = "#aa8877";
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(0, -131);
ctx.lineTo(0, -123);
ctx.lineTo(3, -120);
ctx.stroke();
// Рот
ctx.beginPath();
ctx.moveTo(-5, -118);
ctx.quadraticCurveTo(0, -117, 6, -118);
ctx.stroke();
ctx.restore();
}
Второй арт
Промпт:
Напиши HTML-код, который рисует интересный сюжет из фильма «Люди в черном» на canvas размером 1200×600 пикселей. Рисунок создается программно с использованием только нативного JavaScript и Canvas, без внешних библиотек и изображений.
Полученный код изображает агента в черном и пришельца с миндалевидными глазами на фоне ночного города, в небе которого двигаются стилизованные туманности и галактики. Агент нажимает периодически кнопку на нейрализаторе, происходит знаменитая зелёная вспышка, которая эффектными бликами отражается в больших глазах пришельца и окнах домов ночного города. После чего пришелец впадает в транс и безвольно циклически двигается из стороны в сторону.

Глядя на этот завораживающий процесс, можно бесконечно медитировать и получать удовольствие.
Этот арт тоже получен за 2 шага после корректирующего персонажей промпта.
Посмотреть арт в динамике в песочнице.
Третий арт
Промпт:
Напиши HTML-код, который рисует Корбена Далласа и Лилу из фильма «Пятый элемент» на canvas размером 1200×600 пикселей. Рисунок создается программно с использованием только нативного JavaScript и Canvas, без внешних библиотек и изображений.
Полученный код изображает Корбена Далласа и Лилу рядом с такси на фоне ночного города, в небе которого проносятся другие летающие автомобили. Заметно дыхание персонажей и легкие телодвижения.

Посмотреть арт в динамике в песочнице.
Модель не просто исполняет инструкции промпта. Она придумывает сюжет, создаёт композицию, анимирует персонажей, реализует динамический фон. А также грамотно подбирает цвета и градиенты, применяет реалистичные и согласованные движения и перемещения элементов композиции.
Ну и напоследок, раз уж я сравнил эту модель с Леонардо да Винчи, пусть она попробует нарисовать знаменитый рисунок Леонардо «Витрувианский человек».
Модель подошла творчески и решила поглубже войти в образ и в коде применила такие нюансы, как «эффект выцветания по краям», «небольшие трещины пергамента», а также знаменитые высказывания на латыни типа «homo ad quadratum et circulum», но справа налево, как иногда делал сам Леонардо.
Ну и подпись тоже в обратном порядке. Хороший ход.

Посмотреть арт в песочнице.
P.S. Все HTML-файлы с артами можно скачать архивом здесь и посмотреть локально.
Автор: Keep_lookout