Раскраска фильмов до этого года стоила сотни тысяч долларов, требовала участия массы специалистов и занимала много времени. Теперь всё изменилось. Развитие проекта Deoldify дошло до такого состояния, что результаты его работы можно комфортно смотреть, расслабив фейспалм. Из текста вы узнаете подробности успешного эксперимента по оцветнению фильма без денежных затрат, завершенного за несколько недель силами одного человека. Эта история начиналась так же, как и любая другая подобная история. Сумасбродный алгоритм рекомендаций youtube выдал нечто, что привлекло моё внимание и что имело самые неожиданные дальнейшие последствия. В предпоследний раз это привело к залипанию на канале Forgotten Weapons. Сложно наверняка понять, почему мне было выдано тогда такое предложение, но, скорее всего, было так:

1. user_id смотрит ролики по RDR2.
2. В RDR2 есть Volcanic pistol.
3. На канале Forgotten Weapons есть обзор Volcanic pistol.
4. Люди, интересующиеся RDR2, часто хотят узнать про Volcanic pistol.
5. Тысяча чертей, да ему точно зайдёт Forgotten Weapons!

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

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

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

Любопытство потащило за собой, уже изучаю проект на github'е. После теста облачной версии на паре фотографий, после разглядывания роликов, во мне явно стало зреть какое-то желание. Возможность возвращать в актуальный медиаконтекст настоящие свидетельства прошлого, без вложения сотен тысяч денег, хм, в этом есть что-то захватывающее, что-то вполне достаточное, чтобы взбодрить остывший разум.

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

 Ну, предположим, мотор, action. Берём первый попавшийся видеоряд на 4 минуты. Что сначала? Убрать мерзкую тряску камеры и плёнки, которые есть в таком материале по умолчанию всегда. Ищется какие есть варианты с широким диапазоном контроля, и вне видеоредакторов. Поскольку предстояло использовать целую цепочку разных программных средств, использование любых стандартных пакетов редактирования видео сразу отпадало. Только отдельные кадры файлами, только хардкор. И, конечно, надо не просто как-то стабилизировать, а киношно стабилизировать, имитируя ограниченные и плавные движения киноаппарата. Хоть какое-то доверие вызвал один-единственный модуль для python. Ну, ок, значит, код пойдёт сразу.

Стабилизировали. Долговато что-то, ну ладно. Вау, круто, получилось, да, то что надо, конечно, надо допиливать напильником, но иначе зачем мы здесь собрались? Далее само оцветнение. Ставим то, ставим это, ставим другое, опять конфликт, ещё ставим, поверху, сбоку, не сдаёмся, может мануал почитать, кажется, пошло, нет, delete dir, ещё раз, о, вот так, хорошо, наконец-то. Запуск. Блин, чо-то совсем долго. Зато цвета, цвета, ух ты прямо да, а во всем этом, правда, есть смысл и стоит продолжать.

Что теперь? Наверное, в 2019 году интерполяция кадров не является чем-то выдающимся, и можно нарыть проект для условно профессионального применения. И таки да, опять успех, такой проект свободно доступен. Ставим то, ставим это… Запуск. Блин, чо-то опять небыстро. Зато как плавно, как плавно кадры сменяют друг друга, чудо, как будто обычные 24 кадра.

Так, это что же выходит, всё получилось? Весь конвейер здесь вот, готов к применению, надо только бросить в него что-то и получить результат?

:: решается ::

 На каждом этапе обработки фиксировалось потраченное время. Экстраполирую на 90 минут: нападает уныние, мягко говоря. Даже пару раз перепроверил замеры и расчёты, потому что полученные цифры превращали первоначальную задумку из «просто-быстро-легко-весело» в «просто-долго-легко-грустно». Хотя впоследствии ещё два слова в этой формуле изменятся в худшую сторону, но уже было над чем всерьёз призадуматься.

Итак, на выбранный фильм уйдёт 4 часа стабилизации, 420 часов оцветнения и 30 часов интерполяции кадров. Да-а-а… Вот уж спасибо тебе, Чарли.

Чо делать-то? Восьмиядерный mac mini 2012 это единственное, что можно запрячь. Перед глазами стояло видео с линуксом, запущенным на PS4. Зубы скрежетали в бессильной злобе от невозможности откатить апдейты прошивки, которые ставились с гордой убеждённостью, что jailbreak не нужен. ¿Как бы там работали все эти питонопроекты? ¿был бы ли доступ к расчетам на GPU? Эти вопросы мне не суждено было изучить.

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

 Наконец, суровая реальность начинает прорываться в уютный мир. Кроме проблем с железом, появляются программные проблемы. То, что в хоть как-то дефолтном виде отработало на тестовом видеофрагменте, на полноценном фильме начинает давать то тут, то там сбои. (Неожиданно, да?)

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

