Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
23rd July 2016, 19:07 | #2 | Link |
Registered User
Join Date: Sep 2007
Posts: 5,345
|
One way would be to insert a "placeholder" frame every 4th frame, then replace with an interpolated frame
see this post http://forum.videohelp.com/threads/3...=1#post2222196 |
24th July 2016, 08:03 | #4 | Link |
Moderator
Join Date: Oct 2001
Location: Hawaii
Posts: 7,406
|
I'd create duplicate frames to replace the missing ones and then use filldrops to replace them with interpolated frames (similar to pdr's method):
SelectEvery(3,0,1,2,2)# or whatever the exact cadence is Filldrops() http://forum.doom9.org/showthread.ph...779#post753779 http://forum.doom9.org/showthread.ph...82#post1493082 |
24th July 2016, 17:29 | #5 | Link |
Registered User
Join Date: Feb 2002
Location: California
Posts: 2,691
|
Using Selectevery() by itself will work, but only if you have absolutely no interruption in the drop cadence.
I totally agree with Manano, and do this sort of thing all the time. For instance, in this video I manually replaced all the "jump" frames with a duplicate of the previous frame. I then fed that to "FillDrops" and it created near-perfect video: Restoration of Jumpy Film I too was going to suggest FillDrops: Code:
function filldrops (clip c) { super=MSuper(c,pel=2) vfe=manalyse(super,truemotion=true,isb=false,delta=1) vbe=manalyse(super,truemotion=true,isb=true,delta=1) filldrops = mflowinter(c,super,vbe,vfe,time=50) fixed = ConditionalFilter(c, filldrops, c, "YDifferenceFromPrevious()", "lessthan", "0.1") return fixed } You might find some very interesting code in the following thread I started a few years ago: Automatically fix dups followed (eventually) by drops My video was the more typical scenario where the video had the correct number of frames, but had lots of dropped frames. To keep the audio in sync, the capture card or streaming service added duplicate frames, usually within 1-2 frames of the drop. Finding the duplicate frames was easy, but sensing where there was a drop was more difficult. Then, I had to come up with a way of creating the fixed video, within the constraints of how AVISynth works. Fortunately, Didée came up with a super-clever solution which I incorporated into the script that I presented in post #6 in that thread. You should look at that script and see if it can be adapted to your needs. BTW, if you have all these drops, how is your audio staying in sync?? Usually, if frames get dropped, and there are not an equal number of duplicates, the audio and video end up being different lengths. Last edited by johnmeyer; 24th July 2016 at 17:34. Reason: added link to restoration video |
25th July 2016, 14:17 | #6 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Might also want to take a look here [MorphDupes_MI(), for runs of dupes but can be limited to single dupe run]:- http://forum.doom9.org/showthread.ph...65#post1764865
EDIT: Oops, fixed link (was to single post, linked script is in two parts). EDIT: Set MaxInterp=1, th=0.0. EDIT: Can jump about if required when viewing metrics.
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 25th July 2016 at 16:50. |
29th October 2021, 01:19 | #8 | Link | |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Mod to Mugfunky/JohnMeyer/Selur Filldrops()
Code:
######################################################################################### # # FillDrops.avsi # # An AviSynth filter to detect and replace duplicate frames # with a motion-interpolation of the adjacent frames. # # mod 2021-07-10 by Selur # mod 29 Oct 2021, Added ThreshIs8Bit arg. ssS. https://forum.doom9.org/showthread.php?p=1956020#post1956020 # # - based on Mug Funky's FillDrops # - FillDrops by johnmeyer on Doom9's forum # https://forum.doom9.org/showthread.php?p=1775184#post1775184 # - mod by Selur to parametrize Luma Difference Threshold # https://forum.videohelp.com/threads/402416-repair-Videos-with-duplicates-and-dropped-frames#post2624936 # ### Requirements ### #------------------- # Avs v2.60/+ # MvTools2 (https://github.com/pinterf/mvtools) # ### Arguments ### #----------------- # thresh (default=0.1) - Luma Difference Threshold # Lets you specify how different a frame has to be (from the previous frame) # before it's considered not to be a duplicate, and therefore not replaced with a motion interpolated frame. # If the threshold is too small, some duplicate will not be replaced. # If it's too large, many frames which aren't duplicates (just having very small motions) will be replaced. # (explanation by jagabo on VideoHelp) # # --------------- # ThreshIs8Bit, Default False, If True and bit depth > 8 bit, then thresh is converted to current bit depth threshold. ### Changelog ### #--------------- # Changed requirements: from MvTools to MvTools2 (johnmeyer) # Parametrized Luma Difference Threshold (Selur) # ssS: Added Bool arg "ThreshIs8Bit", default = False. ######################################################################################### Function FillDrops(clip c, float "thresh",Bool "ThreshIs8Bit") { thresh = Default(thresh, 0.1) ThreshIs8Bit = Default(ThreshIs8Bit,False) # False = thresh is in current bit depth range try { bpc=c.BitsPerComponent } catch(msg) { bpc=8 } thresh = (ThreshIs8Bit) ? thresh * BitLShift(1,bpc-8) : thresh # super = MSuper(c, pel=2) vfe = MAnalyse(super, truemotion=true, isb=false, delta=1) vbe = MAnalyse(super, truemotion=true, isb=true, delta=1) filldrops = MFlowInter(c, super, vbe, vfe, time=50) fixed = ConditionalFilter(c, filldrops, c, "YDifferenceFromPrevious()", "lessthan", String(thresh)) return fixed } Function FilldropsI (clip c, float "thresh",Bool "ThreshIs8Bit") { thresh = Default(thresh, 0.1) ThreshIs8Bit = Default(ThreshIs8Bit,False) # False = thresh is in current bit depth range try { bpc=c.BitsPerComponent } catch(msg) { bpc=8 } thresh = (ThreshIs8Bit) ? thresh * BitLShift(1,bpc-8) : thresh # even = c.SeparateFields().SelectEven() super_even=MSuper(even,pel=2) vfe=manalyse(super_even,truemotion=true,isb=false,delta=1) vbe=manalyse(super_even,truemotion=true,isb=true,delta=1) filldrops_e = mflowinter(even,super_even,vbe,vfe,time=50) odd = c.SeparateFields().SelectOdd() super_odd=MSuper(odd,pel=2) vfo=manalyse(super_odd,truemotion=true,isb=false,delta=1) vbo=manalyse(super_odd,truemotion=true,isb=true,delta=1) filldrops_o = mflowinter(odd,super_odd,vbo,vfo,time=50) evenfixed = ConditionalFilter(even, filldrops_e, even, "YDifferenceFromPrevious()", "lessthan", String(thresh)) oddfixed = ConditionalFilter(odd, filldrops_o, odd, "YDifferenceFromPrevious()", "lessthan", String(thresh)) Interleave(evenfixed,oddfixed) Weave() } EDIT: Added arg, Bool "ThreshIs8Bit", default=False. Quote:
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 29th October 2021 at 01:34. |
|
29th October 2021, 20:22 | #10 | Link | |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
@ JohnMeyer,
Do you remember Gavino post:- https://forum.doom9.org/showthread.p...78#post1409378 Quote:
If we do in fact tween using a 2nd EXACT dupe, then there is no problem at all in how it now works, however, in case of FillDrops, we do the tween governed by a threshold, and so the 2nd of two assumed identical frames is not necessarily identical at all, maybe only an eye movement or something. It is unlikely to make any major difference to results, but there will be times when it produces a definitely better result (I think). All it needs is to use Delta=2 instead of 1, and use the filldrops frame from n-1 to fix the assumed duplicate at n. (so we are tweening between n-1 and n+1). Thoughts ... EDIT: Whilst I'm at it, I might as well add HPad=16, VPad=16, and maybe a few more usual args to MSuper. EDIT: I can also fix the interlaced version too. EDIT: Something like this (untested) Code:
Function FillDrops(clip c, float "thresh",Bool "ThreshIs8Bit") { thresh = Default(thresh, 0.1) ThreshIs8Bit = Default(ThreshIs8Bit,False) # False = thresh is in current bit depth range try { bpc=c.BitsPerComponent } catch(msg) { bpc=8 } thresh = (ThreshIs8Bit) ? thresh * BitLShift(1,bpc-8) : thresh # super = MSuper(c, pel=2,hpad=16,vpad=16) vfe = MAnalyse(super, truemotion=true, isb=false, delta=2) vbe = MAnalyse(super, truemotion=true, isb=true, delta=2) filldrops = MFlowInter(c, super, vbe, vfe, time=50).SelectEvery(1,-1) fixed = ConditionalFilter(c, filldrops, c, "YDifferenceFromPrevious()", "lessthan", String(thresh)) return fixed }
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 29th October 2021 at 20:33. |
|
29th October 2021, 23:23 | #11 | Link |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
John does this meet with your approval [dated 30 Oct 2021, about 40 mins from now].
Code:
######################################################################################### # # FillDrops.avsi # # An AviSynth filter to detect and replace duplicate frames # with a motion-interpolation of the adjacent frames. # # mod 2021-07-10 by Selur # mod 29 Oct 2021, Added ThreshIs8Bit arg. ssS. https://forum.doom9.org/showthread.php?p=1956020#post1956020 # mod 30 Oct 2021, ssS:- https://forum.doom9.org/showthread.php?p=1956096#post1956096 # Corrected original odd Delta=1 to Delta=2 (see:- https://forum.doom9.org/showthread.php?p=1409378#post1409378 ) # Added ShowDot, arg. # # - based on Mug Funky's FillDrops # - FillDrops by johnmeyer on Doom9's forum # https://forum.doom9.org/showthread.php?p=1775184#post1775184 # - mod by Selur to parametrize Luma Difference Threshold # https://forum.videohelp.com/threads/402416-repair-Videos-with-duplicates-and-dropped-frames#post2624936 # ### Requirements ### #------------------- # Avs v2.60/+ # MvTools2 (https://github.com/pinterf/mvtools) # ### Arguments ### #----------------- # thresh (default=0.1) - Luma Difference Threshold # Lets you specify how different a frame has to be (from the previous frame) # before it's considered not to be a duplicate, and therefore not replaced with a motion interpolated frame. # If the threshold is too small, some duplicate will not be replaced. # If it's too large, many frames which aren't duplicates (just having very small motions) will be replaced. # (explanation by jagabo on VideoHelp) # # --------------- # ThreshIs8Bit, Default False, If True and bit depth > 8 bit, then thresh is converted to current bit depth threshold. ### Changelog ### #--------------- # ShowDot, If True, Subtitle "*" on frame Bottom Left of interpolated frames. [Interlaced Even field "*-" and Odd field "-*"] #--------------- # Changed requirements: from MvTools to MvTools2 (johnmeyer) # Parametrized Luma Difference Threshold (Selur) # ssS: Added Bool arg "ThreshIs8Bit", default = False. Added ShowDot default False. ######################################################################################### Function FillDrops (clip c, float "thresh",Bool "ThreshIs8Bit",Bool "ShowDot") { thresh = Default(thresh, 0.1) ThreshIs8Bit = Default(ThreshIs8Bit,False) # False = thresh is in current bit depth range ShowDot = Default(ShowDot,false) try { bpc=c.BitsPerComponent } catch(msg) { bpc=8 } thresh = (ThreshIs8Bit) ? thresh * BitLShift(1,bpc-8) : thresh super = MSuper(c, pel=2,hpad=16,vpad=16,sharp=1,rfilter=4) vfe = MAnalyse(super, truemotion=true, isb=false, delta=2,blksize=16,blksizeV=16,Overlap=8,OverlapV=8,search=4, dct=0) vbe = MAnalyse(super, truemotion=true, isb=true, delta=2,blksize=16,blksizeV=16,Overlap=8,OverlapV=8,search=4, dct=0) filldrops = MFlowInter(c, super, vbe, vfe, time=50,blend=false) # Dont blend at scene change : Generate interpolated frame n at filldrops frame n-1. # SHIFT n-1 to frame n, and Maintain original length, ConditionalFilter returns length of 2nd (filldrops) clip. filldrops = filldrops.DuplicateFrame(0).DeleteFrame(c.FrameCount) filldrops = (ShowDot) ? filldrops.Subtitle("*",align=1,font="Courier New") : filldrops # If ShowDot, then subtitle Single asterisk at bottom left. fixed = ConditionalFilter(c, filldrops, c, "YDifferenceFromPrevious()", "lessthan", String(thresh)) return fixed.AudioDubEx(c) # ConditionalFilter returns audio from filldrops clip which is shifted. [Should not be necessary, Safety Measure only] } Function FilldropsI (clip c, float "thresh",Bool "ThreshIs8Bit",Bool "ShowDot") { thresh = Default(thresh, 0.1) ThreshIs8Bit = Default(ThreshIs8Bit,False) # False = thresh is in current bit depth range ShowDot = Default(ShowDot,false) try { bpc=c.BitsPerComponent } catch(msg) { bpc=8 } thresh = (ThreshIs8Bit) ? thresh * BitLShift(1,bpc-8) : thresh # even = c.SeparateFields().SelectEven() super_even=MSuper(even,pel=2,hpad=16,vpad=8,sharp=1,rfilter=4) vfe=manalyse(super_even,truemotion=true,isb=false,delta=2,blksize=16,blksizeV=8,Overlap=8,OverlapV=4,search=4, dct=0) vbe=manalyse(super_even,truemotion=true,isb=true, delta=2,blksize=16,blksizeV=8,Overlap=8,OverlapV=4,search=4, dct=0) filldrops_e = mflowinter(even,super_even,vbe,vfe,time=50,blend=false) # dont blend at scene change filldrops_e = filldrops_e.DuplicateFrame(0).DeleteFrame(c.FrameCount) filldrops_e = (ShowDot) ? filldrops_e.Subtitle("*-",align=1,font="Courier New") : filldrops_e # EVEN, If ShowDot, then subtitle asterisk + hyphen (*-) at bottom left. # odd = c.SeparateFields().SelectOdd() super_odd=MSuper(odd,pel=2,hpad=16,vpad=8,sharp=1,rfilter=4) vfo=manalyse(super_odd,truemotion=true,isb=false,delta=2,blksize=16,blksizeV=8,Overlap=8,OverlapV=4,search=4, dct=0) vbo=manalyse(super_odd,truemotion=true,isb=true, delta=2,blksize=16,blksizeV=8,Overlap=8,OverlapV=4,search=4, dct=0) filldrops_o = mflowinter(odd,super_odd,vbo,vfo,time=50,blend=false) # dont blend at scene change filldrops_o = filldrops_o.DuplicateFrame(0).DeleteFrame(c.FrameCount) filldrops_o = (ShowDot) ? filldrops_o.Subtitle("-*",align=1,font="Courier New") : filldrops_o # ODD, If ShowDot, then subtitle hyphen + asterisk (-*) at bottom left. # evenfixed = ConditionalFilter(even, filldrops_e, even, "YDifferenceFromPrevious()", "lessthan", String(thresh)) oddfixed = ConditionalFilter(odd, filldrops_o, odd, "YDifferenceFromPrevious()", "lessthan", String(thresh)) Interleave(evenfixed,oddfixed) Weave() return Last.AudioDubEx(c) # ConditionalFilter returns audio from filldrops clip which is shifted. [Should not be necessary, Safety Measure only] } I've used eg BlkSize=16, BlkSizeV=8, Overlap=8,OverlapV=4, for Interlaced, is that OK. [I get rid of interlaced stuff at earliest opportunity] Also Added a ShowDot whatsit [EDIT: At Bottom left, to distinguish from other ShowDots, Interlaced showdot different for Even/Odd].
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 29th October 2021 at 23:54. |
30th October 2021, 00:46 | #12 | Link |
Registered User
Join Date: Feb 2002
Location: California
Posts: 2,691
|
I would have to play around with it to know for sure whether it is an improvement.
I did not go back and re-read that thread, but I've revisited this Delta=2 issue many times. In general, I always try to avoid using Delta=2 because by using information from two frames away, you introduce additional temporal (and spatial) displacement compared to Delta=1. For most MVTools2 applications you use Delta=1 for exactly that reason. What I have always wanted with MVtools2 -- and maybe there is a way to do this -- is to estimate the next frame using vectors from the two previous frames. You obviously need to have to samples for each pixel from two different frames in order to create a vector. When the goal is to interpolate a new frame at some position following the current frame it just seems like you'd get better results using the previous two frames because that way you only have one point on the vector that is from a moment in time that is two frames away. However, the proof will be in the use, and when I get a chance I'll try to see if your approach produces cleaner video. |
30th October 2021, 02:23 | #13 | Link | |
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
You use Delta=1 only for eg framerate doubling where you want to interpolate/synthesize a frame between each existing adjacent frame pair,
if you want to replace a frame (corrupt frame or tween a dupe) then you have to use Delta=2 (which uses as source those frames either side of the frame to be replaced), it was pure accident that original Filldrops worked, and seemingly [in most cases] without NOTICABLE problems, but it is most certainly wrong (both spacially and temporally). Original FillDrops where replacing EXACT dupe, then is no problem at all, but when not exact dupe (ie little motion) then is spatial/temporally wrongly synthesized. If the mod does not seem better, then will be down to me changing blkSize (from 8 to 16) and the other similar settings that I changed. [ msuper(sharp, rfilter) ] EDIT: MSuper(hpad=16,vpad=16) can only improve things, pad of 8 can cause distortion around frame edge, mostly left and right. [especially if blksize greater than 8] EDIT: Here the only example in mvtools docs that uses delta=1. (where moving adjacent frames to align with current for degraining - ie not interpolating at all) Code:
To denoise by MDegrain2 with overlapped blocks (blksize=8) and subpixel precision: AVISource("c:\test.avi") # or MPEG2Source, DirectShowSource, some previous filter, etc super = MSuper(pel=2, sharp=1) backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4) backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4) forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4) forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4) MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400) but NOT a frame that looks like a dupe simply because the YDifferencetoPrevious is below some threshold. Where a seeming dupe (low motion non dupe) is synthesized, it would ideally produce a frame that is also quite similar to the replaced mistaken dupe. [but not where delta=1, where would be spatially/temporally skew whiff - probably not by that much, but wrong nevertheless] EDIT: when Gavino said this: Quote:
[If the Big G sees this, then maybe he could respond]
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? Last edited by StainlessS; 30th October 2021 at 13:14. |
|
30th October 2021, 18:53 | #14 | Link |
Registered User
Join Date: Feb 2002
Location: California
Posts: 2,691
|
StainlessS,
I tried out your version of Filldrops and the results looked very good. Thank you for taking the time to do that. The only additional tweaking might be to slightly modify the MAnalyze parameters. You may remember this thread: SlowMo: Simple slow motion, using interpolation The script I posted had some "magic" parameters that soon became the touchstone against which other MFlowFPS() attempts were measured. I didn't have any great insight when I made that post, I simply did 100+ tests and kept tuning until I came up with those settings. Even without the forum rules, there really is no "best," especially when it comes to motion estimation, but any time I need to get the cleanest results from MFlowFPS, I always use start with the two-step estimation shown in that link. Now I need to spend a few minutes with your last version of "Duplicity" to see if it handles the drop/dup problem that I've been obsessed with perfecting. I don't see how it could work for that, but you've posted a few times that it will, so I'm going to try it on my test cases. |
30th October 2021, 19:00 | #15 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Hi StainlessS, I remember that discussion, although the details are a bit hazy now - well, it was 11 years ago!
Your summary and analysis of what I said there is correct - in general, you need to use delta=2 when replacing a frame by interpolating between the frames on either side of it, but delta=1 will work if the frame to be replaced is a dup (exact or perhaps very close) of the previous one. However, John continued to maintain that in practice delta=1 worked better. Later in that same thread, I suggested a possible explanation: Quote:
|
|
30th October 2021, 20:11 | #16 | Link | |
Registered User
Join Date: Feb 2002
Location: California
Posts: 2,691
|
Quote:
I've tried to figure out a way to get MVtools2 to do this, but have never succeeded. Since most of my use for Filldrops is to remove exact dups, I see no reason not to use my old Delta=1 version since, as pointed out again in this thread, it works when Delta+1 and Delta+2 are the identical frames. Don't get me wrong, I very much appreciate the mods StainlessS made, and I will use his version when appropriate. |
|
7th November 2021, 23:04 | #17 | Link | ||
HeartlessS Usurer
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
|
Sorry guys, I've been a bit AWOL.
Gavino, Good God, 11 years ago !!! Yep, I vaguely remembered that thing about MFlowInter and occlusion areas, I tried to find it actually but must have skipped over it. Maybe that 2*delta thingy could be done on purpose, rather than rely on dupe/noisydupe delta=1 whotsit. by john, Quote:
Quote:
__________________
I sometimes post sober. StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace "Some infinities are bigger than other infinities", but how many of them are infinitely bigger ??? |
||
Thread Tools | Search this Thread |
Display Modes | |
|
|