Log in

View Full Version : How To Overlay Bobbed Metrics On Original Clip


johnmeyer
11th September 2017, 18:28
Short version of my question: How do I get the bobbed metric from the comparison of the two fields in a frame to display over the original source (un-bobbed) video?

Longer version:

My film transfer machine's timing got screwed up and I didn't notice the problem until I'd transferred 8+ hours of film. I went back to re-do the transfer, and the Firewire on my FX1 camcorder blew out. 2+ months and $$$ to fix, so I have to deal with what I've got.

The problem is quite fixable because it only affects one field in a frame, and it only happens for a few seconds every minute, affecting roughly a dozen frames before the timing drifts back into alignment.

I have my fix working, and can overlay the metrics on top of the bobbed source, but what I want to do is compute the metrics from the bobbed source, but then overlay that metric on top of the original video. I must be having a brain freeze, because I can't figure out how to do it. Once I have a bobbed stream, the "frame" numbers for that stream are 2x the original frame numbers.

In essence, I want to have everything happen on the screen while looking at frames, not fields, and I only want to see the inter-frame field difference metrics, not the differences between the last field in the previous frame and the first frame in the current frame.

Here's a link to a 32-frame test clip. If you bob it, you'll see that many of the frames are just fine, but when the problem happens, the first field is fine but the second field is blurred because the film was captured while moving.