Главную сложность вызывает смена сцен. Проект рассчитан на обработку только коротких фрагментов, в которых контекст не меняется. После изучения, что там и как происходит, находится место для грубого патча, смысл которого в отключении стабилизации при высоких значениях смещения кадра. Без этого патча негативный эффект проявлялся как плавное выползание следующей сцены откуда-то с края в черное поле.

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

 Компьютер уносится на кухню, поскольку обычно абсолютно тихий mac mini под нагрузкой безостановочно громко шумит. Редко кому из владельцев этих штуковин удается услышать этот звук, поскольку то, что они считают шумом вентиляторов (который бывает раздается на серьезной нагрузке), это лишь половинная частота вращения от возможной. Запускается оцветнение.

Файлы проекта пришлось немного пропатчить, чтобы научить работать с моими входящими данными, и складывать их в нужном формате, порядке и виде. Хоть и пришлось написать небольшой скрипт для запуска, будем считать, что проект работает без допила напильником. Вопросы могут возникнуть только по параметру render_factor.

Влияние на результат следующее:
0-7 полная каша
8-12 перенасыщенные цвета, грубая раскраска (для плохо распознаваемых сцен дает хоть какой-то эффект)
13-18 такое себе, для нераспознанных сцен стоит попробовать сначала этот диапазон
19-20 для экспериментов (выполним шинопровод из берёзовой коры)
21 — оптимальное число
>=22 начинает теряться насыщенность, смысл использования падает

Чем меньше это число, тем меньше расход памяти и быстрее происходит расчет. М-да. На другой день в голове всплывают воспоминания о том, что процессор i7 имеет режим turbo, и даже как-то проверялась его работа. Находится информация, о том как его активировать под Windows, и тестовые утилиты начинают показывать более бодрые значения частоты ядер. Температура процессора скачет в диапазоне 85-99 °C. Сверху ставится кастрюля с водой для отбора тепла. Снизу дует охладитель от ноутбука. Если раньше в сутки обрабатывалось 5% кадров, то в ускоренном режиме это значение стало 7%. Хоть какая-то радость. Любая программа может упасть. Конечно оцветнение упало. Ну упало, перезапустим. И тут настал «ой». Иногда в прод попадают версии для экспериментов, ну вы понимаете, так вот, когда я патчил модули проекта, то, отвлекшись, забыл просмотреть всю цепочку и смысл каждой инструкции и считал патчинг завершенным. Проект изначально удаляет временную папку, создает новую, складывает туда вытащенные кадры из видео… в общем вы уже догадались, что папку с результатами за сутки мне снесло.

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

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

 Ладно, вроде как-то жизнь наладилась, миник спокойно гудел, можно было уже планировать дальнейшие работы и писать скрипты для постобработки.

Просмотр оцветненного материала вызвал кроме радости еще и досаду. Было две неприятных вещи. Во-первых, тон цвета скакал между кадрами, скорее всего из-за неравномерной яркости исходника. Во-вторых, обнаружилась куча дублирующихся кадров. Казалось бы зачем, но, видимо, чтобы бытовые видеоплееры не сходили с ума от чего-то меньшего чем 24 кадра/с.

Проблемы есть и их надо как-то решать. Становится очевидным, что поток кадров необходимо разбивать на сцены. Чтобы регулировать тон/яркость, нужно иметь границы. А чтобы не поудалять тексты вместе с дублирующимися кадрами, нужно разделить кадры на текст и не_текст.

Начинаются долгие эксперименты с определением похожести кадров. Ну, здравствуй, opencv, что ты такое?
Пропустим душевные метания (их будет видно по коду), количество версий, испробованных методов (видно по количеству вспомогательных функций). Попробую объяснить финальную версию.
 Загружаем последовательно два кадра. Делаем легкое размытие, черт знает зачем, но раз так, значит эксперименты показали улучшение результатов (возможно, исключается влияние шума). Находим ключевые точки в кадрах и производим их сравнение.
 Пояснение для незнакомых с opencv:

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

ORB — это один из многих методов выделения ключевых точек.

des — descriptions, параметрические описания ключевых точек.

