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.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage
Register FAQ Calendar Today's Posts Search

Reply
 
Thread Tools Search this Thread Display Modes
Old 26th May 2014, 20:55   #1  |  Link
lisztfr9
Registered User
 
Join Date: Apr 2010
Posts: 175
Interpolating duplicated frames

Hi all,

I was trying out gavino's nice script for interpolating duplicated frames :

Code:
# ScriptClip(last, "Subtitle(String(YDifferenceFromPrevious))")


#Interpolation_for_second_frame_of_duplicate_(by_Gavino).avs
super = MSuper()
backward_vectors = MAnalyse(super, isb = true, delta=2)
forward_vectors = MAnalyse(super, isb = false, delta=2)
inter = MFlowInter(super, backward_vectors, forward_vectors, time=50, ml=70)
ConditionalFilter(inter.Loop(2,0,0), last, "YDifferenceFromPrevious", "<", "2.0")
# ConvertToRGB24() # for easy display in VirtualDub
Sometimes, 2.0 is fine but when Y vary not much, it should be ~0.75... So i was wondering if this could be made adaptive, to the average luma difference ?

YDifferenceFromPrevious > 10 threshold ~ 2

YDifferenceFromPrevious < 7 threshold ~ 1

But the threshold should not jerk too much, i mean i cannot simply made it like f(YDifferenceFromPrevious)...

Well how to write this function ?

Thanks ,

L
lisztfr9 is offline   Reply With Quote
Old 26th May 2014, 22:08   #2  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,373
Try this, I think it's a better dupe detector:
Code:
#Interpolation_for_second_frame_of_duplicate_(by_Gavino).avs
super = MSuper()
backward_vectors = MAnalyse(super, isb = true, delta=2)
forward_vectors = MAnalyse(super, isb = false, delta=2)
inter = MFlowInter(super, backward_vectors, forward_vectors, time=50, ml=70)
#ConditionalFilter(inter.Loop(2,0,0), last, "YDifferenceFromPrevious", "<", "2.0")
S=Subtract(Last, BlankClip(Last, length=1)+Last)
ConditionalFilter(inter.Loop(delta, 0, 0), Last, "YPlaneMinMaxDifference(S, 2) ", "<", "1")
# ConvertToRGB24() # for easy display in VirtualDub
raffriff42 is offline   Reply With Quote
Old 26th May 2014, 22:25   #3  |  Link
johnmeyer
Registered User
 
Join Date: Feb 2002
Location: California
Posts: 2,695
Several quick thoughts ...

1. The point of the function is to interpolate and then replace duplicated frames. By definition, a duplicated frame with have a Ydiff value of zero. So, for true duplicates, any value, including zero, will work.

2. If the two frames are not perfectly identical, but a "visually identical," then you are correct that the Ydiff value can be quite different at various points in the clip, and yet the adjacaent frames may still look the same. My advice is to simply use a larger value for the threshold because if two frames are not perfectly identical, but are really, really close, and you end up replacing one of these "almost identical" frames with an interpolated frame, you probably won't even be able to tell the difference (i.e., you won't create a really bad frame).

3. If you truly want to create an adaptive difference value, I recommend playing around with taking ratios of Ydiff values, using the current frame to last frame, and the last frame to the frame before that (and even more frame pairs, if needed). There are more complex variations on the idea, but the basic concept is that by taking ratios, you end up with a function that only does something when the difference is much less than its neighbors. Depending on your function, and depending on exactly what you are trying to accomplish, you may need to incorporate scene detection logic.

Another variation on the idea is to create a moving average of Ydiff values, and then compare the current Ydiff to that moving average, and only invoke the conditional logic when the current Ydiff exceeds that moving average by a set amount.
johnmeyer is offline   Reply With Quote
Old 26th May 2014, 22:59   #4  |  Link
lisztfr9
Registered User
 
Join Date: Apr 2010
Posts: 175
Thanks for replying, you'r right, per definition duplicated frames should be identical, but there is some blocking, which rise a little diff.

i added such a function :

function fmin(float f1, float f2) {
return (f1>f2) ? 2 : 1
}

ConditionalFilter(inter.Loop(2,0,0), last, "YDifferenceToNext", "<", "fmin(YDifferenceFromPrevious, 8.0)")

i had to change for YDifferenceToNext in order to get it work, - still testing it.

If you are interested, i'm trying to rescue an old movie, Fährmann Maria Which is only available on youtube or in that IQ.

Now at scene changes, the last frame is repeated after the first new one !