32-frame 3MB test clip (https://www.mediafire.com/file/h4pgo70v499iedi/bad%20film%20transfer%20test%20clip.avi)

Here's the almost-finished script. It works, but is difficult to use because of having to walk through bobbed fields. It will place numbers over the bobbed version of the film if you set METRICS=TRUE. This overrides everything else. If you set METRICS=FALSE and REPLACE=TRUE, it will correctly replace the bad field with the other field. I can then un-bob with a selectevery and weave (not shown in this script), and have my original film frames back, with the good frames un-touched, and the bad frames with half the vertical resolution, but no blur. (I could also motion estimate a frame or field, but this approach has the advantage of introducing zero artifacts.)

So, how do I get the bobbed metric from the comparison of the two fields in a frame to display over the original source (un-bobbed) video?

#Find And (Optionally) Fix Bad Frames
#Requires interlaced video where fields normally are from same point in time, but when pulldown happens on one field,
#the two fields don't match. So, replace the bad field with the good field, and live with half the resolution for one frame.

#-----------------------------
#Control the script operation by changing the following values :
#=====================================================================
VideoFile = "e:\fs.avi"
#VideoFile = "S:\Video\Rosen Video\Rosen Movies\1 (yellow sticker); 11 on can; Europe June 15 1952 to August 18, 1952.avi"
global badthreshold = 2.0 # Set METRICS=TRUE to determine best value
METRICS = TRUE # TRUE will show Metrics ONLY (i.e., TRUE overrides all other selctions)
SHOWDOT = FALSE # TRUE will add "***" to each replacment frame (for troubleshooting)
REPLACE = FALSE # TRUE will replace each bad frame with a one that is interpolated from adjacent frames
FILEWRITE = FALSE # TRUE will create a file which contains the frame numbers of all bad frames
filename = "E:\Bad.txt" # Set to name and location where you want the frame numbers stored
#=====================================================================

source = AVISource(VideoFile).convertTOYV12().killaudio().bob(0.0,1.0) #Do totally dumb bob. This is important.
script = """Subtitle("\nPrevious Ratio = " + String( YDifferenceFromPrevious(source) /
\ Max(YDifferenceFromPrevious( selectevery(source, 1, -2) ),0.001 ) ) , lsp=0)"""
MetClip = Scriptclip(source, script)

FileFixed = (FILEWRITE)
\ ? WriteFileIf(source, filename, "
\ YDifferenceFromPrevious(source) / Max(YDifferenceFromPrevious( selectevery(source, 1, -2) ),0.001 )
\ > badthreshold && (current_frame %2 <> 0)", "((current_frame-1)/2)", append = false) : Source

output = (METRICS) ? MetClip : (REPLACE) ? ReplaceBadField(FileFixed,showdot) : FileFixed
return output.separatefields().selectevery(4,1,2).weave() #Use this return when creating a new video file.
#return output #Use this return when looking at metrics. "Frame" numbers will be 2x real frame numbers
#------------------------------

function ReplaceBadField (clip c, bool SHOWDOT)
{
replacement = SHOWDOT ? c.subtitle("***").selectevery(1,-1) : c.selectevery(1,-1)
fixed = ConditionalSelect(c, "
Prev = YDifferenceFromPrevious()
Prev1 = Max(YDifferenceFromPrevious( selectevery( 1, -2) ),0.001 )
Prev/Prev1 > badthreshold && (current_frame %2 <> 0) ? 0 : 1", \
replacement, c)

return fixed
}


If StainlessS reads this, he may recognize a little code from a different bad frame replacement script he helped me with a year ago. I just re-used the same construct and plugged in new code.

StainlessS
11th September 2017, 19:27
Think this should work John, (I did not use RT_Stats, not sure what avs you are using),
Not tested much at all.


#Find And (Optionally) Fix Bad Frames From Botched Film Transfer

#-----------------------------

#Control script operation by changing the following values :
#=====================================================================
VideoFile = "d:\bad film transfer test clip.avi"
filename = "D:\Bad.txt" # Set to name and location where you want the frame numbers stored
global badthreshold = 2 # Set METRICS=TRUE to determine best value
METRICS = TRUE # TRUE will show Metrics ONLY (i.e., TRUE overrides all other selctions)
SHOWDOT = FALSE # TRUE will add "***" to each replacment frame (for troubleshooting)
REPLACE = FALSE # TRUE will replace each bad frame with a one that is interpolated from adjacent frames
FILEWRITE = FALSE # TRUE will create a file which contains the frame numbers of all bad frames
METMODE = True # False=Bobbed, True=Not bobbed
#=====================================================================

ORG = AVISource(VideoFile).convertTOYV12().killaudio()
source = ORG.bob()

# Note below we use Last (source given to ScriptClip)
script = """
S="\nPrevious Ratio = " + String( YDifferenceFromPrevious(Last) / Max(YDifferenceFromPrevious(SelectEvery(Last, 1, -2) ),0.001 ) )
Subtitle(S , lsp=0)
"""

# Note below we use Source (ORG given to ScriptClip)
script2 = """
curRem = current_frame
current_frame = current_frame*2 # Source has double frames, ORG Even field
S1="\nPrevious Ratio = " + String(YDifferenceFromPrevious(source) / Max(YDifferenceFromPrevious(SelectEvery(source, 1, -2)),0.001 ) )
current_frame = current_frame+1 # ORG Odd field
S2="\nPrevious Ratio = " + String(YDifferenceFromPrevious(source) / Max(YDifferenceFromPrevious(SelectEvery(source, 1, -2)),0.001 ) )
current_frame = curRem # Title on current frame of ORG clip (arg to subtitle)
return Subtitle(S1+S2 , lsp=0)
"""


MetClip = (!METMODE) ? Scriptclip(source, script) : Scriptclip(ORG, script2)

FileFixed = (FILEWRITE)
\ ? WriteFileIf(source, filename, "
\ YDifferenceFromPrevious(source) / Max(YDifferenceFromPrevious( selectevery(source, 1, -2) ),0.001 )
\ > badthreshold", "current_frame", append = false)
\ : Source

output = (METRICS) ? MetClip : (REPLACE) ? ReplaceBadField(FileFixed,showdot) : FileFixed
return output

#------------------------------

function ReplaceBadField (clip c, bool SHOWDOT)
{
replacement = selectevery(c,1,-1) # previous field
fixed = ConditionalSelect(c, "
Prev = YDifferenceFromPrevious()
Prev1 = Max(YDifferenceFromPrevious( selectevery( 1, -2) ),0.001 )
Prev/Prev1 > badthreshold && (current_frame %2 <> 0) ? 0 : 1", \
replacement, c)

return fixed
}


EDIT: Does that do it ?, did not touch anything not in blue.

EDIT:
In essence, I want to have everything happen on the screen while looking at frames, not fields, and I only want to see the inter-frame field difference metrics, not the differences between the last field in the previous frame and the first frame in the current frame.

I'm feelin' bit tired, and cant really be bothered to figure out if I did exactly what you want, I'm sure you can remove anything that is not required.
EDIT: Maybe you wanna remove top S1 Metric.

johnmeyer
11th September 2017, 21:11
StainlessS,

Thanks for the quick response. I'll check this as soon as my current VD run is finished.

johnmeyer
12th September 2017, 01:30
Everything is working. Thanks so much!