BFMatcher — хренота, для проведения сравнения ключевых точек, используя des. Её задача, выделить одну и ту же точку в двух массивах и рассчитать величину ухода каждой заматчившейся точки с первоначального положения. Сорри ми майн инглеж.

Получается, что чем меньше суммарное расстояние смещения точек, тем идентичнее кадры.
 Если score больше магического числа, то стоит провести дополнительные проверки, возможно это действительно уже другая сцена? Для начала проверим, не является ли какой-нибудь кадр из двух текстом, во-первых, нам нужен этот признак, во-вторых, если произошло изменение типа кадра(текст -> не_текст), то сцена точно сменилась. Приводим цветное изображение к монотонному и отправляем в детект текста нездорового человека (хотя is_text еще прекраснее).
 Если попробовать описать суть, то происходит поиск замкнутых контуров, и если получается так, что мы имеем множество контуров, попадающих по своим размерам в наши магические ожидания, то высока вероятность, что это текст. Как можно догадаться, этот код пришел на замену is_text, можно считать его удачным, хотя есть фейлы на очень БОЛЬШИХ буквах и сценах вроде бликов на черной воде. Словами тут сложно будет передать все метания между разными вариантами «просто, но работает» и «точно работает, но overkill». Какое-то инженерное жлобство не позволяло уходить далеко от решения «черные полосы по всем краям = текст».
 Если текстом тут не пахнет, тогда пробуем сравнить черно-белые гистограммы, если подозрения усиливаются, то сравниваем цветные, если прямо очень подозрительно, то сравниваем через один кадр, чтобы уж прямо наверняка.
 Здесь чисто практические действия: если скрипту захотелось сделать короткую сцену, то, вероятно, ему показалось и лучше добавить эту сцену в предыдущую. А если кадров в сцене стало больше 90, то это увеличит время дальнейшей обработки сцены.

Найти что-то по компенсации тона оказалось непросто. Явно гуглится лишь одна научная статья и связанный с ней проект.

 Если хочешь что-то сделать, сделай это сам. Делать самому не хочется, но придется. Гуглёж с пристрастием наконец помог найти в opencv хоть что-то, что могло мне помочь. Обнаружился набор классов, для сшивки панорамных фото, среди которых был механизм для коррекции различий освещенности и тона. Не совсем то что надо, но это хотя бы вариант.

После долгих экспериментов с единственным (да!) примером использования этой штуки, наконец получился полезный код. Вся магия заключалась в опытном установлении подходящего для моих целей класса, и выяснении формата маски. Дальше очевидно: накормить компенсатор изображениями для расчета усредненного значение общей экспозиции и уровня каждого цветового канала, потом повторно подсунуть ему исходники уже для преобразования.

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

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

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

Оставалось придумать как вычислять дубликаты. Логично предположить, что с этим справится тот же самый код, что находил окончание сцен, но с другими параметрами. Почти так и оказалось. Почти.

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

github.com/sniklaus/3d-ken-burns

Поставил, стал патчить, получил искомый результат. Но. Функция отделения объекта от фона еще далека от идеала. И куски модели оставались на «небе». Как ни крутил «камеру», но подобрать ракурс, чтобы и перспектива была правильная и артефактов не было, не вышло. Жаль.

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

 Результат сильно зависит от исходного материала и, возможно, приведенный пример не объясняет зачем надо было это делать, но сцены, которые раздражали, больше не беспокоили. Зайдя в очередной раз попить водички, насторожился, вентилятор миника шумел как-то, ну не так. Монитор не включался, чертыхнулся и попробовал выключить-включить. Вентилятор завелся, но звука, сообщающего о начале загрузки не было. Началась диагностика с разным подключением мониторов, зажиманием разных секретных комбинаций клавиш, и пару раз компьютер ненадолго включился с появлением изображения, но через несколько секунд все обрывалось, либо же сразу начиналась радужная цветомузыка. Потом хоть какие-то включения прекратились. Пришлось признать неизбежное: отчалил чипсет. Сняв сервисную крышку, я понял, кто тут дурак, и что следовало очень серьезно отнестись к вопросу охлаждения. Честно говоря наивно полагал, что схемотехники эпл оставили хорошую защиту по теплу от дураков, но видимо эти люди не рассчитывали, что найдутся идиоты, гоняющие десятки суток (да, к этому моменту уже прошло больше недели) mac mini без перерыва в экстремальном температурном режиме.

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

