Простой путь создания анимации из набора фотографий

Захотелось мне намедни создать GIF анимацию из набора фотографий. Фотографии вот такие (это между прочим анимация на библиотеке в Минске, если кто не знает):

Библиотека в Минске. Набор кадров

Все они сфотографированы примерно из одной позиции примерно одного объекта. Если создать из этих фотографий анимацию (делал с помощью сайта gifmaker.me), то получится вот такая неприглядная GIF-ка:

Сырая анимация библиотеки в Минске

Разумеется, это было мало похоже на анимацию, скорее на набор кадров. Так что пришлось вручную подгонять каждую фотографию к одному виду в графическом редакторе. Потратив на это три с лишним часа, стало понятно, что так дальше продолжаться не может — кадры скакали чуть меньше, но все равно очень заметно. Ведь фотографии отличаются не только сдвигом фотоаппарата относительно объекта, но и масштабом с искажением.

Обратился за помощью к хабра-сообществу и решение нашлось. Это программа Hugin и утилита align_image_stack, которая есть в установочном пакете этой программы.

Оно плохо работает, если кадров мало, но это лучше, чем ничего. Делюсь с вами, вдруг пригодится.

  • устанавливаем программу Hugin (ссылка для скачивания)
  • создаем файл проекта output.pto с помощью утилиты align_image_stack (align_image_stack.exe -p output.pto in_0.jpg in_1.jpg in_N.jpg). Названия файлов надо указывать по-одному, маска файлов программой не поддерживается.
  • открываем получившийся output.pto в программе Hugin
  • нажимаем «Объединить» (Hugin должен пересчитать контрольные точки для изображений), закрываем открывшееся после процедуры окно
  • после этого кнопку «Создать панораму»

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

Получаются вот такие изображения (можно их обрезать с помощью любого редактора, например IrfanView):

Выровненные изображения библиотеки в Минске

Создаем GIF-ку из получившихся фотографий:

Анимация после обработки программой Hugin

P.S. Важный момент — лучше использовать оригинальные изображения с фотоаппарата, потому что они содержат информацию о фокусном расстоянии камеры, которое необходимо программе Hugin для правильной работы.

Убираем резкие перепады входных данных

И снова в эфире наша рубрика: «Банальности программирования в массы»…

В этот раз хочу поделиться с народом штукой под названием «Low-pass filter».

«Ну что ты, в самом деле, опять про то, что все уже давным-давно знают» — скажут опытные программисты. «А вот ничего подобного» — отвечу им, лично я узнал об этом совсем недавно. И очень жалею, что не знал этого раньше.

Итак, вот функция для сглаживания входных данных:

def filter(a, b, dt, RC):
    t = dt / (RC + dt)
    return a + t * (b - a)

где a — текущее значение переменной, b — следующее значение, dt — время в миллисекундах между кадрами, RC — некий коэффициент (чем больше значение, тем больше сглаживание).

Соответственно, если вам надо сгладить какое-то значение (например, позицию камеры по Y в зависимости от позиции Y главного героя), то можно применить эту функцию следующим образом (значение RC подбирается опытным путем):

def update(dt):
    camPosY = filter(camPosY, heroPosY, dt, 0.85)

Кстати, тут используется линейная интерполяция, которая вкратце описана в этой заметке: «Линейная интерполяция и кривая Безье».

Линейная интерполяция и кривая Безье

Как-то после обеда прочитал статью на gamedev.ru, а потом в комментариях к статье нашел другую и неожиданно обрел знание: как работают кривая Безье и в чем собственно суть. И чтобы не забыть, сделал эту запись в блоге.

Вообще я сразу теряюсь, когда в статье наталкиваюсь на математические формулы и сразу пытаюсь их пролистать, а тут решил вникнуть и внезапно осенило!

Линейная кривая

Самая простая кривая Безье называется «линейная кривая», хотя она не кривая, а очень даже прямая. Это банальная линейная интерполяция от точки P_0 до P_1. Формула этой кривой вот такая: P=(1-t)*P_0+t*P_1
Параметр t у нас живет в пределах от нуля до единицы, заместо P подставляем X или Y и получаем искомое значение.

Программистами используется та же самая формула, только в профиль (убирается лишнее умножение): P=P_0+t*(P_1-P_0)

Квадратичная кривая

