Как стать автором
Обновить

Апскейл видео из SD (DVD) в FullHD/4K современными нейросетями

Уровень сложностиСредний
Время на прочтение13 мин
Количество просмотров1.6K

Меня давно интересовала тема апскейла изображений, отдельно - апскейла старых видео. Одно из первых решений, которое попалось в руки несколько лет назад - waifu2x (https://github.com/nagadomi/waifu2x). Но эта нейронка больше подходила для апскейла аниме (насколько я помню на них она и тренировалась). То есть, waifu2x подходила для довольно простых изображений без избытка деталей и сложности текстур.

Затем я поизучал ESRGAN (https://github.com/xinntao/ESRGAN) и Real-ESRGAN (https://github.com/xinntao/Real-ESRGAN). Довольно неплохие модельки, вполне годятся для апскейла изображений, но очень часто заметна синтетичность, особенно в сложных сценах, например когда на изображении есть деревья. Я даже попробовал дотренировать Real-ESRGAN, к слову это делать не сложно, на их гитхабе есть скрипты и инструкции (https://github.com/xinntao/Real-ESRGAN/blob/master/docs/Training.md), но пока дособирал свой датасет для тренировки на глаза попалась другая модель - SwinIR (https://github.com/JingyunLiang/SwinIR), потестировав которую понял - она покрывает мои текущие потребности, если не полностью, то по меньшей мере процентов на 80%. А потребности были - заапскейлить несколько старых фильмов, и чтобы после апскейла фильм смотрелся как фильм, а не как пластилиновый театр. В целом все получилось. Именно об этом эта статья.

Апскейлить будем фильм "Пираты Силиконовой долины" (1999г, США). Он повествует о появлении домашнего ПК и становлении компаний Apple и Microsoft. Довольно интересный фильм с бунтарским духом той эпохи. Главные герои - молодые Джобс, Возняк, Гейтс и другие участники "революции домашних ПК". Кстати, апскейлить фильм будем конечно же на домашнем ПК.

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

Слева оригинал, справа апскейл 2x
Слева оригинал, справа апскейл 2x

Или в виде анимированного гифа:

До и после апскейла
До и после апскейла

Характеристики диска:
- DVD5, MPEG-2, разрешение 720x480 (NTSC)

Моя конфигурация для этой задачи:
- Gigabyte A520M, AMD Ryzen 5 PRO 3600, 32Gb DDR4 3200 MT/s (16+16)
- Gigabyte GeForce RTX 3060 12GB, CUDA Version: 12.5
- Ubuntu 22.04

Нам понадобятся:
- ПК и видеокарта с поддержкой CUDA
- Python
- Библиотека Spandrel для Python
- Одна из моделей SwinIR
- ffmpeg и ffprobe
- Порядка 80Гб дискового пространства
- Несколько дней работы ПК (если непрерывно, то ~5 дней для апскейла в 2x на конфигурации вроде моей)

Кратко суть алгоритма:
- С помощью ffmpeg распаковываем фильм по кадрам в формате PNG
- Апскейлим каждый кадр
- С помощью ffmpeg кодируем полученные изображения в HD-версию фильма с присоединением аудио-дорожек из исходного материала

Приступим.

Актер Ноа Уайли в роли Стива Джобса прошедший апскейл 2x
Актер Ноа Уайли в роли Стива Джобса прошедший апскейл 2x

Установка ПО

Установка ffmpeg

Под Ubuntu:

apt update
apt install ffmpeg

(при установке ffmpeg одновременно подтягивается ffprobe)

Под Windows:
https://www.ffmpeg.org/download.html

Качаем один из последних build, распаковываем архив, например в c:\ffmpeg. Из архива нам нужны две утилиты: ffmpeg и ffprobe.
Можно прописать путь к папке ffmpeg в PATH, чтобы вызывать ffmpeg из командной строки в любой директории.

Установка Spandrel

pip install spandrel

Скачивание модели

Список доступных моделей SwinIR:
https://github.com/JingyunLiang/SwinIR/releases

Я тестировал все модели из списка, наиболее понравились эти 2:
Для апскейла 2x: 003_realSR_BSRGAN_DFO_s64w8_SwinIR-M_x2_GAN.pth
Для апскейла 4x: 003_realSR_BSRGAN_DFOWMFC_s64w8_SwinIR-L_x4_GAN.pth

Качаем модель, запоминаем путь к модели.

Я делал апскейл до 2x, соответственно модель: 003_realSR_BSRGAN_DFO_s64w8_SwinIR-M_x2_GAN.pth

О требуемом времени и ресурсах будет ниже, замечу лишь, что апскейл в 4x будет существенно дольше, а качество в сравнении с 2x скорее незначительное, а в чем-то хуже.

Этап1: Распаковка видео

Склейка VOB'ов

В моем DVD экземпляре 4 основных vob'а:
VTS_01_1.VOB
VTS_01_2.VOB
VTS_01_3.VOB
VTS_01_4.VOB

Склеим их.
Команда для Linux:
cat VTS_01_1.VOB VTS_01_2.VOB VTS_01_3.VOB VTS_01_4.VOB > video.vob

Команда для Windows:
copy /b VTS_01_1.VOB+VTS_01_2.VOB+VTS_01_3.VOB+VTS_01_4.VOB video.vob

Дальше будем работать с объединенным video.vob.

Сразу можно выгрузить аудио-дорожки. Посмотрим какие вообще есть:
ffprobe -i video.vob

Видим 2 аудиодорожки:

Stream #0:2[0x80]: Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s, Start-Time 0.281s
Stream #0:3[0x81]: Audio: ac3, 48000 Hz, stereo, fltp, 192 kb/s, Start-Time 0.281s

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

ffmpeg -i video.vob -map 0:a:0 -c copy audio_track_eng.ac3 -map 0:a:1 -c copy audio_track_rus.ac3

Параметр "-c copy" указывает выгружать аудио как есть, без пережатия.

Теперь можно приступить к распаковке фреймов.

Раскадровка

Ремарка:
Здесь и далее все команды приводятся под Linux. Под Windows они обычно идентичные, если не задано другого варианта явно, за исключением указания путей к директориям. В Linux путь к директории идет через прямой слеш "/", в Windows через обратный "\".

В идеальном сценарии мы могли бы выполнить простую команду:
ffmpeg -i video.vob "video_in_png/file_%06d.png"

После чего в папке "video_in_png" появились бы все фреймы в исходном количестве и в исходном разрешении. Но... Из двух DVD, которые я успел обработать, в обоих случаях были "особенности". Данный диск оказался самым сложным из них.

Во-первых, реальная частота кадров. Я смотрел данные по ней несколькими утилитами и разными способами, вот краткий список FPS, которые определялись для фильма:
60000/1001 = 59,94...
29970/1000 = 29,97
119/4 = 29,75
24000/1001 = 23,98...

Мне даже пришлось смотреть VOB файлы в hex-редакторе и по определенным сигнатурам расшифровывать значения байтов (большое спасибо ChatGPT).
Там я узнал "точно", что:

  • фреймрейт 29.97 fps - не правда (спойлер: либо диск скомпонован криво, либо я просто не до конца разбираюсь в структуре DVD)

  • разрешение 720x480 - не правда, фактическое разрешение оказалось 640x480

UPD:

В комментариях поправили, возможно отображаемое разрешение диска было 720x540 (исходное 720x480, где пиксели растягиваются по вертикали до 540). Сложно понять, как на самом деле, я совсем не доверяю служебной информации этого диска. В любом случае растянутые пиксели исходной картинки нам были не нужны, ведь мы и так собрались их "растягивать" через апскейл, поэтому 640x480 вероятно оптимальный выбор в любом случае.

Кстати, утилита ffprobe тоже выводит эти данные:
Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv, smpte170m, progressive), 720x480 [SAR 32:27 DAR 16:9], 29.75 fps

Еще и уверяет, что видео формата 16:9, тогда как оно 4:3.

В общем методом перебора я пришел к тому, что реальная частота кадров:
24000/1001, то есть, ~23,98 fps. Не хочу сильно задерживаться на этом, это история размером с отдельную статью, и надеюсь данный случай был редким исключением, поэтому нет смысла его описывать.

Улучшенное изображение
Улучшенное изображение

Отдельно - история с разрешением. Все утилиты, а также биты в исходных VOB'ах, говорят, что разрешение видео стандартное - 720x480, но если выгружать фреймы в этом разрешении, картинка становится растянута по горизонтали. Как уже писал выше, фактическое разрешение фреймов оказалось 640x480. Это я вывел эмпирически, и позже подтвердил расчетами (на всякий случай). Здесь тоже не хотелось бы задерживаться, надеюсь этот диск просто исключение, видеоряд формата 640x480 записали как стандартное для DVD разрешение 720x480, и вероятно просто не корректно внесли разметку в структуру данных.

Если бы вместо:
720x480 [SAR 32:27 DAR 16:9]
было указано:
720x480 [SAR 8:9 DAR 4:3]
Тогда бы все сходилось. SAR (Sample Aspect Ratios) если простыми словами, указывает, как растянуть или сузить видео. На всякий случай формула расчета:
Ширина фактическая = Ширина исходная (в файле) x (SAR_width / SAR_height) = 720 x (8/9) = 640, высота не меняется, итого 640x480.

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

Итоговая команда для выгрузки фреймов:
ffmpeg -i video.vob -r 24000/1001 -vf "scale=640:480:flags=lanczos" "/home/user/frames_orig/file_%06d.png"

Здесь:
"-i video.vob" - исходный объединенный файл
"-r 24000/1001" - частота кадров равная ~23,98 кадров/сек
"-vf "scale=640:480:flags=lanczos"" - фильтр выходного потока: меняем разрешение на 640x480 и добавляем метод интерполяции Ланцоша, последний хорошо сглаживает неровности на изображении после любой его деформации, но сохраняет четкость изображения
"/home/user/frames_orig" - директория куда будут выгружаться фреймы; нужно предварительно создать
"file_%06d.png" - формат PNG, маска файлов %06d - 6-значный счетчик начиная с 000000, файлы будут вида "file_000000.png", "file_000001.png" и тд.

Вариант этой же команды, но с использованием GPU (CUDA), работает обычно быстрее:
ffmpeg -hwaccel cuda -i video.vob -r 24000/1001 -vf "scale=640:480:flags=lanczos" "/home/user/frames_orig/file_%06d.png"

Еще раз напомню, если бы не было проблем с конкретным диском, команда была бы проще и очевидней:
ffmpeg -i video.vob -vf "scale=640:480:flags=lanczos" "/home/user/frames_orig/file_%06d.png"

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

Если бы мы выгружали фреймы этой командой, тогда каждый 3-5 фрейм был бы дублем предыдущего. Всего бы выгрузилось 174000 фреймов, тогда как фактически их 139202, или 139235 по другой оценке, но не будем про это, и так достаточно :)