Вокруг образовалось тьма. Было вот совсем не до этих проблем, но что-то делать придётся. Почитав истории про утюг и духовку, посмотрев каким станком делают нормальную установку чипа, пришлось смириться с реальностью и начать поиск сервиса.

 Понятия не имею как поздно ночью найти сервис, способный провести данную операцию разумно, быстро и за нестрашные деньги. Что-то там нашел, вызвавшее доверие. Смутило конечно, что телефон не гуглился, ну да ладно. Компьютер отдан, общение было приятным, при мне другому клиенту объясняли, что ремонт его приставки будет дороже б/у и обещали предложить варианты. Еще подумалось, «какие милые пупсики, о клиенте заботятся».

Вечером позвонил менеджер с результатами диагностики, он подтвердил мою версию про чипсет и сообщил, что гарантия на замену чипа не предоставляется (э, да как так, сайт же обещал?), и что правильнее будет купить б/у аналог. Всё это стало странно попахивать, но допустим. Стал ждать результатов поиска «аналога». На второй день сомнения усиливались, зашел на авито и стало совсем невесело, поскольку цена была равна цене нового в 2014. Это мягко говоря «не соответствовало ожидаемым размерам бюджета проекта». Менеджер что-то не отзванивался, набрал его сам послушать новости. Он вроде узнал меня, но вместо предложений «аналогов», на вопрос «фигли так долго?», пробормотал что-то про поиск доноров для ремонта в Москве. А? Чо? Какой ремонт? Кажется пришло время искать отзывы о сервисе. Уже можно! Вот теперь пора!

Полчаса поисков и уже бегу вызволять своё сокровище из грязных лап мерзких обманщиков. Да, пришлось заплатить денежку за «диагностику», но ты же сам подписал договор? Страдай, ъуъ.

Было обидно потерять 3 дня, а главное было непонятно что же делать дальше. Искать новый сервис что-то не хотелось. Покупать часы в облаке нелогично, черт его знает сколько еще доделок и переделок понадобится, и всё это без привычного инструментария и полного контроля. Выходило, что нужен новый комп. В концепцию «просто-быстро-легко-весело» явно закралась какая-то ошибка. Но бросить всё после потраченных сил уже просто нельзя.

 Собрать компьютер для GPU-рендеринга без денег выглядит невозможным. И таковым и является. Пришлось потратить еще половину дня, чтобы разобраться в современных железках и вычислить оптимальный конфиг нищего датасаентолога.

Собираем, включаем, не работает. Допустим. Вставляем видеокарту. Появляется сообщение про нехватку питания, и предложение подключить кабель от блока питания. Какой еще кабель, ну бывает, забыл проверить его наличие у блока питания, зато 720 рублей за 400 Вт. Откладываем карту, потом разберемся. Надо понять почему не включается сама плата. Идем на балкон, вынимаем динамик из Pentium 133 (На самом деле Cyrix 100, но кто поймет). Подключаем динамик, сигналит необычно. Гуглим. Точно не понять, производитель напрямую не предоставляет таблицу под эту плату, но все источники сходятся на том, что нет видеокарты. Ну как это нет? Вон у вас два видеовыхода на матплате. Непонятно, неужели опять беда, и надо менять по гарантии.

Через 2 часа войны, решаю переключиться, чтобы не замыкаться в нерешаемой проблеме. Втыкаю видеокарту, обрезаю провода питания для привода, вот твои 12 Вольт, радуйся.

Включаю, компьютер стартует без всяких вопросов, заранее подготовленный ssd с образом винды начинает установку. У меня замыкание, чувствую, что в мире появилось что-то чего раньше не было, и именно это является сутью моего непонимания.

Начинаю гуглить в эту сторону и выясняется, что наличие видеовыходов на матплате не коррелирует с наличием графического процессора в чипсете. Воу! Да как вы выживаете в этом мире? Вот бы удивился, если бы всё-таки склонился в сторону конфига без GPU. И ведь главное, ни в доках, ни на коробке не обращено жирным внимание на этот неприятный факт, только скромная сноска «if APU available», ну раз выходы есть наверное этот APU эвейлебл, и не стоит разбираться о чем речь, логично? Нет. Не стесняемся разгонять и получаем бесплатный 1 ГГц, долгий выбор кулера и его стоимость оправдали себя. Ставим оцветнитель. Запускаем. Бум! CUDA out of memory. Классно, отлично, утром разберемся.

На утро памяти не прибавилось. Гугл сообщал, что эта ошибка означает, что размер доступной видеопамяти меньше необходимой. В это очень не хотелось верить, потому что этому не следовало быть правдой. Ведь, я не мог ошибиться, купив версию видеокарты с урезанной памятью, нет не мог, я же никогда не ошибаюсь.