Следующая по сложности идет «квадратичная кривая». Она строится по трем точкам P_0, P_1 и P_2. Оказывается, она представляет собой линейную интерполяцию двух простых кривых Безье по точками P0, P1 и P1, P2 соответственно. На мой взгляд звучит ужасно сложно, в голове рисуются страшные формулы, но на деле выходит довольно просто.

Формула первой кривой: A=(1-t)*P_0+t*P_1
Формула второй кривой: B=(1-t)*P_1+t*P_2
Линейная интерполяция: P=(1-t)*A+t*B

После замены A и B получается такой монстр: (1-t)*((1-t)*P_0+t*P_1)+t*((1-t)*P_1+t*P_2)

Раскрываем, сокращаем, упрощаем: P=P_0*(1-t)^2+2*t*P_1*(1-t)+t^2*P_2

Касательная к квадратичной кривой

Если записать по науке, то формула выше такая: f(t)=P_0*(1-t)^2+2*t*P_1*(1-t)+t^2*P_2

Чтобы найти касательную к кривой Безье в любой точке t, надо вычислить производную этой функции (подсмотрено в википедии): f'(t)=2*(1-t)*(P_1-P_0)+2*t*(P_2-P_1)

Для чего может пригодится касательная:

  • поворачиваем касательную на 90 градусов, делим на длину и получаем нормаль к кривой Безье в точке t
  • берем некий шаг \Delta t, вычисляем касательную для каждой t от нуля до единицы с шагом \Delta t, суммируем длину этих касательных, умноженную на \Delta t, получаем общую длину кривой Безье, точность которой зависит от \Delta t

Если я ничего не напутал, то формула для вычисления длины выглядит вот так:

\sum\limits_{t=0}^1=|f'(t)|*\Delta t

Затем можно рассмотреть «кубическую кривую», но это уж как-нибудь сами. Вот собственно и все, чем хотел поделиться… Не судите строго.

Гранд Макет России — краткий фотоотчёт+видео

В выходные посетили выставку под названием «Гранд Макет Россия». Находится на улице Цветочной, дом 16. Категорически рекомендую посетить всем: взрослым, молодым, старым с детьми, внуками, с родственниками и друзьями! Лучше брать в прокат бинокль — можно рассмотреть больше деталей. Выкладываю десяток фотографий выставки.

Добро пожаловать, берегите макет и руки!

Гранд Макет России. Предупреждение

Кижи — без единого гвоздя. Только клей.

Гранд Макет России. Кижи

Пляж. Топлес не нашел. В следующий раз надо взять бинокль.

Гранд Макет России. Пляж

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

Гранд Макет России. Джип

«Сифон и Борода. На бухло. <дальше неразборчиво>» — гласит плакат.

Гранд Макет России. Сифон и Борода

Побег из тюрьмы. Они еще не в курсе, что их уже ждут.

Гранд Макет России. Побег из тюрьмы

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

Гранд Макет России. Гараж

Лошадки. Пока ты фоткаешь лошадок, маленькие человечки фоткают тебя.

Гранд Макет России. Лошадки

Впечатляет размер? А это ведь только половина выставки.

Гранд Макет России

И тут вездесущая оппозиция. Они ведь тоже люди! Руками не трогать!

Гранд Макет России. Митинг

Высота горы где-то 3 метра.

Гранд Макет России. Гора

Шпиль Петропавловки как живой.

Гранд Макет России. Петропавловская крепость

Строят ракету даже ночью. Наверно Байконур.

Гранд Макет России. Байконур

Превед медвед!

Гранд Макет России. Медведи

Жизнерадостные свинки. 18+

Гранд Макет России. Свинки

Компания оленей. Сибирь. Мороз.

Гранд Макет России. Сибирь

Судя по всему, тырят железо со ржавого корабля. И увозят на Ниве.

Гранд Макет России. Металлолом

В Питере даже трамвайчик присутствует.

Гранд Макет России. Трамвай

Под покровом темноты «ООН» выгружает «мирную» технику. Скорее всего Ульяновск.

Гранд Макет России. ООН

Рабочие угольной шахты. В центре фотографии — плакат времен СССР.

Гранд Макет России. Шахта

Каллинград (поезд и автобус). Был еще грузовичок красного цвета, но он в кадр не попал.

А еще рекомендую посетить музей LEGO в Петербурге.

Блог Евгения Жирнова