Re: Замена выпавших кадров (drop'ов) и SVP
Bars
1. Можно еще поинтересоваться о том как были получены выпавшие кадры?
2. Нельзя ли найти в интернете этот фильм без выпавших кадров, чтобы не заниматься лишней работой?
You are not logged in. Please login or register.
SmoothVideo Project → Эксплуатация SVP → Замена выпавших кадров (drop'ов) и SVP
Bars
1. Можно еще поинтересоваться о том как были получены выпавшие кадры?
2. Нельзя ли найти в интернете этот фильм без выпавших кадров, чтобы не заниматься лишней работой?
1. Можно еще поинтересоваться о том как были получены выпавшие кадры?
Без понятия как получены, запись чужая. Полагаю комп не тянул кодирование напрямую в AVI при захвате с ТВ-тюнера.
2. Нельзя ли найти в интернете этот фильм без выпавших кадров, чтобы не заниматься тут лишней работой?
Другой вариант найти нельзя (абсолютно точно нельзя), но в данном конкретном случае просмотр уже в прошлом:
собственно с этого глючного сериала, чтобы хоть как-то более менее терпимо (плавно) его посмотреть я и стал изучать ависинт, в итоге ничего лучше "TDecimate(cycle=7)" так и не удалось подобрать, и бОльшая часть дублей как раз выбрасывалась (в среднем 3 дропа в секунду было), ну и частично нужные кадры повыбрасывались, где в 7-ке кадров не было дропов.
В теории при "TDecimate(Mode=2,rate=22)" должно было быть медленнее, но лучше (дропы раскиданы хаотично, и ложных срабатываний при анализе сразу всех кадров за каждую секунду должно было быть меньше), и вроде было получше, но при этом был рассинхрон ~500мс (причины которого я так и не понял, и никакой инфы не нашёл ).
На данный момент меня это видео интересует исключительно для тестовых целей (на будущее, т.к. видео с дропами периодически встречается, пусть и не в таком жутком количестве дропов, как в моём семпле).
Bars
Приложенный в архиве исправленный файл выглядит даже хуже, чем исходник. Причина: замена кадров дублей со смещением на кадр раньше. Вообще вижу такое впервые и теряюсь в догадках как такое можно было получить, применяя предложенный скрипт. Разве что, если в скрипт были внесены изменения.
Как должно быть:
исходник : кадр1 - кадр2 - дубль - кадр4 - кадр5
результат: кадр1 - кадр2 - Fix-50 - кадр4 - кадр5
Как это выглядит в файле из архива:
исходник : кадр1 - кадр2 - дубль - кадр4 - кадр5
результат: кадр1 - Fix-50 - кадр2 - кадр4 - кадр5
Из-за этого подергивания еще сильней усугубились, т.к. перед скачком (кадр2-кадр4) идет затормаживание, а на смене сцен вообще красотища: перемигивание кадров из предыдущей и следующей сцены.
Прогнал через оригинальный скрипт - все в порядке. Как удалось умудрится этим скриптом сделать видео еще хуже - я не представляю.
Причина: замена кадров дублей со смещением на кадр раньше.
Как должно быть:
исходник : кадр1 - кадр2 - дубль - кадр4 - кадр5
результат: кадр1 - кадр2 - Fix-50 - кадр4 - кадр5Как это выглядит в файле из архива:
исходник : кадр1 - кадр2 - дубль - кадр4 - кадр5
результат: кадр1 - Fix-50 - кадр2 - кадр4 - кадр5
Вот именно про это я и писал в первом комментарии, во втором пункте
Прогнал через оригинальный скрипт - все в порядке.
Тоже FlipVertical() использовали, чтобы не было перевернутого изображения из-за DSS2?
Вообще вижу такое впервые и теряюсь в догадках как такое можно было получить, применяя предложенный скрипт. Как удалось умудрится этим скриптом сделать видео еще хуже - я не представляю.
Я сейчас ещё потестировал, и оказалось что моё изначальное предположение было верным, всё дело в том, через что открывать, через DSS2 (со всеми отключенными фильтрами в запускаемом ffdshow) тоже всё нормально (так что деблокинг или повышение резкости совершенно непричём), а через AVISource будет то, что я приложил в архиве. Почему-то при открытие через AVISource скрипт работает неправильно.
Просто сколько я читал, avi обычно рекомендуют открывать именно через AVISource, поэтому и я так делал.
Bars
DSS2 открывает на каждом компьютере используя DS-декодеры, установленные в системе, выбирая согласно приоритетам (merit-ам). Это может оказаться ffdShow, LAV или любой другой декодер. Поэтому перевернутая картинка - это индивидуально на одной конкретной системе так вышло. Переставить LAV или ffdShow с повышением приоритетов и это исправится. У меня DSS2 кадры открывает нормально, не перевернутыми.
AVISource не пробовал. Возможно в нем проблема, но скорее всего в самом AVI, VirtualDub ругается на него, мол отсутствуют первые два кадра. Вот Avisynth'у и снесло башку от нестандартного AVI. В нем еще и кадры-дубли закодированы по-честному (D - флаг пропуска кадра). Это значит, что кодировщик имел доступ к информации, что кадр пропущен, иначе бы закодировался кадр-близнец. А как такие D-кадры обрабатываются Avisynth'ом я не проверял. Возможно, для него D означает заполнить это пропуск кадром из будущего, а не из прошлого. Ну а иначе я просто не могу объяснить такую чехарду с кадрами.
интересует исключительно для тестовых целей
Вот я направление подсказал, если интересует, то можно дальше самостоятельно в этом направлении поизучать и поэкспериментировать. Я же сторонник подхода: не придумывать себе сложности.
И я не имел в виду включенные улучшалки именно в ffdShow. Просто до формата H.264 не сущестовало стандартизованного правила по декодированию и декодерам не ставилось условие попиксельного соответствия декодеру-референсу. Постобработка не являлась стандартом и обязательным условием. Поэтому в общем случае кадры полученные через AVISource, DirectShowSource и DSS2 дадут разные картинки с разной степенью постобработки. И не обязательно Вам об этом сообщат разработчики декодера или выведут настройку наружу.
Перевернутая картинка - это яркий пример нестандартизованного способа распаковки и постобработки кадра.
Но это все лирика и уже далека от темы замены выпавших кадров. Я так понял, что все получилось и все теперь устраивает?
Я рад.
DSS2 открывает на каждом компьютере используя DS-декодеры, установленные в системе, выбирая согласно приоритетам (merit-ам). Это может оказаться ffdShow, LAV или любой другой декодер. Поэтому перевернутая картинка - это индивидуально на одной конкретной системе так вышло.
Да, это я уже знал, когда читал про DSS2, с причиной как раз мне было всё-понятно...а вот про изменение приоритетов фильтров я как-то вообще забыл (давно GSpot'ом не пользовался)
Переставить LAV или ffdShow с повышением приоритетов и это исправится.
Спасибо, изменил, так удобнее (на воспроизведения в плеере не повлияло, там свои приоритеты для фильтров прописаны)
AVISource не пробовал. Возможно в нем проблема, но скорее всего в самом AVI, VirtualDub ругается на него, мол отсутствуют первые два кадра.
Как станно, учитывая что семпл этот я специально вырезал через:
"VirtualDubMod 1.5.10.3 (build 2550/release)"
В нем еще и кадры-дубли закодированы по-честному (D - флаг пропуска кадра).
Спасибо! Теперь я, наконец, понял почему в свойствах рендерера при воспроизведении (без плавности) частота колебалась в райне 22, а не была чётко 25
Я так понял, что все получилось и все теперь устраивает?
В принципе да, ваш скрипт оказался полностью нормально работающим через DSS2 и этого думаю вполне достаточно.
P.S. Но вот вопрос с двумя отсутствующими кадрами всё ещё не дает покоя, сам виртуалдуб вырезает, а потом сам же и ругается на отсутствующие кадры...(хотя может у вас версия дуба другая?)
Bars
вопрос с двумя отсутствующими кадрами всё ещё не дает покоя, сам виртуалдуб вырезает, а потом сам же и ругается на отсутствующие кадры...(хотя может у вас версия дуба другая?)
Проверял на оказавшемся под рукой VDub 1.9.11.1 APNG Mod. Он что-то буркнул мне, что двух первых кадров нет и что сдвинет весь видеоряд на 80ms, мол возможно отставание аудиодорожки. Файл и VDub остались на работе. Если это так важно, то могу скачать еще раз и посмотреть уже на домашнем VDub (тут у меня оригинальный 1.9.10 установлен). Но я верю, что с этим вопросом можно разобраться без меня самостоятельно
Но я верю, что с этим вопросом можно разобраться без меня самостоятельно
Да, конечно.
P.S. Все не очень ясные моменты по теме, вы уже прояснили, спасибо
Подкинул тут Булат95 ссылку на плавный трейлер игрушки BattleField 4.
Трейлеры 720p и 1080p и правда имеют 60 к/сек, но вот только во многих сценах присутствуют выпавшие кадры. Мне это дело не очень понравилось, поэтому решил попытать свои силы в задаче повышения плавности игровым трейлерам.
Заодно развить алгоритм замены выпавших кадров.
Вышел довольно сложный, но мощный скрипт: GameDropFix
SetMemoryMax(1024)
global svp_scheduler=true
global threads=7
global svp_cache_fwd=threads+2
LoadPlugin("C:\Program Files (x86)\SVP 3.1.4\plugins\svpflow1.dll")
LoadPlugin("C:\Program Files (x86)\SVP 3.1.4\plugins\svpflow2.dll")
SetMTMode(3,threads)
DSS2("G:\Downloads\Game_60fps_trailer\BF4_720p60.mp4").ConvertToYV12()
SetMTMode(2)
global super_params_mini="{scale:{up:0},gpu:1}"
global analyse_params_mini="{block:{w:16,h:16}}"
mini=BicubicResize(width/2,height/2)
super_mini=mini.SVSuper(super_params_mini)
vectors_mini=SVAnalyse(super_mini, analyse_params_mini)
vectors_Forward=SVConvert(vectors_mini, false)
HorizontalSpeed_luma=mini.MMask(vectors_Forward, kind=3).convertToRGB32().PointResize(width/32, height/32).PointResize(width/8, height/8).ConvertToYV12().mt_lut(y=2, u=128, v=128)
global super_params="{scale:{up:0},gpu:1}"
global analyse_params="{main:{search:{coarse:{distance:4,bad:{sad:2000}},type:2,distance:4},penalty:{lambda:1,pglobal:10000}},refine:[{thsad:65000}]}"
global smoothfps_params="{gpuid:21,rate:{num:2,den:1},algo:13,scene:{limits:{blocks:50}}}"
global smoothfps_params3366="{gpuid:21,rate:{num:3,den:1},algo:13,scene:{limits:{blocks:50}}}"
super=SVSuper(super_params)
vectors=SVAnalyse(super, analyse_params)
global fix50 = SVSmoothFps(super, vectors, smoothfps_params, mt=threads, url="www.svp-team.com").SelectOdd().Subtitle("fix50", align=3, size=12)
fix3366 = SVSmoothFps(super, vectors, smoothfps_params3366, mt=threads, url="www.svp-team.com")
global fix33 = fix3366.SelectEvery(3,1).Subtitle("fix33", align=3, size=12)
global fix66 = fix3366.SelectEvery(3,2).Subtitle("fix66", align=3, size=12)
global min_move=0.02
global move_idx=10
global debug=0
global spc=" "
global fmt="% 1.2f"
global star="*"
last.ScriptClip("
luma_lft=HorizontalSpeed_luma.crop(0,0,width/32,0)
luma_rgh=HorizontalSpeed_luma.crop(width/32+width/16,0,0,0)
AvgLuma_lft=128-luma_lft.AverageLuma
AvgLuma_rgh=128-luma_rgh.AverageLuma
AvgLuma_lft_prev=128-(luma_lft.trim(1,1)+luma_lft).AverageLuma
AvgLuma_rgh_prev=128-(luma_rgh.trim(1,1)+luma_rgh).AverageLuma
AvgLuma_lft_next=128-luma_lft.trim(1,0).AverageLuma
AvgLuma_rgh_next=128-luma_rgh.trim(1,0).AverageLuma
AvgLuma_lft_next2=128-luma_lft.trim(2,0).AverageLuma
AvgLuma_rgh_next2=128-luma_rgh.trim(2,0).AverageLuma
Max_lft=max(abs(AvgLuma_lft_prev),abs(AvgLuma_lft),abs(AvgLuma_lft_next))
Max_rgh=max(abs(AvgLuma_rgh_prev),abs(AvgLuma_rgh),abs(AvgLuma_rgh_next))
A_prev= (Max_rgh>Max_lft) ? AvgLuma_rgh_prev : AvgLuma_lft_prev
A_cur= (Max_rgh>Max_lft) ? AvgLuma_rgh : AvgLuma_lft
A_next= (Max_rgh>Max_lft) ? AvgLuma_rgh_next : AvgLuma_lft_next
drop_lft= (AvgLuma_lft_prev*AvgLuma_lft_next>0 && abs(AvgLuma_lft*move_idx)<Max_lft && abs(AvgLuma_lft_prev)>min_move && abs(AvgLuma_lft_next)>min_move) ? 1 : 0
drop_rgh= (AvgLuma_rgh_prev*AvgLuma_rgh_next>0 && abs(AvgLuma_rgh*move_idx)<Max_rgh && abs(AvgLuma_rgh_prev)>min_move && abs(AvgLuma_rgh_next)>min_move) ? 1 : 0
drop = drop_lft*drop_rgh
Max_lft2=max(abs(AvgLuma_lft),abs(AvgLuma_lft_next),abs(AvgLuma_lft_next2))
Max_rgh2=max(abs(AvgLuma_rgh),abs(AvgLuma_rgh_next),abs(AvgLuma_rgh_next2))
A_prev2= (Max_rgh2>Max_lft2) ? AvgLuma_rgh : AvgLuma_lft
A_cur2= (Max_rgh2>Max_lft2) ? AvgLuma_rgh_next : AvgLuma_lft_next
A_next2= (Max_rgh2>Max_lft2) ? AvgLuma_rgh_next2 : AvgLuma_lft_next2
drop_lft2= (AvgLuma_lft*AvgLuma_lft_next2>0 && abs(AvgLuma_lft_next*move_idx)<Max_lft2 && abs(AvgLuma_lft)>min_move && abs(AvgLuma_lft_next2)>min_move) ? 1 : 0
drop_rgh2= (AvgLuma_rgh*AvgLuma_rgh_next2>0 && abs(AvgLuma_rgh_next*move_idx)<Max_rgh2 && abs(AvgLuma_rgh)>min_move && abs(AvgLuma_rgh_next2)>min_move) ? 1 : 0
drop2 = drop_lft2*drop_rgh2
drop2==1 \
? abs(A_prev2)/1.3>abs(A_next2) \
? fix50.trim(1,1)+fix50 \
: (abs(A_prev2)/1.3<=abs(A_next2) && abs(A_prev2)>=abs(A_next2)/1.3) \
? fix66.trim(1,1)+fix66 \
: last \
: last
drop==1 \
? abs(A_prev)/1.3<=abs(A_next) \
? fix50 \
: abs(A_prev)<=abs(A_next)/1.3 \
? fix33 \
: last \
: last
debug==1 ? Subtitle(x=10,y=10,string(AvgLuma_lft_prev,fmt)+spc+string(AvgLuma_rgh_prev,fmt)) : last
debug==1 ? Subtitle(x=10,y=30,string(AvgLuma_lft,fmt)+spc+string(AvgLuma_rgh,fmt),text_color=$FF8888) : last
debug==1 ? Subtitle(x=10,y=50,string(AvgLuma_lft_next,fmt)+spc+string(AvgLuma_rgh_next,fmt)) : last
debug==1 ? Subtitle(x=10,y=70,string(AvgLuma_lft_next2,fmt)+spc+string(AvgLuma_rgh_next2,fmt)) : last
debug==1 ? Max_rgh>Max_lft ? Subtitle(x=70,y=90,star) : Subtitle(x=20,y=90,star) : last
debug==1 ? Subtitle(x=10,y=110,string(drop_lft)+spc+string(drop_rgh)+spc+string(drop)) : last
(debug==1 && drop==1 && abs(A_prev)/1.3>abs(A_next)) ? Subtitle(x=10,y=130, star+star+star+star+star+star) : last
")
Distributor()
Это пока предварительный вариант в стадии работающего прототипа. Настройки максимальной подвижности при интерполировании взяты такие же, как для повышения плавности видео с видеорегистратора. Т.к. характер движений в таком видео очень схож.
Скрипт умеет заменять одиночные выпавшие кадры, но с дополнительным анализом величины движений в соседних кадрах, что позволяет выявить три разных вида одиночных дропов с индивидуальным исправлением этих дропов в каждом из трех случаев.
Случай 1. Классический. Дроп, затем скачок.
Перед выпавшим кадром движение обычной амплитуды, на самом выпавшем кадре движений нет, на следующем за ним кадре - движение в два раза больше из-за пропуска фазы движения. Такой дроп лечится классической заменой кадра-дропа интерполированным кадром, взятого посередине длинного движения. На картинке обозначен: fix50.
Случай 2. Обратный. Скачок, затем дроп.
Перед выпавшим кадром по какой-то причине игровой движок показывает кадр из будущего. Выглядит как скачок. А за ним следует дроп. Видимо движок игры неровно тратит время на отрисовку кадров и если предыдущий кадр ему дался легко, то со следующим он провозился так долго, что не успел подготовить кадр до следующего синхроимпульса монитора, пришлось повторить имеющийся, т.е. вывести дроп. Такой дроп лечится хитро. Вторая копия кадра оставляется нетронутой, а первая заменяется на fix50.
Случай 3. Пропуск кадра из-за низкой частоты рендера кадров игровым движком.
И перед выпавшим кадром и после него нет скачков. Кадра просто не считалось игрой изначально. Если заменить такой дроп на один интерполированный по середине с соседом кадр, то получим два кадра с уполовиненным по скорости движением. Я пока решил интерполировать оба кадра, которые ограничивают кадровый интервал. Первый кадр интерполирую с левым, получая положение 66%: fix66, второй кадр - с правым до положения 33%: fix33.
Таким образом получаю вместо дропа серию из трех замедленных на 33% но равномерно двигающихся кадров. Выглядит уже лучше, чем дерганный исходник.
Все желающие могут скачать и посмотреть результат:
BF4_720p60_DropsFixed.mkv (1,21 ГБ)
Исправил несколько ошибок в предыдущем скрипте, переназвал вставляемые кадры по-правильному: как они соотносятся во времени к заменяемому:
fix50 - взять кадр между текущим и следующим по середине (+50%);
-fix50 - взять кадр между текущим и предыдущим по середине (-50%);
-fix33 & fix33 - всегда идут парой друг за другом с той же логикой: (-33% и 33%);
Картинки-диаграммы движения с выпавшим кадром, которые умеет восстанавливать скрипт:
Скрипт GameDropFix_v2
SetMemoryMax(1024)
global svp_scheduler=true
global threads=3
global svp_cache_fwd=threads+2
LoadPlugin("C:\Program Files (x86)\SVP 3.1.4\plugins\svpflow1.dll")
LoadPlugin("C:\Program Files (x86)\SVP 3.1.4\plugins\svpflow2.dll")
SetMTMode(3,threads)
DSS2("G:\Downloads\Game_60fps_trailer\BF4_720p60.mp4").ConvertToYV12()
SetMTMode(2)
global super_params_mini="{scale:{up:0},gpu:1}"
global analyse_params_mini="{block:{w:16,h:16}}"
mini=BicubicResize(width/2,height/2)
super_mini=mini.SVSuper(super_params_mini)
vectors_mini=SVAnalyse(super_mini, analyse_params_mini)
vectors_Forward=SVConvert(vectors_mini, false)
HorizontalSpeed_luma=mini.MMask(vectors_Forward, kind=3).convertToRGB32().PointResize(width/32, height/32).PointResize(width/8, height/8).ConvertToYV12().mt_lut(y=2, u=128, v=128)
global super_params="{scale:{up:0},gpu:1}"
global analyse_params="{main:{search:{coarse:{distance:4,bad:{sad:2000}},type:2,distance:4},penalty:{lambda:1,pglobal:10000}},refine:[{thsad:65000}]}"
global smoothfps_params_2_1="{gpuid:21,rate:{num:2,den:1},algo:13,scene:{limits:{blocks:50}}}"
global smoothfps_params_3_1="{gpuid:21,rate:{num:3,den:1},algo:13,scene:{limits:{blocks:50}}}"
super=SVSuper(super_params)
vectors=SVAnalyse(super, analyse_params)
global fix50 = SVSmoothFps(super, vectors, smoothfps_params_2_1, mt=threads, url="www.svp-team.com").SelectOdd()
fix_3_1 = SVSmoothFps(super, vectors, smoothfps_params_3_1, mt=threads, url="www.svp-team.com")
global fix33 = fix_3_1.SelectEvery(3,1).Subtitle("fix33", align=3, size=12)
global fix66 = fix_3_1.SelectEvery(3,2).Subtitle("-fix33", align=3, size=12)
global min_move=0.02
global move_idx=10
global debug=0
global spc=" "
global fmt="% 1.2f"
global star="*"
global fix50t="fix50"
global fix50nt="-fix50"
last.ScriptClip("
luma_lft=HorizontalSpeed_luma.crop(0,0,width/32,0)
luma_rgh=HorizontalSpeed_luma.crop(width/32+width/16,0,0,0)
AvgLuma_lft=128-luma_lft.AverageLuma
AvgLuma_rgh=128-luma_rgh.AverageLuma
AvgLuma_lft_prev=128-(luma_lft.trim(1,1)+luma_lft).AverageLuma
AvgLuma_rgh_prev=128-(luma_rgh.trim(1,1)+luma_rgh).AverageLuma
AvgLuma_lft_next=128-luma_lft.trim(1,0).AverageLuma
AvgLuma_rgh_next=128-luma_rgh.trim(1,0).AverageLuma
AvgLuma_lft_next2=128-luma_lft.trim(2,0).AverageLuma
AvgLuma_rgh_next2=128-luma_rgh.trim(2,0).AverageLuma
Max_lft=max(abs(AvgLuma_lft_prev),abs(AvgLuma_lft),abs(AvgLuma_lft_next))
Max_rgh=max(abs(AvgLuma_rgh_prev),abs(AvgLuma_rgh),abs(AvgLuma_rgh_next))
A_prev= (Max_rgh>Max_lft) ? AvgLuma_rgh_prev : AvgLuma_lft_prev
A_cur= (Max_rgh>Max_lft) ? AvgLuma_rgh : AvgLuma_lft
A_next= (Max_rgh>Max_lft) ? AvgLuma_rgh_next : AvgLuma_lft_next
drop_lft= (AvgLuma_lft_prev*AvgLuma_lft_next>0 && abs(AvgLuma_lft*move_idx)<Max_lft && abs(AvgLuma_lft_prev)>min_move && abs(AvgLuma_lft_next)>min_move && abs(AvgLuma_lft)<=min_move) ? 1 : 0
drop_rgh= (AvgLuma_rgh_prev*AvgLuma_rgh_next>0 && abs(AvgLuma_rgh*move_idx)<Max_rgh && abs(AvgLuma_rgh_prev)>min_move && abs(AvgLuma_rgh_next)>min_move && abs(AvgLuma_rgh)<=min_move) ? 1 : 0
drop = drop_lft*drop_rgh
drop = (drop==0 && A_cur==0 && abs(A_prev)>min_move && abs(A_next)>min_move) ? 1 : drop
Max_lft2=max(abs(AvgLuma_lft),abs(AvgLuma_lft_next),abs(AvgLuma_lft_next2))
Max_rgh2=max(abs(AvgLuma_rgh),abs(AvgLuma_rgh_next),abs(AvgLuma_rgh_next2))
A_prev2= (Max_rgh2>Max_lft2) ? AvgLuma_rgh : AvgLuma_lft
A_cur2= (Max_rgh2>Max_lft2) ? AvgLuma_rgh_next : AvgLuma_lft_next
A_next2= (Max_rgh2>Max_lft2) ? AvgLuma_rgh_next2 : AvgLuma_lft_next2
drop_lft2= (AvgLuma_lft*AvgLuma_lft_next2>0 && abs(AvgLuma_lft_next*move_idx)<Max_lft2 && abs(AvgLuma_lft)>min_move && abs(AvgLuma_lft_next2)>min_move && abs(AvgLuma_lft_next)<=min_move) ? 1 : 0
drop_rgh2= (AvgLuma_rgh*AvgLuma_rgh_next2>0 && abs(AvgLuma_rgh_next*move_idx)<Max_rgh2 && abs(AvgLuma_rgh)>min_move && abs(AvgLuma_rgh_next2)>min_move && abs(AvgLuma_rgh_next)<=min_move) ? 1 : 0
drop2 = drop_lft2*drop_rgh2
drop2 = (drop2==0 && A_cur2==0 && abs(A_prev2)>min_move && abs(A_next2)>min_move) ? 1 : drop2
drop2==1 \
? abs(A_prev2)/1.3>abs(A_next2) \
? (fix50.trim(1,1)+fix50).Subtitle(fix50nt, align=3, size=12) \
: (abs(A_prev2)/1.3<=abs(A_next2) && abs(A_prev2)>=abs(A_next2)/1.3) \
? fix66.trim(1,1)+fix66 \
: last \
: last
drop==1 \
? abs(A_prev)<abs(A_next)/1.3 \
? fix50.Subtitle(fix50t, align=3, size=12) \
: abs(A_prev)/1.3<=abs(A_next) \
? fix33 \
: last \
: last
debug==1 ? Subtitle(x=10,y=10,string(AvgLuma_lft_prev,fmt)+spc+string(AvgLuma_rgh_prev,fmt)) : last
debug==1 ? Subtitle(x=10,y=30,string(AvgLuma_lft,fmt)+spc+string(AvgLuma_rgh,fmt),text_color=$FF8888) : last
debug==1 ? Subtitle(x=10,y=50,string(AvgLuma_lft_next,fmt)+spc+string(AvgLuma_rgh_next,fmt)) : last
debug==1 ? Subtitle(x=10,y=70,string(AvgLuma_lft_next2,fmt)+spc+string(AvgLuma_rgh_next2,fmt)) : last
debug==1 ? Max_rgh>Max_lft ? Subtitle(x=70,y=90,star) : Subtitle(x=20,y=90,star) : last
debug==1 ? Subtitle(x=10,y=110,string(drop_lft)+spc+string(drop_rgh)+spc+string(drop)) : last
(debug==1 && drop==1 && abs(A_prev)/1.3>abs(A_next)) ? Subtitle(x=10,y=130, star+star+star+star+star+star) : last
")
trim(0,framecount-10)
Distributor()
Результат работы скрипта стал лучше:
BF4_720p60_DropsFixed_v2.mkv (1,22 ГБ)
Добавлю объективности к выше сказанному.
Написал небольшой скрипт определения количества дублей в файле. Посчитал для имеющихся трех файлов.
Итак, Цифры, характеризующие качество работы вышеприведенных скриптов:
В исходном файле BF4_720p60.mp4 1142 одиночных выпавших кадра и 56 двойных.
В файле BF4_720p60_DropsFixed.mkv 318 одиночных выпавших кадра и 84 двойных.
В файле BF4_720p60_DropsFixed_v2.mkv 189 одиночных выпавших кадра и 96 двойных.
Видно, что число одиночных выпавших кадров во второй версии сокращено еще почти вдвое. Причину, по которой растет число двойных выпавших кадров я пока не знаю, но найду. А вот что самое главное, раз я теперь умею считать эти кадры, то смогу и заменить их, не пропустив ни одного.
Отличная работа, результат на лицо!
Окончательный вариант ролика с замененными выпавшими кадрами: BF4_720p60_DropsFixed_v3.mkv (1,25 ГБ)
Отличается от двух предыдущих:
- возвращена ошибочно выставленная частота кадров с 60 fps до 59.94 fps. Это исключило появление 62 выпавших кадров на ровном месте
- добавлена замена парных выпавших кадров;
- добавлена замена тройных выпавших кадров;
- изменены настройки интерполяции для уменьшения волновых артефактов на интерполированных кадрах, применено смешивание кадров на сменах сцен.
Вот карта расположения выпавших кадров во всех четырех роликах с цифрами.
Самые заметные выпавшие кадры - это одиночно-расположенные, особенно, если находятся в местах с динамичным движением.
Самые безобидные - чередующиеся через один. Наблюдаются на вставках с низкой частотой кадров (30 к/сек) из других роликов.
Двойные и тройные дропы заметнее одинарных, особенно если они отдельно-расположенные, как в этом ролике.
Итого за три итерации количество отдельно стоящих выпавших кадров уменьшено с 1160 до 170. По остальным типам выпавших кадров тоже получен значительный прогресс.
Разработанный скрипт избавляет видео в первую очередь от приостановок в глобальных движениях: панорамирование, зум. Локальные движения остаются без изменений.
Теперь, при просмотре ролика на фоне плавных движений камеры уже явно бросаются в глаза недоработки игрового движка:
- низкая частота кадров, примененная в анимации персонажей (особенно неприятно смотрится перемещение персонажей и смена поз попеременно через кадр);
- низкая точность анимации персонажей, что делает их движения кукольными особенно вблизи;
- низкая точность анимации объектов, скачкообразные движения вертолета;
- двойные крылья у птиц
Вот такие у меня замечания. Но несмотря на вышесказанное, приятного просмотра!
А сам скрипт(3ю версию) где можно скачать ?
dlr5668
Да, точно подмечено. Скрипт я еще не выкладывал. Здесь основную ценность представляет не видео, а скрипт, которым можно обработать тысячи подобных видео
Подчистил лишние строки, убрал отладочные конструкции. В таком виде уже можно использовать. Оформление скрипта все еще рабочее, для выставки не годится.
Скрипт GameDropFix_v3
SetMemoryMax(1024)
global svp_scheduler=true
global threads=5
global svp_cache_fwd=threads+10
LoadPlugin("C:\Program Files (x86)\SVP 3.1.4\plugins\svpflow1.dll")
LoadPlugin("C:\Program Files (x86)\SVP 3.1.4\plugins\svpflow2.dll")
SetMTMode(3,threads)
DSS2("BF4_720p60.mp4",fps=59.94).ConvertToYV12()
SetMTMode(2)
super_params_mini="{scale:{up:0},gpu:1}"
analyse_params_mini="{block:{w:8,h:8}}"
mini=BicubicResize(width/2,height/2).TemporalSoften(1, 1, 0, scenechange=1, mode=2)
super_mini=mini.SVSuper(super_params_mini)
vectors_mini=SVAnalyse(super_mini, analyse_params_mini)
vectors_Forward=SVConvert(vectors_mini, false)
HorizontalSpeed_luma=mini.MMask(vectors_Forward, kind=3).convertToRGB32().PointResize(width/32, height/32).PointResize(width/8, height/8).ConvertToYV12().mt_lut(y=2, u=128, v=128)
VerticalSpeed_luma=mini.MMask(vectors_Forward, kind=4).convertToRGB32().PointResize(width/32, height/32).PointResize(width/8, height/8).ConvertToYV12().mt_lut(y=2, u=128, v=128)
size=16
luma_lft=HorizontalSpeed_luma.crop(0,0,int(width/64)*2,0).BicubicResize(size,size)
luma_rgh=HorizontalSpeed_luma.crop(int(width/64)*2+int(width/32)*2,0,0,0).BicubicResize(size,size)
luma_top=VerticalSpeed_luma.crop(0,0,0,int(height/64)*2).BicubicResize(size,size)
luma_btm=VerticalSpeed_luma.crop(0,int(height/64)*2+int(height/32)*2,0,0).BicubicResize(size,size)
luma_drop=luma_lft.mt_lut(y=-1, u=128, v=128)
move_idx=5
y_idx=3
min_move=0.2
max_stop=0.5
drop_clip=luma_drop.ScriptClip("
AvgLuma_lft=128-luma_lft.AverageLuma
AvgLuma_rgh=128-luma_rgh.AverageLuma
AvgLuma_lft_prev=128-(luma_lft.trim(1,1)+luma_lft).AverageLuma
AvgLuma_rgh_prev=128-(luma_rgh.trim(1,1)+luma_rgh).AverageLuma
AvgLuma_lft_next=128-luma_lft.trim(1,0).AverageLuma
AvgLuma_rgh_next=128-luma_rgh.trim(1,0).AverageLuma
AvgLuma_top=128-luma_top.AverageLuma
AvgLuma_btm=128-luma_btm.AverageLuma
AvgLuma_top_prev=128-(luma_top.trim(1,1)+luma_top).AverageLuma
AvgLuma_btm_prev=128-(luma_btm.trim(1,1)+luma_btm).AverageLuma
AvgLuma_top_next=128-luma_top.trim(1,0).AverageLuma
AvgLuma_btm_next=128-luma_btm.trim(1,0).AverageLuma
Max_lft=max(abs(AvgLuma_lft_prev),abs(AvgLuma_lft),abs(AvgLuma_lft_next))
Max_rgh=max(abs(AvgLuma_rgh_prev),abs(AvgLuma_rgh),abs(AvgLuma_rgh_next))
Max_top=max(abs(AvgLuma_top_prev),abs(AvgLuma_top),abs(AvgLuma_top_next))
Max_btm=max(abs(AvgLuma_btm_prev),abs(AvgLuma_btm),abs(AvgLuma_btm_next))
Max_all=max(Max_lft,Max_rgh,Max_top,Max_btm)
MaxLuma=max(abs(AvgLuma_lft),abs(AvgLuma_rgh),abs(AvgLuma_top),abs(AvgLuma_btm))
MaxLuma_prev=max(abs(AvgLuma_lft_prev),abs(AvgLuma_rgh_prev),abs(AvgLuma_top_prev),abs(AvgLuma_btm_prev))
MaxLuma_next=max(abs(AvgLuma_lft_next),abs(AvgLuma_rgh_next),abs(AvgLuma_top_next),abs(AvgLuma_btm_next))
dif=mini.YDifferenceFromPrevious
dif_next=mini.trim(1,0).YDifferenceFromPrevious
dif_prev=(mini.trim(1,1)+mini).YDifferenceFromPrevious
GoodContrast = (max(mini.YPlaneMinMaxDifference,mini.trim(1,0).YPlaneMinMaxDifference)>20) ? 1 : 0
drop = (MaxLuma<0.1 && MaxLuma*2<Max(MaxLuma_prev,MaxLuma_next) && dif*y_idx<max(dif_prev,dif_next)) ? 1 : 0
drop_lft = (AvgLuma_lft_prev*AvgLuma_lft_next>0 && abs(AvgLuma_lft*move_idx)<Max_lft && abs(AvgLuma_lft)<=min_move && dif*y_idx<max(dif_prev,dif_next)) ? 2 : 0
drop_rgh = (AvgLuma_rgh_prev*AvgLuma_rgh_next>0 && abs(AvgLuma_rgh*move_idx)<Max_rgh && abs(AvgLuma_rgh)<=min_move && dif*y_idx<max(dif_prev,dif_next)) ? 3 : 0
drop_top = (AvgLuma_top_prev*AvgLuma_top_next>0 && abs(AvgLuma_top*move_idx)<Max_top && abs(AvgLuma_top)<=min_move && dif*y_idx<max(dif_prev,dif_next)) ? 4 : 0
drop_btm = (AvgLuma_btm_prev*AvgLuma_btm_next>0 && abs(AvgLuma_btm*move_idx)<Max_btm && abs(AvgLuma_btm)<=min_move && dif*y_idx<max(dif_prev,dif_next)) ? 5 : 0
drop = (drop==0 && MaxLuma<Max_stop && Max_lft==Max_all) ? drop_lft : drop
drop = (drop==0 && MaxLuma<Max_stop && Max_rgh==Max_all) ? drop_rgh : drop
drop = (drop==0 && MaxLuma<Max_stop && Max_top==Max_all) ? drop_top : drop
drop = (drop==0 && MaxLuma<Max_stop && Max_btm==Max_all) ? drop_btm : drop
drop_dif = (dif<0.4 && MaxLuma<min_move) ? 6 : 0
drop = (drop==0 && drop_dif>0) ? drop_dif : drop
drop = (drop>0 && Max_all<0.2) ? 0 : drop
drop = (drop>0 && GoodContrast==0) ? 0 : drop
luma=mini.AverageLuma
luma_next=mini.trim(1,0).AverageLuma
max_luma=max(luma,luma_next)
drop = (drop>0 && max_luma<16.5) ? 0 : drop
(drop>0) ? luma_drop : \
(Max_lft==Max_all) ? luma_lft : \
(Max_rgh==Max_all) ? luma_rgh : \
(Max_top==Max_all) ? luma_top : luma_btm
")
fix_r50=luma_lft.mt_lut(y=-1, u=128, v=128)
fix_lr33=luma_lft.mt_lut(y=-2, u=128, v=128)
fix_l50=luma_lft.mt_lut(y=-3, u=128, v=128)
fix_r133=luma_lft.mt_lut(y=-4, u=128, v=128)
fix_r66=luma_lft.mt_lut(y=-5, u=128, v=128)
AvgDrop=127
MaxMulty=10
dblMulti=1.3
fix_clip=luma_drop.ScriptClip("
drop=drop_clip.AverageLuma
AvgLuma=abs(128-drop_clip.AverageLuma)
AvgLuma_prev=abs(128-(drop_clip.trim(1,1)+drop_clip).AverageLuma)
AvgLuma_prev_= (AvgLuma_prev==AvgDrop) ? 0 : AvgLuma_prev
AvgLuma_prev2=abs(128-(drop_clip.trim(1,2)+drop_clip).AverageLuma)
AvgLuma_next=abs(128-drop_clip.trim(1,0).AverageLuma)
AvgLuma_next_= (AvgLuma_next==AvgDrop) ? 0 : AvgLuma_next
AvgLuma_next2=abs(128-drop_clip.trim(2,0).AverageLuma)
#AvgLuma_next3=abs(128-drop_clip.trim(3,0).AverageLuma)
RightZero = (AvgLuma_prev_*MaxMulty<AvgLuma_next_) ? (AvgLuma_prev_>max_stop || AvgLuma_next_>max_stop) ? 1 : 0 : 0
LeftZero = (AvgLuma_next_*MaxMulty<AvgLuma_prev_) ? (AvgLuma_prev_>max_stop || AvgLuma_next_>max_stop) ? 1 : 0 : 0
drop = (AvgLuma==AvgDrop && AvgLuma_next==AvgDrop) ? -50 : 0
drop = (AvgLuma==AvgDrop && AvgLuma_prev==AvgDrop) ? 50 : drop
drop = (drop==0 && AvgLuma==AvgDrop && LeftZero==0 && RightZero==0) ? \
AvgLuma_prev_>AvgLuma_next_*dblMulti ? -50 : \
AvgLuma_prev_*dblMulti>=AvgLuma_next_ ? AvgLuma_next2==AvgDrop ? 50 : 33 : 50 : drop
drop = (drop==0 && AvgLuma==AvgDrop && RightZero==0 && AvgLuma_next2==AvgDrop) ? -50 : drop
drop = (drop==0 && AvgLuma==AvgDrop && LeftZero==0 && AvgLuma_prev2==AvgDrop) ? 66 : drop
(drop==50) ? fix_r50 : \
(drop==33) ? fix_lr33 : \
(drop==-50) ? fix_l50 : \
(drop==133) ? fix_r133 : \
(drop==66) ? fix_r66 : drop_clip
")
r50=1
lr33=2
l50=3
r133=4
r66=5
super_params="{scale:{up:0},gpu:1}"
analyse_params="{main:{search:{coarse:{distance:4,bad:{sad:2000}},type:2,distance:4},penalty:{lambda:1,pglobal:10000}},refine:[{thsad:65000}]}"
smoothfps_params="{rate:{num:12,den:1},algo:13,scene:{blend:true}}"
super=SVSuper(super_params)
vectors=SVAnalyse(super, analyse_params)
fix_all = SVSmoothFps(super, vectors, smoothfps_params, mt=threads, url="www.svp-team.com")
fix50 = fix_all.SelectEvery(12,6).Subtitle("fix50", align=3, size=12)
fix33 = fix_all.SelectEvery(12,4).Subtitle("fix33", align=3, size=12)
fix66 = fix_all.SelectEvery(12,8).Subtitle("-fix33", align=3, size=12)
fix66p = fix_all.SelectEvery(12,8).Subtitle("fix66", align=3, size=12)
fix75 = fix_all.SelectEvery(12,9).Subtitle("-fix25", align=3, size=12)
fix50n = fix_all.SelectEvery(12,6).Subtitle("-fix50", align=3, size=12)
fix133 = fix_all.SelectEvery(12,4).Subtitle("fix133", align=3, size=12)
fix125 = fix_all.SelectEvery(12,3).Subtitle("fix125", align=3, size=12)
ScriptClip("
AvgFix=fix_clip.AverageLuma
AvgFix_next=fix_clip.trim(1,0).AverageLuma
AvgFix_next2=fix_clip.trim(2,0).AverageLuma
AvgFix_next3=fix_clip.trim(3,0).AverageLuma
AvgFix_prev=(fix_clip.trim(1,1)+fix_clip).AverageLuma
(AvgFix==r50) \
? (AvgFix_next2==lr33 || AvgFix_next2==l50) ? fix33 : fix50 : \
(AvgFix==lr33) ? fix33 : \
(AvgFix_next==lr33) \
? (AvgFix_prev==r66) ? fix75.trim(1,1)+fix75 : fix66.trim(1,1)+fix66 : \
(AvgFix_next==l50) \
? (AvgFix_prev==lr33 || AvgFix_prev==r50) ? fix66.trim(1,1)+fix66 \
: (AvgFix_prev==r66) ? fix75.trim(1,1)+fix75 : fix50n.trim(1,1)+fix50n : \
(AvgFix==r66) \
? (AvgFix_next2==lr33 || AvgFix_next2==l50) ? fix50 : fix66p : \
(AvgFix_next==r66) \
? (AvgFix_next3==lr33 || AvgFix_next3==l50) ? fix125.trim(1,0) : fix133.trim(1,0) : \
last
")
trim(0,framecount-10)
Distributor()
Немного об алгоритме:
- в кадре выделяются четыре зоны, в которых оценивается движение: слева/справа, сверху/снизу;
- все кадры, на которых наблюдается резкая приостановка движений (max_stop, пкс) признаются кандидатами к замене и помещаются в клип drop_clip;
- далее идет выделение из этих кандидатов одиночных, двойных и тройных выпавших кадров, на выходе получается клип кадров к замене fix_clip с пятью вариантами замены кадров;
- далее производится обработка конфликтных ситуаций, чтобы не происходило образование новых кадров дублей после замены и выполняется непосредственно замена кадра выбором одного из 8-ми вариантов;
Алгоритм однопроходной, но из-за сложной конвейерной структуры и необходимости буферизации промежуточных результатов в таком виде не пригоден для работы на лету, подходит только для последовательной обработки с предварительным сохранением результата для последующего просмотра.
Очень круто! Сохранил, буду использовать. Спасибо.
MAG79
Очень интересная тема. Попробовал скрипт на видео, снятом на слабой видеокарте, и там дропы через каждый кадр, после уплавнения стало плавнее , но все равно множество двоящихся объектов (например, снег). Но в качестве скорой помощи, очень полезная вещь. Хотя идея предотвращать дропы мне нравится больше). А с помощью чего Вы делали статистику дропов в видео?
Vivian
с помощью чего Вы делали статистику дропов в видео?
С помощью скрипта выводил статистику в текстовый файл и анализировал в MS Excel.
MAG79
Скрипт GameDropFix_v3
Данный скрипт заточен именно под игровое видео? (в плане чувствительности определения движения и т.д. и т.п.)
Если цель дубли в фильмах/сериалах, то есть смысл переходить с "второй версии DoubleDropFix.avs" (из этого поста, которой я пользуюсь с февраля и её качество меня в принципе устраивает) на GameDropFix_v3?
Bars
Скрипт затачивался на один конкретный ролик батлфилда-4 и отлаживался на нем. Для фильмов можно попробовать применить, но фильмы имеют другой характер пропущенных кадров. Половина логики скрипта GameDropFix_v3 заточена именно под особенности пропущенных кадров при записи игр.
Для видео есть специализированные библиотеки и скрипты для удаления циклических кадров-дублей. Например, TIVTC.
Для видео есть специализированные библиотеки и скрипты для удаления циклических кадров-дублей. Например, TIVTC.
Я в курсе про TIVTC и пользуюсь им по назначению именно для циклических дублей.
Но DropFix из текущей темы мне пригождается именно для удаления хаотично расположенных дублей (или как в том варианте, что мы обсуждали в начале этой темы) или в качестве дополнения, после отработки TDecimate, т.к. попадаются фильмы где при смене сцен последовательность меняется, и как итог после смены сцены остаётся дубль
(что-то подобное описано тут).
Если я правильно понял, то мне стоит продолжить пользоваться DoubleDropFix.avs, а переходить на GameDropFix_v3 нет никакого смысла?
Bars
мне стоит продолжить пользоваться DoubleDropFix.avs, а переходить на GameDropFix_v3 нет никакого смысла?
Для фильмов лучше подойдет DoubleDropFix.
MAG79
Здравствуйте.
Есть вопрос по DoubleDropFix, а скорее проблема
Небольшой тестовый семпл (исходник + после обработки DoubleDropFix+на особо интересные проблемные места скрины с точным временем на них): http://sendfile.su/884431
Там вот никак не могу понять почему так сильно сбоит дропфикс, например, 1-ый пример (на скринах приложенных к архиву выше) это:
исходник : кадр1 - кадр2 - дубль - кадр4 - кадр5 (на нём смена сцены)
результат: кадр1 - кадр2 - Fix33* - кадр4 - кадр5
*Причем этот Fix33 построенный явно между кадрами 4 и 5, и как следствие получается заглядывание в будущее и перемигивание
2-ой пример:
исходник : кадр1 - кадр2 - кадр3 - дубль - дубль - кадр6 (на нем смена сцены)
результат: кадр1 - кадр2 - кадр3 - Fix33* - дубль - кадр6
*Тут Fix33 построен между кадрами 3 и 6, т.е. правильно, если бы ещё вместо второго дубля был Fix66 - было бы отлично, а так опять имеем перемигивание
Ну и третий пример на скринах, просто единичный замененный кадр, но почему-то с индикацией Fix66, т.е. и тут что-то пошло не так.
P.S. Перепробовал различные декодеры (LAV, ffdshow) с различными вариантами открытия в avs-скрипте: DSS2, ffvideosource, AVISource - безрезультатно
Bars
Спасибо за наблюдения!
Архив скачал, поглядел. Была проблема в логике скрипта.
Скрипт по-разному искал кадры-дубли для текущего и соседних с ним кадров, отсюда появлялись половинки двойных замен кадров-дублей: Fix33 без следующего за ним Fix66, либо Fix66 без предшествующего Fix33.
Модифицировал скрипт DoubleDropFix второй версии. Организовал конвейер по опыту скрипта GameDropFix_v3: добавил промежуточный клип кадров к замене drop_clip.
Для работы скрипта теперь требуется еще и плагин MaskTools2.
Третья версия DoubleDropFix_v3.avs:
DSS2("E:\Downloads\Bars\2013.10.21\test.avi").ConvertToYV12()
sc=MSuper(pel=1)
vf=MAnalyse(sc,isb=false)
vb=MAnalyse(sc,isb=true)
global frame_50 = MFlowInter(sc,vb,vf,time=50).SubTitle("Fix-50", size=12, align=3)
global frame_33 = MFlowInter(sc,vb,vf,time=33).SubTitle("Fix-33", size=12, align=3).trim(1,0)
global frame_66 = MFlowInter(sc,vb,vf,time=66).SubTitle("Fix-66", size=12, align=3)
global frame_src = last
global mini=sc.crop(8,height+8*3,width/2,height/2).TemporalSoften(1, 1, 0, scenechange=1, mode=2)
global luma_drop=mini.mt_lut(y=-1, u=128, v=128)
drop_clip=mini.scriptclip("dif=mini.ydifferencefromprevious()
\ dif_next1=mini.trim(1,0).ydifferencefromprevious()
\ dif_prev1=(mini.trim(1,1)+mini).ydifferencefromprevious()
\ dif_nextMax=max(max(dif,dif_next1)/8,0.01)
\ dif_prevMax=max(max(dif,dif_prev1)/8,0.01)
\ dif>min(dif_prevMax,dif_nextMax) ? mini : luma_drop
")
scriptclip("
\ Fix_prev2=(drop_clip.trim(1,2)+drop_clip).AverageLuma
\ Fix_prev1=(drop_clip.trim(1,1)+drop_clip).AverageLuma
\ Fix=drop_clip.AverageLuma
\ Fix_next1=drop_clip.trim(1,0).AverageLuma
\ Fix_next2=drop_clip.trim(2,0).AverageLuma
\ Fix!=1
\ ? frame_src
\ : Fix_next1!=1
\ ? Fix_prev1!=1
\ ? frame_50
\ : Fix_prev2!=1
\ ? frame_66
\ : frame_src
\ : Fix_next2!=1
\ ? Fix_prev1!=1
\ ? frame_33
\ : frame_src
\ : frame_src")
---
Кстати, поглядел на характер выпавших кадров именно этого видеоролика. Тут, как ни странно встречаются разные пропуски в том числе и раннее появление кадра с последующим повтором, что обычно не характерно для выпавших кадров в фильмах. В этом случае будет уместным анализ движения в местах выпавших кадров, поэтому для такого видео вполне можно применить скрипт GameDropFix_v3. Результат будет плавнее, чем после DoubleDropFix_v3.
MAG79
Была проблема в логике скрипта.
Скрипт по-разному искал кадры-дубли для текущего и соседних с ним кадров, отсюда появлялись половинки двойных замен кадров-дублей: Fix33 без следующего за ним Fix66, либо Fix66 без предшествующего Fix33.
Спасибо за пояснение.
Модифицировал скрипт DoubleDropFix второй версии. Организовал конвейер по опыту скрипта GameDropFix_v3: добавил промежуточный клип кадров к замене drop_clip.
Для работы скрипта теперь требуется еще и плагин MaskTools2.
Третья версия DoubleDropFix_v3.avs
Огромное спасибо за доработку скрипта! Завтра займусь тестированием и заодно сравню с результатом работы GameDropFix_v3.
разные пропуски в том числе и раннее появление кадра с последующим повтором
А что имелось ввиду под "ранним появлением"? 2-ой случай (скачок, потом дроп) описанный в этом посте или что-то другое?
В этом случае будет уместным анализ движения в местах выпавших кадров, поэтому для такого видео вполне можно применить скрипт GameDropFix_v3. Результат будет плавнее, чем после DoubleDropFix_v3.
А за счет чего в данном случае будет плавнее с GameDropFix_v3?
Если я правильно понял, то DoubleDropFix_v3 умеет фиксить только обычные дропы (fix50), если говорить об одиночных, а GameDropFix_v3 за счет анализа движения умеет определять и делать выбор между фиксом обычного дропа (fix50) и обратного дропа (-fix50). Т.е. для данного случая более высокая плавность будет достигнута за счет фикса обратных дропов (там где нужно) или по другой причине?
SmoothVideo Project → Эксплуатация SVP → Замена выпавших кадров (drop'ов) и SVP
Powered by PunBB, supported by Informer Technologies, Inc.