Начались эксперименты с принудительной очисткой памяти, изменением параметров, надежду давал тот факт, что падение происходило не сразу, что несколько кадров успевали появиться на выходе. Можно было конечно запустить в цикле перезапуск оцветнения, но время подготовки к запуску составляет порядка 2 минут, и смысла это не несло.

Внезапно, отладочный скрипт стал исправно работать, и обработка полетела, понятия не имею, что там навертел, решил ничего трогать, и просто получить уже свои цветные кадры. Остававшиеся 60% кадров закончились через 5 часов. К этому дню обработка на минике только бы начала подходить к концу, о, бедный миник.

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

Всего полчаса и можно ехать дальше. Запускаем тоновую компенсацию. Через пару часов пробуем порадоваться результату, но радость половинная. Небольшая часть сцен плохо оцветнена. Еще небольшой части сцен от тоновой компенсации поплохело. Если со вторым можно было, или просто взять то, что было до компенсации, или попробовать выравнять тон без использования автобаланса белого. То с переоцветнением было все сильно сложнее. Часть сцен улучшилась от уменьшения параметра render_factor, оставшиеся просто так не поддавались. Алгоритм просто не находил ничего похожего в обученной модели и выдавал странные результаты. Пришлось каждую такую сцену многократно оцветнять с разным render_factor, и потом выбирать лучший кадр, чтобы он хоть как-то напоминал истину. Сложно передать насколько это занятие выматывает мозг. Пришлось написать скрипты, собирающие для каждого кадра варианты в отдельную папку, что повысило производительность и уменьшило поток брани.

 Прежде чем двигаться дальше, нужно вырезать лишние тексты и переставить несколько сцен местами. Понадобилось какое-то простое средство для видеомонтажа. Загружаем структуру папок с кадрами прямо в текущий редактор. Удаляем сцены, меняем местами, выгружаем обновленную структуру на диск в новую папку. Теперь можно преобразовывать 12 к/с в 24 к/с.

 Начались эксперименты с алгоритмами сравнения похожих изображений. Сложность была в том, что большинство из них позволяет сообщить, что картинки совсем разные, или сравнительно сильно похожи. Для меня же почти похожи были действительно разные кадры в одной сцене, и нужно было поймать изображения, которые являются смещенными копиями. Все перепробованные алгоритмы мешали в одну кучу и то, и другое.

Хоть какую-то пользу смог принести compare_ssim из skimage. Не буду притворяться будто помню что это, это просто хотя бы иногда давало правильные результаты и позволило выявить сразу некоторую часть дубликатов. Остальное пришлось искать глазами. На второй день моя естественная нейросеть натренировалась замечать незаметное. К этому моменту меня уже мучила профдеформация: попадающиеся на глаза черно-белые изображения, воспринимались как незавершенная работа, а любое подёргивание стороннего видео-контента отдавалось резью «опять дубликаты!».

Собираем следующую версию видео, смотрим. Приходит понимание, что часть сцен имеет кислотную насыщенность. И это опять проблема, потому что нельзя просто так взять и понизить насыщенность всех сцен на общее значение, часть из них наоборот не сильно яркая.

Начинается насыщенность-challenge. Изменить этот параметр несложно, но невероятно сложно адекватно измерить. Это было понятно в теории, на практике это только подтвердилось. Любой наивный способ сравнивать насыщенность кадров натыкался в ходе тестирования на сцены, которые были яркие, но их показатель был в норме, или блеклые, но их показатель был очень высоким.

К концу дня родилось хоть как-то рабочее решение. К медиане разброса насыщенности пикселей добавляем стандартное отклонение насыщенности, и получаем условную максимальную насыщенность кадра. Это неидеально, но с таким способом измерения выравнивание насыщенности начало работать. Оставалось только подставить полином величина_коррекции = f(измеренная_величина). Составляем руками табличку на тестовых данных «замер» -> «величина коррекции, которая дала приятный результат», загоняем табличку в любой инструмент умеющий в аппроксимацию.

Итоговая функция коррекции насыщенности: Переходим из пространства BGR (дефолтное представление opencv) в HSV. Характеризуем матрицу насыщенности одним числом. Вычисляем усиление/ослабление насыщенности. Обрезаем вылеты за диапазон. Сливаем скорректированную матрицу насыщенности с исходной яркостью и тоном, возвращаемся в пространство BGR.

 Ну кажется видео наконец готово. Можно заняться музыкой.