Last edited by lisztfr9; 26th May 2014 at 23:07. Reason: news
lisztfr9 is offline   Reply With Quote
Old 27th May 2014, 06:38   #5  |  Link
bxyhxyh
Registered User
 
Join Date: Dec 2011
Posts: 354
If it is grainy source, difference is always higher and not really dependent to detect duplicates.
So I think testclip should be denoised.
One boolean argument called grainy or something should be there.
bxyhxyh is offline   Reply With Quote
Old 27th May 2014, 11:13   #6  |  Link
lisztfr9
Registered User
 
Join Date: Apr 2010
Posts: 175
Yes, i have also a series of black frames, all seen as dupes... ! And other very static sequence.. transitions with fade out, rise very little Y. I will try raffriff42' suggestion.
lisztfr9 is offline   Reply With Quote
Old 27th May 2014, 12:03   #7  |  Link
lisztfr9
Registered User
 
Join Date: Apr 2010
Posts: 175

lisztfr9 is offline   Reply With Quote
Old 27th May 2014, 12:08   #8  |  Link
lisztfr9
Registered User
 
Join Date: Apr 2010
Posts: 175
@raffriff42

I don't seem to understand how your Subtraction statement works, since i can't see any differences (see 1th pic), but obviously there are (see 2nd pic). And it seems to detect dupes very well !

Blancklip + last is AlignedSplice...

Ok you skip 1 frame

But how to skip black frames ?

L

Last edited by lisztfr9; 27th May 2014 at 13:49.
lisztfr9 is offline   Reply With Quote
Old 27th May 2014, 14:56   #9  |  Link
lisztfr9
Registered User
 
Join Date: Apr 2010
Posts: 175
I was trying some formula like this, but still not working :

video = ScriptClip(video, "Subtitle(String(YPlaneMinMaxDifference(S, 2) + LumaDifference(video, BlankClip($FFFFFF))) )")

To skip black frame, a White Clip to show max difference to black frames...

-----

Blanc = BlankClip(video, $FFFFFF).ConvertToYV12()

video = ScriptClip(video, "Subtitle(String(LumaDifference(video, Blanc)))")

Keeps crashing... ? why

---------------

This is not crashing :

Blanc = BlankClip(Width=Width(video), Height=Height(video), color=$FFFFFF)
Blanc = Blanc.ConvertToYV12()

S=Blanc

video = ScriptClip(video, "Subtitle(String(LumaDifference(Blanc)))")

I guess ScriptClip cannot evaluate LumaDifference(video, Blanc) but leave clip1 as implicit, it works : i get average lumadiff = 218, to black frames (max would be 255). Well, why Scriptclip can't take LumaDiff with 2 arguments ? And there are many better solutions i guess, i'm just puting junk together

Last edited by lisztfr9; 27th May 2014 at 15:39.
lisztfr9 is offline   Reply With Quote
Old 27th May 2014, 15:38   #10  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,431
Quote:
Originally Posted by lisztfr9 View Post
video = ScriptClip(video, "Subtitle(String(LumaDifference(video, Blanc)))")

Keeps crashing... ? why
Infinite recursion - see here.

Write it like this:
video = ScriptClip(video, "Subtitle(String(LumaDifference(last, Blanc)))")

EDIT: last can also be left implicit, as you have discovered:
video = ScriptClip(video, "Subtitle(String(LumaDifference(Blanc)))")
__________________
GScript and GRunT - complex Avisynth scripting made easier

Last edited by Gavino; 27th May 2014 at 15:44.
Gavino is offline   Reply With Quote
Old 27th May 2014, 19:27   #11  |  Link
lisztfr9
Registered User
 
Join Date: Apr 2010
Posts: 175
Found :
Quote:
function fmin(float f1, float f2) {
return (f1<f2) ? 100 : f1
}

T = 20

S = ScriptClip(S, "Subtitle(String(fmin(AverageLuma(last), T)))")
To insert in raffriff42' suggestion :

Quote:

#ConditionalFilter(inter.Loop(2,0,0), last, "YDifferenceFromPrevious", "<", "2.0")
S=Subtract(Last, BlankClip(Last, length=1)+Last)
ConditionalFilter(inter.Loop(delta, 0, 0), Last, "YPlaneMinMaxDifference(S, 2) ", "<", "1")
I will made the threshold variable, rising it up for black frames.

But as johnmeyer said, a better script should use ratio instead.

------

I was using a denoiser in depan today. I found theses settings working very well, detecting scene changes :