Кстати, насчет другого DVD который я апскейлил.
Параметры видеоряда там были следующие:
Stream #0:0: Video: mpeg2video (Main), yuv420p(tv, top first), 720x576 [SAR 64:45 DAR 16:9], 25 fps, 25 tbr, 1k tbn

Они соответствовали действительности. Исходя из исходного разрешения 720x576 и SAR 64:45, выходило, что кадр будет выведен на экран в разрешении 1024x576 16:9 (720 x (64/45) = 1024). Я хотел увеличить разрешение видео 2 раза, до FullHD, соответственно разрешение исходного кадра нужно было 960x540 (умножаем на 2 получается 1920x1080). Здесь главное, что пропорции сохранены, 1024x576 и 960x540 оба 16:9. Соответственно выгружал фреймы командой:
ffmpeg -i video_in.mkv -vf scale=960:540:flags=lanczos "/home/user/frames_orig/file_%06d.png"

Актер Майкл Энтони Холл, в роли Билла Гейтса, кажется всем доволен
Актер Майкл Энтони Холл, в роли Билла Гейтса, кажется всем доволен

Этап2: Апскейл фреймов

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

Пример команды в Linux для разбивки общей папки на несколько по 10тыс файлов:
i=1; for file in all_frames/*; do mkdir -p "frames_((i/10000+1))file" "frames_$((i/10000+1))"; ((i++)); done

Команда для Windows (PowerShell):
i=1; Get-ChildItem all_frames | ForEach-Object { $d=([math]::Floor(($i-1)/10000)+1)"; if (!(Test-Path $d)) {New-Item -ItemType Directory -Path $d | Out-Null}; Move-Item $_.FullName $d; $i++ }

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

Основной скрипт:

Код:
import os
import torch
from PIL import Image
import torchvision.transforms as transforms
from spandrel import ImageModelDescriptor, ModelLoader


# ПАРАМЕТРЫ
images_path = "/home/user/frames_in"
output_dir = "/home/user/frames_upscaled"
os.makedirs(output_dir, exist_ok=True) # Создаем папку если не найдена

model_path = "/home/user/models/003_realSR_BSRGAN_DFO_s64w8_SwinIR-M_x2_GAN.pth"

batch_size = 2  # Размер батча
batch_images = []  # Очередь изображений в батче

output_format = "JPG"  # PNG, JPG

# Список изображений
all_files = sorted([f for f in os.listdir(images_path) if os.path.isfile(os.path.join(images_path, f))])
all_files_count = len(all_files)

# Очищать torch.cuda.empty_cache(), True или False, иногда помогает вместить изображения в батч
clean_cache = 0

# Загрузка модели
model = ModelLoader().load_from_file(model_path)
assert isinstance(model, ImageModelDescriptor)
model.cuda().eval()


def save_image(image_name, output_tensor):
    ''' Преобразование изображения из тензора и сохранение в зависимости от заданного формата '''
    
    output_image = transforms.ToPILImage()(output_tensor.cpu().clamp(0, 1))
    output_path = os.path.join(output_dir, f"{image_name}.{output_format.lower()}")
    
    fmt = output_format.upper()
    
    if fmt == "PNG":
        output_image.save(output_path, format="PNG")
    elif fmt == "JPG":
        output_image.save(output_path, format="JPEG", quality=100)
    else:
        raise ValueError(f"Ошибка формата: {output_format!r}")
        

# СТАРТ ОБРАБОТКИ    
for idx, image_in in enumerate(all_files):
    image_path = os.path.join(images_path, image_in)
    image_name = os.path.splitext(image_in)[0]
    
    image = Image.open(image_path).convert("RGB")
    input_tensor = transforms.ToTensor()(image).unsqueeze(0).cuda()

    batch_images.append({'image_name': image_name, 'input_tensor': input_tensor})
    
    # Если накопился полный батч или это последнее изображение - обрабатываем батч
    if len(batch_images) == batch_size or idx == all_files_count - 1:
        try:
            # Очищаем память Cuda если clean_cache = True (иногда помогает вместить изображения в батч)
            if clean_cache: torch.cuda.empty_cache()
            
            # Проверяем доступную память перед объединением изображений в батч
            required_memory = sum(item['input_tensor'].element_size() * item['input_tensor'].nelement() for item in batch_images)
            free_memory = torch.cuda.memory_reserved(0) - torch.cuda.memory_allocated(0)
            if free_memory < required_memory:
                raise RuntimeError("CUDA out of memory")
    
            batch_tensor = torch.cat([item['input_tensor'] for item in batch_images], dim=0)
            
            # Отправляем модели батч с изображениями
            with torch.no_grad():
                output_tensor = model(batch_tensor)

            # Сохраняем обработанные изображения
            for i, item in enumerate(batch_images):
                image_name = item['image_name']
                save_image(image_name, output_tensor[i])
                
        except RuntimeError as e:
            if "CUDA out of memory" in str(e):
                print("Ошибка наличия свободной памяти, обрабатываем изображения по одному...")
            
                for item in batch_images:
                    image_name = item['image_name']
                    single_tensor = item['input_tensor']
                
                    with torch.no_grad():
                        output_tensor = model(single_tensor)
                    save_image(image_name, output_tensor[0])
                    
            else:
                raise
                
        except Exception as e:  # Другая ошибка
            print(f"Ошибка: {e}")
        
        finally:  # Очищаем батч
            batch_images.clear()


print("ГОТОВО.")


# Выгружаем модель
del model
torch.cuda.empty_cache()

Пояснение по некоторым параметрам.
batch_size = 2
Размер батча который мы передаем модели, сколько изображений обрабатывать одновременно. Я обычно использую 2, т.к., во-первых - это существенно ускоряет обработку в сравнении с 1 изображением, во-вторых - оптимальное расходование памяти, в третьих - дальнейшее увеличение батча, в моем случае, почти не дает прироста скорости, зато потребление памяти возрастает существенно.

К слову, для фреймов в разрешении 640x480 на моей RTX 3600 12Gb batch_size максимум 3, больше не хватит памяти; для 960x540 максимум 2 фрейма можно отправить видеокарте единовременно.

А вот замер обработки фреймов в разрешении 320x240 с разными батчами, апскейл 2x:

Открыть

1 batch:
Время выполнения: 1 минута 40 секунд
Максимум памяти использовалось: 849.29 MB
Максимум памяти включая резерв: 982.00 MB

2 batches:
Время выполнения: 1 минута 14 секунд
Максимум памяти использовалось: 1612.66 MB
Максимум памяти включая резерв: 1840.00 MB

3 batches:
Время выполнения: 1 минута 13 секунд
Максимум памяти использовалось: 2365.52 MB
Максимум памяти включая резерв: 2712.00 MB

4 batches:
Время выполнения: 1 минута 12 секунд
Максимум памяти использовалось: 3122.71 MB
Максимум памяти включая резерв: 3570.00 MB

6 batches:
Время выполнения: 1 минута 12 секунд
Максимум памяти использовалось: 4640.16 MB
Максимум памяти включая резерв: 5328.00 MB

8 batches:
Время выполнения: 1 минута 12 секунд
Максимум памяти использовалось: 6153.86 MB
Максимум памяти включая резерв: 7046.00 MB

10 batches:
Время выполнения: 1 минута 12 секунд
Максимум памяти использовалось: 7674.44 MB
Максимум памяти включая резерв: 8778.00 MB

12 batches:
Время выполнения: 1 минута 12 секунд
Максимум памяти использовалось: 9183.08 MB
Максимум памяти включая резерв: 10538.00 MB

Как видно прирост в скорости заметен лишь в сравнении 2 batches и 1 batch. Возможно на других конфигурациях и видеокартах увеличение батча скажется существеннее.

output_format = "JPG" # PNG, JPG
В каком формате сохранить увеличенное изображение. Итоговые файлы я обычно сохраняю в JPG, т.к. увеличенные фреймы в PNG будут занимать слишком много места, а вот исходные фреймы выгружаю через ffmpeg в PNG.

clean_cache = 0 # True или False
Нужно ли очищать кеш CUDA перед проверкой доступной GPU памяти. Честно признаться - это костыль, чтобы впихнуть невпихуемое вместить фреймы в батчи в отдельных случаях. Только с помощью этого костыля мне удалось вместить 2 фрейма в батч в случае обработки другого диска, где разрешение входящих фреймов было 960x540.

По другим параметрам должно быть все очевидно.

Запускаем скрипт и уходим на несколько дней ждать обработки.

Примеры изображений ДО и ПОСЛЕ

(рекомендуется смотреть в увеличенном)

Слева оригинал, справа апскейл 2x
Слева оригинал, справа апскейл 2x
Слева оригинал, справа апскейл 2x
Слева оригинал, справа апскейл 2x
Слева оригинал, справа апскейл 2x
Слева оригинал, справа апскейл 2x
Слева оригинал, справа апскейл 2x
Слева оригинал, справа апскейл 2x
Слева оригинал, справа апскейл 2x
Слева оригинал, справа апскейл 2x

Или к примеру анимированные гифки в большем разрешении:

Сравнение в гифах:
До и после
До и после
До и после
До и после
До и после
До и после
До и после
До и после
До и после
До и после

Этап3: Финал, кодирование видео

После того как мы запскейлили все фреймы, остается закодировать итоговое видео.
Команда:
ffmpeg -r 24000/1001 -i "/home/user/frames_upscaled/file_%06d.jpg" -i "/home/user/audio_track_rus.ac3" -i "/home/user/audio_track_eng.ac3" -c:v hevc_nvenc -b:v 10M -minrate 5M -maxrate 15M -bufsize 30M -preset p7 -map 0:v -map 1:a -map 2:a -metadata:s:a:0 title="Russian" -metadata:s:a:0 language=rus -metadata:s:a:1 title="English" -metadata:s:a:1 language=eng -c:a copy -pix_fmt yuv420p video_hd.mkv

Здесь:
"-r 24000/1001" - частота кадров равная ~23,98 кадров/сек
"-i /home/user/frames_upscaled/file_%06d.jpg" - директория с увеличенными фреймами
"-i "/home/user/audio_track_rus.ac3" -i "/home/user/audio_track_eng.ac3"" - подключаем аудиодорожки
"-c:v hevc_nvenc" - кодек
"-b:v 10M -minrate 5M -maxrate 15M" - переменный битрейт, среднее значение 10Мбит/сек, минимальное 5Мбит/сек, максимальное 15Мбит/сек
"-bufsize 30M" - размер буфера для переменного битрейта, рекомендуется использовать 2x от maxrate (2x15M=30M), либо можно не указывать, оставить на усмотрение ffmpeg
"-preset p7" - пресет 7 для кодека hevc_nvenc, высокое качество
"-map 0:v -map 1:a -map 2:a" - порядок потоков которые подключаем в итоговый файл: видео из фреймов, аудио1, аудио2 - которые указали до этого
"-metadata:s:a:0 title="Russian" -metadata:s:a:0 language=rus -metadata:s:a:1 title="English" -metadata:s:a:1 language=eng" - прописываем мета-информацию о языках аудиодорожек
"-c:a copy" - копировать аудио без пережатия
"-pix_fmt yuv420p" - цветовой формат пикселей, для обычных видео обычно используется yuv420p
"video_hd.mkv" - имя выходного видео в контейнере MKV

Ждем компиляции и все готово.

Заключение

Мы заапскейлили фильм с помощью модели SwinIR. В принципе можно попробовать любую другую модель, библиотека Spandrel позволяет работать со многими моделями. Есть сайт https://openmodeldb.info/ где сотни моделей на разных архитектурах, в основном там тюны базовых моделей.

Внимание:
Если у вас PyTorch ниже версии 2.6, тогда настоятельно рекомендуется запускать модели .pth/.bin от неизвестных авторов с флагом weights_only=True. Это связано с тем, что в бинарные файлы моделей может быть встроен вредоносный код, который может произвольно выполниться при десериализации модели (при загрузке). Если мы задаем флаг weights_only=True, тогда PyTorch загружает только веса модели.
Начиная с PyTorch 2.6 флаг по умолчанию стал weights_only=True, если значение параметра не передается явно.

Итого, из исходных 640x480 мы получили видео 1280x960 (4:3). Это не стандартное разрешение формата HD (1280x720 16:9) или FullHD (1920x1080 16:9), но и исходный материал оказался не стандартным.

Ниже будут ссылки на примеры кадров ДО/ПОСЛЕ, а также фрагмент видео ДО/ПОСЛЕ. В целом качество вполне приличное, как-будто действительно полноценное HD.

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

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

Дополнительные материалы

Примеры кадров ДО и ПОСЛЕ можно посмотреть и скачать на моем гугл-диске. Там же есть примеры изображений увеличенных в 4 раза. Некоторые примеры опубликую у себя в Тг-канале.

Фрагмент видео: оригинал и улучшенный.

После того как из DVD видео сделали HD, его можно переделать в 3D. Об этом я писал в другой статье:
Как сделать 3D версию любого фильма на примере StarWars4 (DepthAnythingV2 + Parallax)

Спасибо за внимание.

Теги:
Хабы:
+3
Комментарии28

Публикации

Ближайшие события