Re: Замена выпавших кадров (drop'ов) и SVP

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

Re: Замена выпавших кадров (drop'ов) и SVP

MAG79 wrote:

1. Можно еще поинтересоваться о том как были получены выпавшие кадры?

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

MAG79 wrote:

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

Другой вариант найти нельзя (абсолютно точно нельзя), но в данном конкретном случае просмотр уже в прошлом:
собственно с этого глючного сериала, чтобы хоть как-то более менее терпимо (плавно) его посмотреть я и стал изучать ависинт, в итоге ничего лучше "TDecimate(cycle=7)" так и не удалось подобрать, и бОльшая часть дублей как раз выбрасывалась (в среднем 3 дропа в секунду было), ну и частично нужные кадры повыбрасывались, где в 7-ке кадров не было дропов.

В теории при "TDecimate(Mode=2,rate=22)" должно было быть медленнее, но лучше (дропы раскиданы хаотично, и ложных срабатываний при анализе сразу всех кадров за каждую секунду должно было быть меньше), и вроде было получше, но при этом был рассинхрон ~500мс (причины которого я так и не понял, и никакой инфы не нашёл sad ).

На данный момент меня это видео интересует исключительно для тестовых целей (на будущее, т.к. видео с дропами периодически встречается, пусть и не в таком жутком количестве дропов, как в моём семпле).

Re: Замена выпавших кадров (drop'ов) и SVP

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

Как должно быть:
исходник : кадр1 - кадр2 - дубль - кадр4 - кадр5
результат: кадр1 - кадр2 - Fix-50 - кадр4 - кадр5

Как это выглядит в файле из архива:
исходник : кадр1 - кадр2 - дубль - кадр4 - кадр5
результат: кадр1 - Fix-50 - кадр2 - кадр4 - кадр5

Из-за этого подергивания еще сильней усугубились, т.к. перед скачком (кадр2-кадр4) идет затормаживание, а на смене сцен вообще красотища: перемигивание кадров из предыдущей и следующей сцены. big_smile
Прогнал через оригинальный скрипт - все в порядке. Как удалось умудрится этим скриптом сделать видео еще хуже - я не представляю. hmm

29 (edited by Bars 15-02-2013 14:11:38)

Re: Замена выпавших кадров (drop'ов) и SVP

MAG79 wrote:

Причина: замена кадров дублей со смещением на кадр раньше.
Как должно быть:
исходник : кадр1 - кадр2 - дубль - кадр4 - кадр5
результат: кадр1 - кадр2 - Fix-50 - кадр4 - кадр5

Как это выглядит в файле из архива:
исходник : кадр1 - кадр2 - дубль - кадр4 - кадр5
результат: кадр1 - Fix-50 - кадр2 - кадр4 - кадр5

Вот именно про это я и писал в первом комментарии, во втором пункте

MAG79 wrote:

Прогнал через оригинальный скрипт - все в порядке.

Тоже FlipVertical() использовали, чтобы не было перевернутого изображения из-за DSS2?

MAG79 wrote:

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

Я сейчас ещё потестировал, и оказалось что моё изначальное предположение было верным, всё дело в том, через что открывать, через DSS2 (со всеми отключенными фильтрами в запускаемом ffdshow) тоже всё нормально (так что деблокинг или повышение резкости совершенно непричём), а через AVISource будет то, что я приложил в архиве. Почему-то при открытие через AVISource скрипт работает неправильно.
Просто сколько я читал, avi обычно рекомендуют открывать именно через AVISource, поэтому и я так делал.

Re: Замена выпавших кадров (drop'ов) и SVP

Bars
DSS2 открывает на каждом компьютере используя DS-декодеры, установленные в системе, выбирая согласно приоритетам (merit-ам). Это может оказаться ffdShow, LAV или любой другой декодер. Поэтому перевернутая картинка - это индивидуально на одной конкретной системе так вышло. Переставить LAV или ffdShow с повышением приоритетов и это исправится. У меня DSS2 кадры открывает нормально, не перевернутыми.

AVISource не пробовал. Возможно в нем проблема, но скорее всего в самом AVI, VirtualDub ругается на него, мол отсутствуют первые два кадра. Вот Avisynth'у и снесло башку от нестандартного AVI. В нем еще и кадры-дубли закодированы по-честному (D - флаг пропуска кадра). Это значит, что кодировщик имел доступ к информации, что кадр пропущен, иначе бы закодировался кадр-близнец. А как такие D-кадры обрабатываются Avisynth'ом я не проверял. Возможно, для него D означает заполнить это пропуск кадром из будущего, а не из прошлого. Ну а иначе я просто не могу объяснить такую чехарду с кадрами.

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

И я не имел в виду включенные улучшалки именно в ffdShow. Просто до формата H.264 не сущестовало стандартизованного правила по декодированию и декодерам не ставилось условие попиксельного соответствия декодеру-референсу. Постобработка не являлась стандартом и обязательным условием. Поэтому в общем случае кадры полученные через AVISource, DirectShowSource и DSS2 дадут разные картинки с разной степенью постобработки. И не обязательно Вам об этом сообщат разработчики декодера или выведут настройку наружу. hmm
Перевернутая картинка - это яркий пример нестандартизованного способа распаковки и постобработки кадра.

Но это все лирика и уже далека от темы замены выпавших кадров. Я так понял, что все получилось и все теперь устраивает?
Я рад. smile

31 (edited by Bars 15-02-2013 15:27:12)

Re: Замена выпавших кадров (drop'ов) и SVP

MAG79 wrote:

DSS2 открывает на каждом компьютере используя DS-декодеры, установленные в системе, выбирая согласно приоритетам (merit-ам). Это может оказаться ffdShow, LAV или любой другой декодер. Поэтому перевернутая картинка - это индивидуально на одной конкретной системе так вышло.

Да, это я уже знал, когда читал про DSS2, с причиной как раз мне было всё-понятно...а вот про изменение приоритетов фильтров я как-то вообще забыл sad (давно GSpot'ом не пользовался)

MAG79 wrote:

Переставить LAV или ffdShow с повышением приоритетов и это исправится.

Спасибо, изменил, так удобнее (на воспроизведения в плеере не повлияло, там свои приоритеты для фильтров прописаны)

MAG79 wrote:

AVISource не пробовал. Возможно в нем проблема, но скорее всего в самом AVI, VirtualDub ругается на него, мол отсутствуют первые два кадра.

Как станно, учитывая что семпл этот я специально вырезал через:
"VirtualDubMod 1.5.10.3 (build 2550/release)"

MAG79 wrote:

В нем еще и кадры-дубли закодированы по-честному (D - флаг пропуска кадра).

Спасибо! Теперь я, наконец, понял почему в свойствах рендерера при воспроизведении (без плавности) частота колебалась в райне 22, а не была чётко 25

MAG79 wrote:

Я так понял, что все получилось и все теперь устраивает?

В принципе да, ваш скрипт оказался полностью нормально работающим через DSS2 и этого думаю вполне достаточно.

P.S. Но вот вопрос с двумя отсутствующими кадрами всё ещё не дает покоя, сам виртуалдуб вырезает, а потом сам же и ругается на отсутствующие кадры...(хотя может у вас версия дуба другая?)

Re: Замена выпавших кадров (drop'ов) и SVP

Bars
вопрос с двумя отсутствующими кадрами всё ещё не дает покоя, сам виртуалдуб вырезает, а потом сам же и ругается на отсутствующие кадры...(хотя может у вас версия дуба другая?)
Проверял на оказавшемся под рукой VDub 1.9.11.1 APNG Mod. Он что-то буркнул мне, что двух первых кадров нет и что сдвинет весь видеоряд на 80ms, мол возможно отставание аудиодорожки. Файл и VDub остались на работе. Если это так важно, то могу скачать еще раз и посмотреть уже на домашнем VDub (тут у меня оригинальный 1.9.10 установлен). Но я верю, что с этим вопросом можно разобраться без меня самостоятельно wink

Re: Замена выпавших кадров (drop'ов) и SVP

MAG79 wrote:

Но я верю, что с этим вопросом можно разобраться без меня самостоятельно wink

Да, конечно.

P.S. Все не очень ясные моменты по теме, вы уже прояснили, спасибо

Re: Замена выпавших кадров (drop'ов) и SVP

Подкинул тут Булат95 ссылку на плавный трейлер игрушки BattleField 4.
Трейлеры 720p и 1080p и правда имеют 60 к/сек, но вот только во многих сценах присутствуют выпавшие кадры. Мне это дело не очень понравилось, поэтому решил попытать свои силы в задаче повышения плавности игровым трейлерам. smile
Заодно развить алгоритм замены выпавших кадров.

Вышел довольно сложный, но мощный скрипт: 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. Классический. Дроп, затем скачок.

http://www.svp-team.com/forum/misc.php?item=2468

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

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

Случай 3. Пропуск кадра из-за низкой частоты рендера кадров игровым движком.
И перед выпавшим кадром и после него нет скачков. Кадра просто не считалось игрой изначально. Если заменить такой дроп на один интерполированный по середине с соседом кадр, то получим два кадра с уполовиненным по скорости движением. Я пока решил интерполировать оба кадра, которые ограничивают кадровый интервал. Первый кадр интерполирую с левым, получая положение 66%: fix66, второй кадр - с правым до положения 33%: fix33.
Таким образом получаю вместо дропа серию из трех замедленных на 33% но равномерно двигающихся кадров. Выглядит уже лучше, чем дерганный исходник.

Все желающие могут скачать и посмотреть результат:
BF4_720p60_DropsFixed.mkv (1,21 ГБ)

Post's attachments

BF4_drop_ani.gif, 256.92 kb, 256 x 343
BF4_drop_ani.gif 256.92 kb, 352 downloads since 2013-04-05 

Re: Замена выпавших кадров (drop'ов) и SVP

Исправил несколько ошибок в предыдущем скрипте, переназвал вставляемые кадры по-правильному: как они соотносятся во времени к заменяемому:
fix50 - взять кадр между текущим и следующим по середине (+50%);
-fix50 - взять кадр между текущим и предыдущим по середине (-50%);
-fix33 & fix33 - всегда идут парой друг за другом с той же логикой: (-33% и 33%);

Картинки-диаграммы движения с выпавшим кадром, которые умеет восстанавливать скрипт:

http://www.svp-team.com/forum/misc.php?item=2470
http://www.svp-team.com/forum/misc.php?item=2471
http://www.svp-team.com/forum/misc.php?item=2472

Скрипт 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 ГБ)

Post's attachments

-fix50_ani.gif, 5.1 kb, 443 x 121
-fix50_ani.gif 5.1 kb, 284 downloads since 2013-04-06 

fix33x2_ani.gif, 6.19 kb, 443 x 121
fix33x2_ani.gif 6.19 kb, 308 downloads since 2013-04-06 

fix50_ani.gif, 4.76 kb, 443 x 121
fix50_ani.gif 4.76 kb, 299 downloads since 2013-04-06 

Re: Замена выпавших кадров (drop'ов) и SVP

Добавлю объективности к выше сказанному.
Написал небольшой скрипт определения количества дублей в файле. Посчитал для имеющихся трех файлов.

Итак, Цифры, характеризующие качество работы вышеприведенных скриптов:
В исходном файле BF4_720p60.mp4 1142 одиночных выпавших кадра и 56 двойных.
В файле BF4_720p60_DropsFixed.mkv 318 одиночных выпавших кадра и 84 двойных.
В файле BF4_720p60_DropsFixed_v2.mkv 189 одиночных выпавших кадра и 96 двойных.

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

Re: Замена выпавших кадров (drop'ов) и SVP

Отличная работа, результат на лицо!

Re: Замена выпавших кадров (drop'ов) и SVP

Окончательный вариант ролика с замененными выпавшими кадрами: BF4_720p60_DropsFixed_v3.mkv (1,25 ГБ)

Отличается от двух предыдущих:
- возвращена ошибочно выставленная частота кадров с 60 fps до 59.94 fps. Это исключило появление 62 выпавших кадров на ровном месте wink
- добавлена замена парных выпавших кадров;
- добавлена замена тройных выпавших кадров;
- изменены настройки интерполяции для уменьшения волновых артефактов на интерполированных кадрах, применено смешивание кадров на сменах сцен.

Вот карта расположения выпавших кадров во всех четырех роликах с цифрами.

http://www.svp-team.com/forum/misc.php?item=2483
http://www.svp-team.com/forum/misc.php?item=2484
http://www.svp-team.com/forum/misc.php?item=2485
http://www.svp-team.com/forum/misc.php?item=2486

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

Итого за три итерации количество отдельно стоящих выпавших кадров уменьшено с 1160 до 170. По остальным типам выпавших кадров тоже получен значительный прогресс.

Разработанный скрипт избавляет видео в первую очередь от приостановок в глобальных движениях: панорамирование, зум. Локальные движения остаются без изменений.
Теперь, при просмотре ролика на фоне плавных движений камеры уже явно бросаются в глаза недоработки игрового движка:
- низкая частота кадров, примененная в анимации персонажей (особенно неприятно смотрится перемещение персонажей и смена поз попеременно через кадр);
- низкая точность анимации персонажей, что делает их движения кукольными особенно вблизи;
- низкая точность анимации объектов, скачкообразные движения вертолета;
- двойные крылья у птиц smile

Вот такие у меня замечания. Но несмотря на вышесказанное, приятного просмотра! wink

Post's attachments

DropsMap_Fixed_v1.png 6.78 kb, 120 downloads since 2013-04-11 

DropsMap_Fixed_v2.png 6.56 kb, 101 downloads since 2013-04-11 

DropsMap_Fixed_v3.png 5.46 kb, 86 downloads since 2013-04-11 

DropsMap_src.png 6.39 kb, 126 downloads since 2013-04-11 

39 (edited by dlr5668 11-04-2013 19:00:53)

Re: Замена выпавших кадров (drop'ов) и SVP

А сам скрипт(3ю версию) где можно скачать ?

Re: Замена выпавших кадров (drop'ов) и SVP

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

Скрипт 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-ми вариантов;

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

Re: Замена выпавших кадров (drop'ов) и SVP

Очень круто! Сохранил, буду использовать. Спасибо.

42 (edited by Vivian 29-05-2013 17:18:03)

Re: Замена выпавших кадров (drop'ов) и SVP

MAG79
Очень интересная тема. Попробовал скрипт на видео, снятом на слабой видеокарте, и там дропы через каждый кадр, после уплавнения стало плавнее  lol , но все равно множество двоящихся объектов (например, снег). Но в качестве скорой помощи, очень полезная вещь. Хотя идея предотвращать дропы мне нравится больше). А с помощью чего Вы делали статистику дропов в видео?

Re: Замена выпавших кадров (drop'ов) и SVP

Vivian
с помощью чего Вы делали статистику дропов в видео?
С помощью скрипта выводил статистику в текстовый файл и анализировал в MS Excel.

Re: Замена выпавших кадров (drop'ов) и SVP

MAG79
Скрипт GameDropFix_v3
Данный скрипт заточен именно под игровое видео? (в плане чувствительности определения движения и т.д. и т.п.)

Если цель дубли в фильмах/сериалах, то есть смысл переходить с "второй версии DoubleDropFix.avs" (из этого поста, которой я пользуюсь с февраля и её качество меня в принципе устраивает) на GameDropFix_v3?

Re: Замена выпавших кадров (drop'ов) и SVP

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

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

46 (edited by Bars 28-08-2013 07:32:06)

Re: Замена выпавших кадров (drop'ов) и SVP

MAG79 wrote:

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

Я в курсе про TIVTC и пользуюсь им по назначению именно для циклических дублей.
Но DropFix из текущей темы мне пригождается именно для удаления хаотично расположенных дублей (или как в том варианте, что мы обсуждали в начале этой темы) или в качестве дополнения, после отработки TDecimate, т.к. попадаются фильмы где при смене сцен последовательность меняется, и как итог после смены сцены остаётся дубль
(что-то подобное описано тут).

Если я правильно понял, то мне стоит продолжить пользоваться DoubleDropFix.avs, а переходить на GameDropFix_v3 нет никакого смысла?

Re: Замена выпавших кадров (drop'ов) и SVP

Bars
мне стоит продолжить пользоваться DoubleDropFix.avs, а переходить на GameDropFix_v3 нет никакого смысла?
Для фильмов лучше подойдет DoubleDropFix.

Re: Замена выпавших кадров (drop'ов) и SVP

MAG79
Здравствуйте.
Есть вопрос по DoubleDropFix, а скорее проблема sad
Небольшой тестовый семпл (исходник + после обработки 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 - было бы отлично, а так опять имеем перемигивание sad

Ну и третий пример на скринах, просто единичный замененный кадр, но почему-то с индикацией Fix66, т.е. и тут что-то пошло не так.

P.S. Перепробовал различные декодеры (LAV, ffdshow) с различными вариантами открытия в avs-скрипте: DSS2, ffvideosource, AVISource - безрезультатно

Re: Замена выпавших кадров (drop'ов) и SVP

Bars
Спасибо за наблюдения! smile

Архив скачал, поглядел. Была проблема в логике скрипта.
Скрипт по-разному искал кадры-дубли для текущего и соседних с ним кадров, отсюда появлялись половинки двойных замен кадров-дублей: 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.

Re: Замена выпавших кадров (drop'ов) и SVP

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). Т.е. для данного случая более высокая плавность будет достигнута за счет фикса обратных дропов (там где нужно) или по другой причине?