mdata = DePanEstimate(i, dxmax=8, dymax=8, zoommax=1, trust=1.0, stab=1.0)
DePanInterleave(i, data=mdata, info=true)
# FluxSmoothST()
DeGrainMedian(limitY=5,limitUV=7,mode=2)
SelectEvery(3, 1)
lisztfr9 is offline   Reply With Quote
Old 27th May 2014, 21:43   #12  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,373
Yes, BlankClip(length=1)+Clip makes a clip "delayed" by 1 frame. To "advance" by one frame, use Clip.Trim(1, 0). Check the first & last frames of the final video; they will probably be invalid and will need to be trimmed off.

The "Subtract" method breaks down somewhat if noise or moving artifacts are present. If the source is clean, subtracting the previous frame - if it's a duplicate - will give you a plain gray image, and YPlaneMinMaxDifference will be exactly zero. If there's noise present, it won't be zero, but it *should* still be lower on a dupe frame than any non-dupe frame.

For fine tuning the threshold values, you'll want to examine the video, noting the difference values for known good & bad frames with something like this:
Code:
## S=Subtract(...
ScriptClip(Last, 
\ """Subtitle("diff="+String(YPlaneMinMaxDifference(S, 2)))""")
...BTW the YPlaneMinMaxDifference threshold argument of "2" was chosen at random; another value might be better. It should be greater than 0 though; not sure why.

If there is grain etc, it helps to denoise the 2 clips being subtracted:
Code:
## LP=BlankClip(...
S=Subtract(Last.Blur(1.0).Blur(1.0), LP.Blur(1.0).Blur(1.0))
...or call RemoveGrain or whatever works best for the type of noise you have. The denoised clips won't be seen in the final output, so the processing can be very aggressive.
raffriff42 is offline   Reply With Quote
Old 28th May 2014, 15:22   #13  |  Link
lisztfr9
Registered User
 
Join Date: Apr 2010
Posts: 175
Very helpful post from raffriff42, in fact i didn't dare to use such a amount of blur. Now using Blur(1.0).Blur(1.0), and only 1 as threshold argument for YPlaneMinMaxDifference, almost all my duplicated frames are detected. I need to deflicker the source, maybe i get even better results.

Edit

o = last
sm = o.bicubicresize(174,88) #25% of source
smm = sm.temporalsoften(1,12,255,24,2).merge(sm,0.25)
smm = smm.temporalsoften(2,7,255,20,2)
o2 = o.mt_makediff(mt_makediff(sm,smm,U=3,V=3).bicubicresize(width(o),height(o),0,0),U=3,V=3)

but i let it as it is... it doesn't improve very much.

Last edited by lisztfr9; 28th May 2014 at 17:02.
lisztfr9 is offline   Reply With Quote
Old 28th May 2014, 18:53   #14  |  Link
lisztfr9
Registered User
 
Join Date: Apr 2010
Posts: 175


I will try it with MVtools.
lisztfr9 is offline   Reply With Quote
Old 31st May 2014, 22:36   #15  |  Link
lisztfr9
Registered User
 
Join Date: Apr 2010
Posts: 175
Seeing only motion vectors

I'm not sure it performs better as dupes detection than previous methods.

Code:
# LOAD PLUGIN :

LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\DGDecode.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\ac3source.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\NicAudio.dll")

LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\depanestimate.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\depan.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\FluxSmooth.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\DeGrainMedian.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\mvtools2.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\FFT3DFilter.dll")

a1 = ColorBars().Trim(0,399)
a2 = ImageSource("dot.png").ConvertToRGB32

# a2.GreyScale returns a grey dot on a black background;
# Levels makes the dot white
mask_clip = Mask(a2, a2.GreyScale.Levels(0, 0.001, 75, 0, 255))

# Layer(a1, mask_clip)

Overlay(a1, a2, mask=ShowAlpha(mask_clip), y=0, x=0, mode="blend", opacity=1)

ConditionalReader("C:\Program Files\AviSynth 2.5\Examples\xoffset.txt", "ol_x_offset", false)
ConditionalReader("C:\Program Files\AviSynth 2.5\Examples\yoffset.txt", "ol_y_offset", false)

ConvertToYV12(last)

S = last

vectors = MSuper().MAnalyse(isb = false)
MShow(Msuper(), vectors, scale = 1)

Crop(last, 8, 8, -8, -8)

Subtract(S, last)


/*
# cinetic blur :
super = MSuper()
backward_vectors = MAnalyse(super, isb = true)
forward_vectors = MAnalyse(super, isb = false)
MFlowBlur(super, backward_vectors, forward_vectors, blur=200)
*/

mt_edge(last, "prewitt").Grayscale()

# info()

Last edited by lisztfr9; 31st May 2014 at 22:36. Reason: Spell
lisztfr9 is offline   Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 00:25.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.