Так как ни одно из существующих музыкальных сопровождений мне не показалось адекватным, ничего другого не оставалось кроме как сделать что-то самому.

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

На третий день работы с музыкой, количество сцен, потерявших насыщенность уже нельзя было игнорировать. Часть кадров стала совсем черно-белой, причем до этого именно эти кадры были самыми яркими. Вот интересно, что бы это могло быть? Неужели полином третьего порядка за пределами исходной таблицы резко улетает в космос? Вот ведь неожиданность, правда? Тут надо заметить, что в очередной раз пересматривать фильм целиком после коррекции насыщенности мне не хотелось, ограничился просмотром одного кадра из каждой сцены, что дало иллюзорное ощущения достаточности результата.

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

Повторяем вычищение дублей, перемонтаж, корректируем насыщенность, естественно, получаем сильный рассинхрон по звуку, начинаем переподгонять ключевые точки треков, расстраиваемся, что волшебный синхрон почти пропадает. Вот и прошла еще неделя. Писать забесплатно новую музыку совсем не вариант, но приклеивать что-то из доступных вариантов сопровождения (хотя их минимум 5) тоже не хватает честности. В процессах поиска бесплатных треков натыкаюсь на интересную штуку.

filmstro.com

Из описания становится понятно, что она позволяет сделать что-то промежуточное между подстановкой чужих треков и сочинением с нуля. Она обладает обширной библиотекой композиций, каждую из которых можно представить как проект из условного Fruity Loops. Все дорожки одной композиции сгруппированы в три секции: Интенсивность, Глубина, Напряжение. Изменяя «силу» секции, можно изменить количество активированных дорожек. Итого: одна композиция в среднем содержит 11 вариантов звучания, которые образуются как результат взаимовлияния секций. С помощью расстановки ключевых точек вдоль видеоряда осуществляется привязка изменения звучания композиции к происходящему на экране. Такой вот доширак. Вкусно, если не знать, как это получилось.
 Наконец можно сделать канал и залить видео. Казалось бы уже всё, финиш, можно отдохнуть. Но реальность не отпускала, и если исходное видео можно условно считать HD, то после заливки оно оказывалось омерзительного качества. По всем признакам и мнениям из интернета выходило, что гугл намеренно для всех новых каналов использует очень низкий битрейт. К счастью, где-то проскочил дельный совет: залить в размере 1440p, будто это заставляет ютуб бережнее относиться к пережатию. Совет правда помог, стало хотя бы смотрибельно.

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

Результат: www.youtube.com/watch?v=r3NQyCInZiQ
Ссылка на скачивание в оригинальном качестве: drive.google.com/uc?id=1dEPcjKbjNowxsfaNcbV6DsbAr3kbACKH&export=download

 То что получилось, мне в целом нравится. Конфетку бы сделала команда оплачиваемых специалистов. В данном случае: 70% нормальных кадров, 20% плохих, 10% эпичных. Бесплатно, автоматически. Все проблемы, что мне пришлось устранять руками, обусловлены лишь тем, что это делалось в первый раз. Следующий фильм оцветнить будет несоизмеримо легче. Не знаю, что это будет, в эпохе немого кино мне пока не попалось других произведений, которые бы просили, чтобы их перенесли в наше метапостбытиё. Вероятно, это будет что-то из раннего звукового кино, а значит надо восстанавливать звук, приводить его в 20-20 Кгц, преобразовывать в стерео. Столько еще разных нейросетей можно потрогать =) На сегодняшний день качество оцветнения сильно зависит от исходного материала, чем больше сохранилось оттенков серого, чем выше четкость, тем лучше результат. Скорее всего, следующие поколения подобных инструментов будут синтезировать новые высококачественные изображения, а не вписывать цвет в старые контуры, это будет похоже на проекты, которые делают имитации фотографии по рисунку от руки. А пока, чтобы получать превосходный результат, нужно вытягивать черно-белое изображение и индивидуально тренировать оцветнитель на видео-материалах, соответствующих целевому фильму.

Наша жизнь меняется быстрее и быстрее, сроки с которыми мы переходим в очередную реальность, сокращаются. Мы пишем нейросети, чтобы успевать отслеживать всё новое, что происходит с нейросетями. Но успеваем всё меньше. Всего полгода назад мне задали вопрос, можно ли автоматически сделать произвольную фотографию достоверно цветной, мой ответ был: «нет, это всё еще фантастика». Человек смыслов -=[ в поиске работы R&D NLU ]=-