Log in

View Full Version : The power of Avisynth: restoring old 8mm films.


Pages : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [21] 22 23 24 25 26 27 28 29 30 31

StainlessS
22nd August 2017, 11:22
Also how should I add the GamMac script to VideoFred’s script? I am not sure how to use the FredAverage and without it, using VideoFred and GamMac’s script is resulting in noticeable color banding as mentioned elsewhere.


I'll try implement dithering.

raffriff42
24th August 2017, 05:34
A script like this (with many chained filters) would be an ideal candidate for porting to AVS+ at 10-bits or greater. I might be able to help, using whatever knowledge I picked up doing the (unfinished) documentation.

johnmeyer
13th September 2017, 23:34
I finally got around to adding GamMac to my version of VideoFred's script. I also got around to doing a lot of deferred housecleaning. As one example, I never use any of the manual controls because I do all those corrections in my NLE. So, I took them out.

I started to think about the order of the restoration steps and decided I could get a better result if I did degraining first, and then used the motion-compensated version of RemovedDirt second. This seems to produce a more pleasing result because with RemoveDirt first, I was getting too much correlation in the remaining grain, i.e., the image movement sometimes looked "gooey" as things moved around.

GamMac introduces a lot of flicker and I wasn't able to find any settings that would eliminate that. So, I moved Deflicker to the end of the restoration chain and, fortunately, it removes the flicker that GamMac introduces, as well as most flicker in the film itself. Hopefully I'll be able to get a better handle on GamMac over the coming weeks and perhaps eliminate that problem.

I thought about posting this in the thread that branched out from this one. That is where I posted my previous update. However, that thread has gone dormant, while this one is still active, so I'm posting here.

I am also including the "filldrops()" function. I find this incredibly useful. In my NLE (Vegas) I wrote a script that lets me, with the push of one button, replace any bad frame with a copy of the previous frame. This is useful for burned frames; huge dirt spots; bad registration errors during transfer (e.g., a frame that "jumps"); a photographer's flash; and anything else that is distracting or annoying that only lasts for one single frame. Since each duplicate frame I create in Vegas is a 100% perfect duplicate, it is simple for AVISynth to detect that dup, and it is easy to create a new frame by motion estimating from the surrounding frames. Any frame that is not a duplicate is passed through (which is 99.99% of all frames) so the function has almost no speed penalty because most frames are not altered. Therefore, most of the new interpolated frames are absolutely perfect and cannot be detected. Quite magic, actually.

So, I've put the script into the next two posts. Hopefully people will find it to be a slight improvement over what I've posted in the past.

johnmeyer
13th September 2017, 23:38
# Film restoration script by videoFred.
# Denoising, resizing, stabilising, sharpening, auto-levels and auto-white balance.
#
# Modified by John Meyer, October 7, 2012
# Modified by John Meyer, July 7, 2015 (remove errors)
# Modified by John Meyer, September 13, 2017
#
# Changes made by Meyer (June 8, 2010):
# 1. Replaced the MVDegrainMulti function, which was part of the original MVTools
# with the equivalent function using the newer and faster MVTools2.
# 2. Added RemoveDirt function prior to Degrain in order to eliminate large dust spots. This
# substantially improves the dirt removal capabilities of this script. The user will need to
# download this plugin at:
# http://www.removedirt.de.tf/
# 3. Eliminated a great deal of sharpening. The original script did sharpening in at least four places.
# With grainy film stock, this sometimes created objectionable grain. Also, the limitedSharpenFaster
# function, while excellent for video, is uncessarily slow, and isn't really needed for this low
# resolution source. Too much sharpening can make the film look too much like video.
# 4. Added multithreading. I was able to roughly triple the script performance. It may be possible to
# substantially increase this, perhaps as much as 12x instead of 3x. However, the autolevels function
# would have to be replaced.
# 5. Fixed several things I found. The result3 option didn't have the manual color correction code, so I
# added that back in. All the numbered "stab" variables (stab1, stab2, etc.) aren't needed except
# for providing a test function for stabilization. I eliminated all of this to streamline the script.
# 6. Deflicker seemed redundant, given all the averaging that takes place with MDegrain, and also the averaging
# that is done when the autolevels outputs are selected.
# 7. I reduced the number of frames used for averaging autolevels from the default (which is 5) to 2.
# I probably should add a variable in the header so the user can change this. Something else to do
# in the future ...
# 8. I added yet another set of crop parameters. I did this because both my capture and my output are
# done using NTSC DV AVI which is 720x480. However, 8mm film is almost exactly square, so the captured
# 720x480 video has black bars on the side. These need to be cropped off prior to doing motion
# stabilization, but then added back prior to the final output, which must still be 720x480 with the
# black bars on the side.
# 9. I reduced the default depan settings to 20, which is what was recommended in the original script. I
# also reduced the post-depan cropping. I did this so I could keep as much of the original frame
# as possible.
# 10. I removed the second denoising and sharpening function. It just seemed to be too much, and made the
# result too artificial
# 11. I removed the MVFLowFPS interpolation. I did this during one of dozens and dozens of attempts
# to improve the speed of the script. I should probably add this back, but if I do so, I also
# need to make it work correctly for interlaced output. If the goal is to show this on an NTSC or PAL
# television set, then it is not correct to convert from the film fps to 25 fps progressive (PAL) or
# 29.97 fps progressive (NTSC). Instead, this should be done as follows (example given is NTSC):
#
# MFlowFPS(source,super,backward_vec, forward_vec, num=60000, den=1001,ml=200)
# SeparateFields()
# SelectEvery(4, 0, 3)
# Weave()
#
# This yields interlaced 29.97, which has twice the temporal resolution as 29.97 progressive, and will
# therefore look correct on a TV set. I have done a lot of this as part of my Kinescope to video
# conversion scripts. For those scripts, the goal is to make the filmed version of a TV show look
# like it was actually videotaped. However, for something that originated on film, this "does violence"
# to the original feel of the media. It is true that it can make horizontal pans less "juddery," but
# it won't feel like film anymore. Also, this technique does break down, espcially with fast motion
# in the foreground.
# 12. Removed the unecessary "coloryuv(off_U=blue,off_V=red)" statement from the denoising section.
# 13. Added killaudio() statement to prevent lockups when using SetMTMode().
#
# Changes made on October 7, 2012
#
# 1. Modified RemoveDirtMC function to do estimation in two steps. This improves performance and quality.
# 2. Modified MDegrain to do estimation in two steps. This provides roughly the same quality with blocksize=8
# as what I was getting with blocksize=4, but with virtually no performance penalty
# 3. Updated to use special build of MVTools2 that works with SVP.
# 4. Moved Autolevels inside special multi-threading section in order to improve performance with autolevels.
# 5. Removed all trim commands because I do all editing outside the script (in Vegas).
# 6. Included two alternative ways to do frame interpolation: SVP and InterFrame. The InterFrame script is probably better
# but I included the SVP code because it may provide a starting point for more customized approaches. Neither is enabled by default.
#
# Changes made on September 13, 2017
#
# 1. Replaced old useless color correction with GamMac.
# 2. Removed never-used manual controls.
# 3. Moved deflicker to end of chain because GamMac introduces flicker.
# 4. Moved RemoveDirtMC to happen AFTER denoising.

johnmeyer
13th September 2017, 23:39
#====================================================================================
#7/12/2021 Fixed Mrecalculate errors
#VIDEO FILE
#----------------------------------------------------------------------------------------------------------------------------
#Change the following line to point to your video file
film="e:\fs.avi"


#GENERAL PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
result="resultS2" #specify the wanted output here
play_speed=16 #play speed (8mm=16; Super8=18; 16mm sound=24)


#COLOR AND LEVELS PARAMATERS
#----------------------------------------------------------------------------------------------------------------------------
saturation = 1.0 #for all outputs
gamma = 1.0 #for all outputs

#GamMac Parameters
LockChan = 0 #(0=red channel)
Scale = 1
RedMul = 1.0
GrnMul = 1.0
BluMul = 1.0
LockVal = 128.0
Th = 0.1


#SIZE, CROP AND BORDERS PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
CLeft=8 CTop=8 CRight=8 CBottom=8 #crop values after Depan and before final resizing
W=720 H=480 #final size after cropping
bord_left=0 bord_top=0 bord_right=0 bord_bot=0 #720p= borders 150
in_bord_left=0 in_bord_top=0 in_bord_right=0 in_bord_bot=0 #Borders around input that must be removed


#STABILISING PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
maxstabH=10 #maximum values for the stabiliser (in pixels) 20 is a good start value
maxstabV=10
est_left=40 est_top=40 est_right=40 est_bottom=40 #crop and contast values for special Estimate clip
est_cont=1.6


#DENOISING PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
denoising_strength=600 #denoising level of first denoiser: MVDegrain()
block_size= 16 #block size of MVDegrain
block_size_v= 16
block_over= 8 #block overlapping of MVDegrainMulti()

#Alternate denoising using smaller block size
#denoising_strength= 600 #denoising level of first denoiser: MDegrain()
#block_size= 8 #block size of MVDegrain
#block_size_v= 8
#block_over= 4 #block overlapping of MVDegrainMulti()

#Alternate denoising using smalles block size
#denoising_strength= 600 #denoising level of first denoiser: MDegrain()
#block_size= 4 #block size of MVDegrain
#block_size_v= 4
#block_over= 2 #block overlapping of MVDegrainMulti()

dirt_strength=18 #sets amount of dirt removal (big spots)


#FOUR STEP SHARPENING PARAMETERS
#--------------------------------------------------------------------------------------------------------------------------------
#120 is pretty aggressive; 85 seems more subtle
#PRE_sharp_ness= 120 PRE_radi_us= 3 #presharpening (UnsharpMask) just after first denoising
PRE_sharp_ness= 85 PRE_radi_us= 3 #presharpening (UnsharpMask) just after first denoising

Sharp_Strength = 0.1 #0.05 is often better (avoid too much sharpening)


#AUTO LEVELS PARAMETER
#--------------------------------------------------------------------------------------------------------------------------------
X=4 #X parameter for reducing the autolevels effect on the whites
X2=4 #X2 parameter for reducing the autolevels effect on the blacks


#NUMBER OF THREADS
#--------------------------------------------------------------------------------------------------------------------------------
threads=4


# END VARIABLES, BEGIN SCRIPT
#=================================================================================================================================

SetMemoryMax(768)

LoadPlugin ("mvtools2.dll") #Version 2.5.11.9 2/24/2012
LoadPlugin("autolevels.dll") #Version 0.6.0.0 1/09/2011
LoadPlugin("Deflicker.dll") #Version 0.4.0.0 8/16/2004
Loadplugin("Depan.dll") #Version 1.10.0.0 4/09/2007
LoadPlugin("DepanEstimate.dll") #Version 1.9.2.0 3/25/2007
LoadPlugin("fft3dfilter.dll") #Version 2.1.1.0 2/20/2007
Loadplugin("mt_masktools.dll") #Version 2.0.23.0 3/14/2008
loadplugin("RemoveDirtSSE2.dll") #Version 0.9 5/05/2005
Loadplugin("RemoveGrainSSE2.dll") #Version 0.9 5/01/2005
#Loadplugin("removegrain.dll") #Version 0.9 5/01/2005
Loadplugin("warpsharp.dll") # 4/05/2010

#Use the following for alternative frame interpolation
#loadplugin("svpflow1.dll") #Version 1.2.1.0 5/29/2012
#loadplugin("svpflow2.dll") #Version 1.3.1.0 6/02/2012
#Import("InterFrame2.avsi") #Version 2.1.0 6/27/2012


#Remove all setmtmode statements (there are three in this script) if not using multi-threaded (MT) AVISynth
setmtmode(5,threads)
source1= Avisource(film).killaudio().assumefps(play_speed).converttoYV12()
cropped_source=source1.crop(in_bord_left,in_bord_top,-in_bord_right,-in_bord_bot) #remove any black borders on input video
setmtmode(2)

#cropped_source=filldrops(cropped_source) #Use this when removing bad frames that have been removed by duplicating previous frame


#STABILIZING
#....................................................................................................................................................................
stab_reference= cropped_source.crop(est_left,est_top,-est_right,-est_bottom).tweak(cont=est_cont).MT_binarize(threshold=80).greyscale().invert()
mdata=DePanEstimate(stab_reference,trust=1.0,dxmax=maxstabH,dymax=maxstabV)
stab=DePanStabilize(cropped_source,data=mdata,cutoff=0.5,dxmax=maxstabH,dymax=maxstabV,method=1,mirror=15)
stabcrop=stab.crop(CLeft,CTop,-CRight,-CBottom)


#DENOISING
#...................................................................................................................................................................
prefiltered = RemoveGrain(stabcrop,2)
superfilt = MSuper(prefiltered, hpad=32, vpad=32,pel=2)
super= MSuper(stabcrop, hpad=32, vpad=32,pel=2)

halfblksize= (block_size>4) ? block_size/2 : 4
halfoverlap= (block_over>2) ? block_over/2 : 2

bvec1 = MAnalyse(superfilt, isb = true, delta = 1, blksize=block_size, overlap=block_over,dct=0)
bvec1 = MRecalculate(super, bvec1, blksize=halfblksize, overlap=halfoverlap,thSAD=100)

fvec1 = MAnalyse(superfilt, isb = false, delta = 1, blksize=block_size, overlap=block_over,dct=0)
fvec1 = MRecalculate(super, fvec1, blksize=halfblksize, overlap=halfoverlap,thSAD=100)

bvec2 = MAnalyse(superfilt, isb = true, delta = 2, blksize=block_size, overlap=block_over,dct=0)
bvec2 = MRecalculate(super, bvec2, blksize=halfblksize, overlap=halfoverlap,thSAD=100)

fvec2 = MAnalyse(superfilt, isb = false, delta = 2, blksize=block_size, overlap=block_over,dct=0)
fvec2 = MRecalculate(super, fvec2, blksize=halfblksize, overlap=halfoverlap,thSAD=100)

# Use these additional vectors if you enable three level denoising (below)
# bvec3 = MAnalyse(superfilt, isb = true, delta = 2, blksize=block_size, overlap=block_over,dct=0)
# bvec3 = MRecalculate(super, bvec3, blksize=halfblksize, overlap=halfoverlap,thSAD=100)
# fvec3 = MAnalyse(superfilt, isb = false, delta = 2, blksize=block_size, overlap=block_over,dct=0)
# fvec3 = MRecalculate(super, fvec3, blksize=halfblksize, overlap=halfoverlap,thSAD=100)


#Use the second line below, and un-comment the four lines above if you want to average more frames. Doesn't seem necessary for most work IMHO.
denoised=stabcrop.MDegrain2(super, bvec1,fvec1,bvec2,fvec2,thSAD=denoising_strength).levels(0,gamma,255,0,255).tweak(sat=saturation).unsharpmask(PRE_sharp_ness,PRE_radi_us,0)

#Three level denoising
#denoised=stabcrop.MDegrain3(super, bvec1,fvec1,bvec2,fvec2,bvec3,fvec3,thSAD=denoising_strength).tweak(sat=saturation).unsharpmask(PRE_sharp_ness,PRE_radi_us,0)

#Remove Dirt
denoised = RemoveDirtMC(denoised,dirt_strength,false)

#SHARPENING
#...................................................................................................................................................................
sharp1=denoised.sharpen(Sharp_Strength)

PreBorderFrame = sharp1.Lanczos4Resize(W - bord_left - in_bord_left - bord_right - in_bord_right, H - bord_top - in_bord_top - bord_bot - in_bord_bot)

#FRAME INTERPOLATION (optional)
#...................................................................................................................................................................
#Everything in this section is commented out because I usually choose NOT to do frame interpolation because
#it causes too many unexpected artifacts on certain frames. It also makes the film look like video which
#aesthetically is not always pleasing.

/*
prefiltered = RemoveGrain(PreBorderFrame,2)
super = MSuper(PreBorderFrame,hpad=16, vpad=16, levels=1) # one level is enough for MRecalculate
superfilt = MSuper(prefiltered, hpad=16, vpad=16) # all levels for MAnalyse
backward = MAnalyse(superfilt, isb = true, blksize=16,overlap=8,search=3,dct=0)
forward = MAnalyse(superfilt, isb = false, blksize=16,overlap=8,search=3,dct=0)
forward_re = MRecalculate(super, forward, blksize=8, thSAD=100)
backward_re = MRecalculate(super, backward, blksize=8, thSAD=100)
PreBorderFrame = MFlowFps(PreBorderFrame,super, backward_re, forward_re, num=30000, den=1001,ml=200,mask=2)
*/

#Alternative interpolation
/*
superfps= MSuper(PreBorderFrame,pel=2)
backward_vec2 = MAnalyse(superfps, isb = true,blksize=16)
forward_vec2 = MAnalyse(superfps, isb = false,blksize=16)
PreBorderFrame = MFlowFps(PreBorderFrame,superfps, backward_vec2, forward_vec2, num=60000, den=1001, ml=200).SeparateFields().SelectEvery(4, 0, 3).Weave()
*/

#Yet another way to do interpolation
#The following alternative can provide synthesized frames for hi-def material that causes MSuper to choke
#////// Begin alternative to MFlowFPS ////
#SmoothFPS2(PreBorderFrame,threads)
#////// End alternative to MFlowFPS ////

#A final way to do interpolation, although Interframe is just a front-end to SmoothFPS, so I don't think the results are any different.
#The following is another alternative that can provide synthesized frames for hi-def material that causes MSuper to choke. Probably better than the one above.
#////// Begin alternative to MFlowFPS ////
#PreBorderFrame=InterFrame(NewNum=30000,NewDen=1001,PreBorderFrame,GPU=true,Cores=threads)
#////// End alternative to MFlowFPS ////

#RESULT1: AUTOLEVELS,AUTOWHITE
#......................................................................................................................................................................
result1= PreBorderFrame.ConvertToRGB24.GamMac(Show=False, LockChan=LockChan, Th=Th, LockVal=LockVal, Scale=Scale, RedMul=RedMul, GrnMul=GrnMul, BluMul=BluMul).converttoYV12().deflicker().addborders(X,0,0,0,$FFFFFF).addborders(0,0,X2,0,$000000).autolevels(filterRadius=2).crop(X,0,-X2,-0).addborders(bord_left+in_bord_left, bord_top+in_bord_top, bord_right+in_bord_right, bord_bot+in_bord_bot)

#RESULT2: AUTOWHITE
#......................................................................................................................................................................
result2= PreBorderFrame.ConvertToRGB24.GamMac(Show=False, LockChan=LockChan, Th=Th, LockVal=LockVal, Scale=Scale, RedMul=RedMul, GrnMul=GrnMul, BluMul=BluMul).converttoYV12().deflicker().addborders(bord_left+in_bord_left, bord_top+in_bord_top, bord_right+in_bord_right, bord_bot+in_bord_bot)

#RESULT3: AUTOLEVELS
#.....................................................................................................................................................................
result3= PreBorderFrame.addborders(X,0,0,0,$FFFFFF).addborders(0,0,X2,0,$000000).autolevels(filterRadius=2).crop(X,0,-X2,-0).addborders(bord_left+in_bord_left, bord_top+in_bord_top, bord_right+in_bord_right, bord_bot+in_bord_bot)

#RESULT4: NO CORRECTIONS
#.....................................................................................................................................................................
result4= PreBorderFrame.addborders(bord_left+in_bord_left, bord_top+in_bord_top, bord_right+in_bord_right, bord_bot+in_bord_bot)

#PARAMETERS FOR THE COMPARISONS
#.....................................................................................................................................................................
W2= W+bord_left+bord_right
H2= H+bord_top+bord_bot
source4=Lanczos4Resize(source1,W2,H2)


#COMPARISONS: ORIGINAL VS RESULTS
#......................................................................................................................................................................
resultS1= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result1,"autolevels, autowhite",size=28,align=2))
resultS2= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result2,"autowhite",size=28,align=2))
resultS3= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result3,"autolevels",size=28,align=2))
resultS4= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result4,"no level or color corrections",size=28,align=2))

Eval(result)


# END SCRIPT, BEGIN FUNCTIONS

johnmeyer
13th September 2017, 23:39
#=================================================================================================================================


#REMOVE DIRT FUNCTION
#......................................................................................................................................................................
function RemoveDirt(clip input, int "limit", bool "_grey")
{
clensed=input.Clense(grey=_grey, cache=4)
alt=input.RemoveGrain(2)
return RestoreMotionBlocks(clensed,input,alternative=alt,pthreshold=6,cthreshold=8, gmthreshold=40,dist=3,dmode=2,debug=false,noise=limit,noisy=4, grey=_grey)

# Alternative settings
# return RestoreMotionBlocks(clensed,input,alternative=alt,pthreshold=4,cthreshold=6, gmthreshold=40,dist=1,dmode=2,debug=false,noise=limit,noisy=12,grey=_grey,show=true)
# return RestoreMotionBlocks(clensed,input,alternative=alt,pthreshold=6,cthreshold=8, gmthreshold=40,dist=3,tolerance= 12,dmode=2,debug=false,noise=limit,noisy=12,grey=_grey,show=false)
}

function RemoveDirtMC(clip,int "limit", bool "_grey")
{
_grey=default(_grey, false)
limit = default(limit,6)

# Alternative way to do pre-filtering.
# prefiltered = fft3dfilter(clip,sigma=1,sigma2=2,sigma3=3,sigma4=5,bw=64,bh=64)

prefiltered = RemoveGrain(clip,2)
superfilt = MSuper(prefiltered, hpad=32, vpad=32,pel=2)

super=MSuper(clip, hpad=32, vpad=32,pel=2)

bvec = MAnalyse(superfilt,isb=true, blksize=16, overlap=2,delta=1, truemotion=true)
fvec = MAnalyse(superfilt,isb=false, blksize=16, overlap=2,delta=1, truemotion=true)

# Increase thSAD if moving objects are being removed
bvec_re = Mrecalculate(super,bvec,blksize=8, overlap=0,thSAD=100)
fvec_re = Mrecalculate(super,fvec,blksize=8, overlap=0,thSAD=100)

backw = MFlow(clip,super,bvec_re)
forw = MFlow(clip,super,fvec_re)

clp=interleave(forw,clip,backw)
clp=clp.RemoveDirt(limit,_grey)
clp=clp.SelectEvery(3,1)
return clp
}

#This function is the previous way to do motion estimation. It is slower and not as accurate.
function RemoveDirtMC_old(clip,int limit, bool "_grey")
{
_grey=default(_grey, false)
limit = default(limit,6)
i=MSuper(clip,pel=2)
fvec = MAnalyse(i,isb=false, blksize=16, delta=1, truemotion=true)
bvec = MAnalyse(i,isb=true, blksize=16, delta=1, truemotion=true)
backw = MFlow(clip,i,bvec)
forw = MFlow(clip,i,fvec)
clp=interleave(forw,clip,backw)
clp=clp.RemoveDirt(limit,_grey)
clp=clp.SelectEvery(3,1)
return clp
}

# This function will remove near duplicates ("0.1") or exact duplicates (change to "0.0"). It replaces these
# duplicates with a motion estimated frame.
# Use: In your video editor, replace any single bad frame (burned frame, jump, missing frame from splice, etc.) with a duplicate of the
# previous frame. Then, include a call to this function

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
}


function SmoothFPS2(clip source, threads) {
super_params="{pel:2,gpu:1}"
analyse_params="""{
block:{w:16,h:16},
main:{search:{coarse:{distance:-10}}},
refine:[{thsad:200}]
}"""
smoothfps_params="{rate:{num:30,den:16,abs:false},scene:{mode:0,limits:{scene:8500}},algo:21,cubic:1}"
threads = 4

super = SVSuper(source,super_params)
vectors = SVAnalyse(super, analyse_params)
SVSmoothFps(source,super, vectors, smoothfps_params, url="www.svp-team.com", mt=threads)

# Alternative for interlaced output
# SVSmoothFps(source,super, vectors, smoothfps_params, url="www.svp-team.com", mt=threads).SeparateFields().SelectEvery(4, 0, 3).Weave().assumefps(29.97)
}

StainlessS
14th September 2017, 01:03
John, scale = 2 (EDIT with Th=0) , in GamMac WILL see all pixels (even a single) as affecting min/max, avoid noise pixels by eg denoise on DC clip,
with a perfect source that may be what you want, with less than prefect, needs more effort.

@ Lem, GamMac never was intended to be any kind of one suit fits all, merely a pre tweak easy get in sync type of thing.
If we all had Lem at our sides, GamMac would be of little worth.
John, seek Lem's counsil, he seems to be the man :)

bassquake
14th September 2017, 23:08
I have a question regarding settings frame rate, as I did a quick search through this thread but couldnt find the info.

I've built a telecine to capture standard 8 and super 8 into separate images. I assume they were shot at 18fps and would like to create 24fps videos (true 24p). The comments in the script file confuses me when it mention 18.75fps. So do I set it like so (need to change denumerator?):

play_speed= 18.75
numerator= 24
denumerator= 1

or

play_speed= 18
numerator= 24
denumerator= 1

Help appreciated, thanks.

johnmeyer
15th September 2017, 03:32
"Play speed" is the speed that you think the original was played (e.g., 18 fps for Super 8).

I recommend doing standard pulldown rather than any sort of motion estimation. Despite heroic efforts to improve motion estimation, it fails way too many times and will give you a mountain of weird-looking frames. I am in the process now of doing four separate restorations of the same material. Two of the 2x2 matrix variations involve using, or not using GamMac, because it fails to do the right thing quite often. The other two variations involve generating an alternate to motion estimation which I used, not to change frame rate, but to fix hundreds of screwed-up frames. In 90% of the cases, the fix was near-perfect but, as is always true with ME, when it fails, it fails spectacularly and calls attention to itself. So, I am doing another set of GamMac and no GamMac with an alternative to ME that doesn't look as good, but never fails.

You can adapt this code to create pulldown for whatever you are doing:

#18p -> 60i

avisource("video.avi")
assumefps(18)
changefps(59.94)
separatefields()
selectevery(4,0,3) #depends on wished field-order
#selectevery(4,1,2) #alternate field order
weave()

manono
15th September 2017, 07:56
...and would like to create 24fps videos (true 24p).
Mind if I ask 'why'? Is it for DVD perhaps? Offhand I can't think of any other reason it has to be 24fps.

johnmeyer
15th September 2017, 08:33
After seeing manono's comment, I re-read his post, and he emphasized "true" 24p. I guess I need clarification of what that means. Forgetting for a moment about the 23.976 vs. 24.000 thing, if he really wants 24 unique frames each second, then motion interpolation is the only choice. That is built into both VideoFred's script, and in my adaptation of his script. I don't recommend it, however, because even if you use the masked version of Interframe that was recently developed, you'll still end up with a LOT of bad frames. The lower the frame rate (and 16 or 18 fps is pretty low), the bigger the temporal gap between frames, and the larger and more frequent these errors become. Motion estimation works really well on 60p material (for when you want to get super-slo-mo) because it doesn't have to move the pixels very far to make the tween frames, but it doesn't work that well on amateur silent film. I've posted the link to my Flint, MI parade many times which I converted from 16 to 30p before I uploaded, and it is a textbook case of what can go wrong.

So, if you want true 24p, ME is the only tool that I know of that will give you what you want, and the code is already posted in this thread.

bassquake
15th September 2017, 11:17
I want to output to bluray but I suppose I can use 23.976 if that's easier?

So would the code then be?:

play_speed= 18.75
numerator= 23.976
denumerator= 1001

Thanks for responses so far.

johnmeyer
15th September 2017, 23:05
I want to output to bluray but I suppose I can use 23.976 if that's easier?

So would the code then be?:

play_speed= 18.75
numerator= 23.976
denumerator= 1001

Thanks for responses so far.No, that is wrong. 23.976 = 24.000 / 1001.0 (make sure to use the decimal to force float)

But, as I said in my previous post, that is a relatively minor issue compared to the bigger point I was trying to make, and which I won't repeat again here.

[edit]Groucho2004 points out my error (a few posts below this one). I put the decimal in wrong place. I was only off by a factor of 1,000.
The correct equations are: 24.000 / 1.001 or 24000.0 / 1001.0

StainlessS
16th September 2017, 02:42
John dont overlook the DC clip, even a simple Blur() can avoid some of the flickering effect (so long as only spurious odd pixels are cause of flicker, shimmering water though would probably not benefit).

manono
16th September 2017, 04:32
Yes, interpolation to go from 18->24fps, but if that doesn't work out so well for the reasons johnmeyer outlined, there is another way that creates blended frames to fill in the gaps. The Motion.dll (http://web.archive.org/web/20060103143553/http://people.pwf.cam.ac.uk/mg262/posts/Motion/motion.html#MotionFPS), can do this to, for example, create 6 new frames every second (a new one after every 3) to go from 18->24fps. Each new frame will be a blend of the ones before and after. Ordinarily I don't like creating blended frames on purpose since I spend my life unblending frames but it might do here.

The reason for my question earlier was, if making a DVD is okay, you only have to bring the framerate up to 19.98fps and you can apply 3:3 pulldown afterwards to output the required 29.97fps. That way you'd have to create only a new frame after every 9, rather than after every 3. Only 10% of the frames would be interpolated. I've never worked with Blu-Ray and have no idea if soft pulldown is allowed.

Groucho2004
16th September 2017, 21:06
No, that is wrong. 23.976 = 24.000 / 1001.0 (make sure to use the decimal to force float)
That's also wrong. 23.976 = 24000 / 1001 (or 24000.0 / 1001.0).

ChangeFPS() takes either a float (23.976) or two integers (24000, 1001), see here (http://avisynth.nl/index.php/ChangeFPS). In order to avoid rounding errors it's recommended to use the (num, denom) format.

johnmeyer
16th September 2017, 22:59
That's also wrong. 23.976 = 24000 / 1001 (or 24000.0 / 1001.0).

ChangeFPS() takes either a float (23.976) or two integers (24000, 1001), see here (http://avisynth.nl/index.php/ChangeFPS). In order to avoid rounding errors it's recommended to use the (num, denum) format.Oops. You got me! That'll teach me to post too quickly. I forgot a decimal point.

bassquake
3rd February 2018, 00:01
Hi. Is it possible to edit the avisynth script to use an image sequence rather than an avi file?

Thanks.

Edit: I ask because I'm not using a machine camera to output to an avi but am using a camera thats taking separate images. Rendering it to a huffy avi takes 2 hrs to do for a 2 minute film!

manono
3rd February 2018, 00:22
Yes, you'd use ImageSource (http://avisynth.nl/index.php/ImageSource). I haven't read the script, but you might also have to change the colorspace. Others will know better than I.

johnmeyer
3rd February 2018, 01:05
... and, of course, you can always assemble the image sequence into an AVI prior to feeding it to the script. Pretty much any NLE can do that, as can Virtualdub.

Yanak
3rd February 2018, 16:28
... and, of course, you can always assemble the image sequence into an AVI prior to feeding it to the script. Pretty much any NLE can do that, as can Virtualdub.

Using the built in frame-server option of Virtualdub to feed avisynth directly and skip the need to write an .avi is a good option too yes ^^

bassquake
3rd February 2018, 21:42
... and, of course, you can always assemble the image sequence into an AVI prior to feeding it to the script. Pretty much any NLE can do that, as can Virtualdub.

That's how I was doing it beforehand but it takes too long to render!

bassquake
5th February 2018, 23:02
Yes, you'd use ImageSource (http://avisynth.nl/index.php/ImageSource). I haven't read the script, but you might also have to change the colorspace. Others will know better than I.

Coolio, I got it working. Here's how to use an image sequence instead of avi:

Replace:

film= "C:\Users\You\Documents\Yourfile.avi" # source clip, you must specify the full path here

with:

film= "C:\Users\You\Documents\Images\SAM_%04d.jpg" #source clip, you must specify the full path here
start= 1 #Start frame
end= 3574 #Total number of frames

The %04d in the filename is the numbering padding used in the images. Mine is SAM_0001.jpg and never goes higher than 4 digits.

You need to tell it what frame it starts and ends with. Eg: Sequence is SAM_0003.jpg to SAM_0499.jpg then the start is 3 and end is 0499.

Also, replace the line:

source1= AviSource(film).assumefps(play_speed).trim(trim_begin,0).converttoYV12()

with:

source1= ImageSource(film, start, end).assumefps(play_speed).trim(trim_begin,0).converttoYV12().flipvertical()

Thats it. Can now load image sequences directly without having to render a lossless avi or similar to edit.

Note: I added flip vertical to the source1 line as my images are all upside down.

Hope that helps someone.

camelopardis
10th February 2018, 18:34
Hello all.

I'm very new to AVISynth, having just started trying to digitize my families old 8mm/Super8 films dating back to the 1950s.

I've bought a Reflecta Film Scanner super8/Normal8 (similar to the Somikon and Wolverine) and currently just experimenting, trying to learn the best way to scan and the best way to post-process.

Even though I realise the fantastic Videofred / John Meyer scripts on here are for the output of far superior scanning methods, I thought I'd give them a try.

I have a little test clip here (https://vimeo.com/255183448) showing a side-by-side result.

Input= Super 8 Reflecta scan at -1.0 exposure (scans as 1440x1080 30fps H.264 MP4)

converted to 18fps AVI using AVC2AVI

Output= latest 2012 VideoFred Script (default parameters)

I'm completely new to this but can see the output doesnt look right. I suspect the original scan is too heavily compressed?

Does anyone have any tips or suggestions? Should I use different parameters in the script - or a different method altogether?

Thank you - all or any advice most welcome :)

johnmeyer
10th February 2018, 22:44
It was tough for me to tell much from the Vimeo post. It actually looked pretty good.

I am not familiar with the Reflecta units, but a quick trip to their site makes it look like they must be frame accurate, meaning you get precisely one from of film on each frame of video. That is a requirement for using VideoFred's script.

I see you are storing the original scans using H.264. That is obviously a compressed format. You didn't provide any information about what settings you used. This is important because any video format that uses compression can use only a little compression (big files) or a LOT of compression (small files). The more the compression, the worse artifacts you will get. So, if artifacts are the problem, then look for a setting in your capture software that lets you use less compression. You can always compress the files when you are finished, in order that your final result doesn't require a huge array of disks to hold the final result. So, do the compression as the final step, if you need it, and not when you do the original capture.

You mention you are using a script dated 2012, but I thought VideoFred had posted something more recently than that. He has made some amazing advances over the past few years, some of which I still need to steal, er, incorporate into my own work, especially StainlessS' GamMac filter, which I still can't get to work reliably, but which shows great promise.

If you can upload a 10-second clip of one of your original transfers, without re-encoding, that will make it a lot easier to see what is going on.

camelopardis
11th February 2018, 17:28
It was tough for me to tell much from the Vimeo post. It actually looked pretty good.

I am not familiar with the Reflecta units, but a quick trip to their site makes it look like they must be frame accurate, meaning you get precisely one from of film on each frame of video. That is a requirement for using VideoFred's script.

I see you are storing the original scans using H.264. That is obviously a compressed format. You didn't provide any information about what settings you used. This is important because any video format that uses compression can use only a little compression (big files) or a LOT of compression (small files). The more the compression, the worse artifacts you will get. So, if artifacts are the problem, then look for a setting in your capture software that lets you use less compression. You can always compress the files when you are finished, in order that your final result doesn't require a huge array of disks to hold the final result. So, do the compression as the final step, if you need it, and not when you do the original capture.

You mention you are using a script dated 2012, but I thought VideoFred had posted something more recently than that. He has made some amazing advances over the past few years, some of which I still need to steal, er, incorporate into my own work, especially StainlessS' GamMac filter, which I still can't get to work reliably, but which shows great promise.

If you can upload a 10-second clip of one of your original transfers, without re-encoding, that will make it a lot easier to see what is going on.

Hi John - thank you very much for your reply!

yes - the Reflecta does scan frame-by-frame but unfortunately it can only save the result as a highly compressed MP4 file (this is the main complaint of most users).

Here is a longer clip of the raw 1440x1080 output from the machine (you can't change the compression ratio, you can only adjust exposure, sharpness, and frame adjustment).
I order to use with AVISynth, the above clip was changed from MP4 to AVI by first extracting the raw h.264 using "My MP4Box" and then converting to AVI using AVC2AVI. If any of this is silly or wrong please let me know. I'm learning as I go along and am more than happy to be corrected!

Raw Clip (https://vimeo.com/255255086)

Here is the same clip showing the output from Videofred's script. I used the latest 01_A script (posted on the first page of this thread (dated 20/06/2012). Is there a later one I should be using?

VideoFred output (https://vimeo.com/255263444)

Here is the actual script used:
# 8mm film restoration script by videoFred.
# www.super-8.be
# info@super-8.be

# version 01.A with frame interpolation
# release date: june 20, 2012
#============================================================================================

# august 2010: added removerdirtMC() as suggested by John Meyer
# october 2010: auto sharpening parameters

# march 2011: new autolevels.dll by Jim Battle
# www.thebattles.net/video/autolevels.html

# june 2012: improved stabilisation


#=============================================================================================

# cleaning, degraining, resizing, stabilizing, sharpening, auto-levels and auto-white balance.
#=============================================================================================


film= "C:\Users\You\Documents\Yourfile.avi" # source clip, you must specify the full path here






#PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
result="resultS1" # specify the wanted output here

trim_begin=2 trim_end=10 play_speed=18 #trim frames and play speed (PAL: 16.6666 or 18.75)

numerator= 25 #numerator for the interpolator (final frame rate)
denumerator= 1 #denumerator example: 60000/1001= 59.94fps


#COLOR AND LEVELS PARAMATERS
#----------------------------------------------------------------------------------------------------------------------------
saturation=1.2 #for all outputs

gamma= 1.2 # for all outputs

blue= 0 red= 0 #manual color adjustment, when returning result3 or result4. Values can be positive or negative


black_level=0 white_level=255 output_black=0 output_white=255 # manual levels, when returning result4


#AUTO LEVELS PARAMETERS
#--------------------------------------------------------------------------------------------------------------------------------

autolev_low= 6 # limit of autolevels low output
autolev_high= 235 # limit of autolevels high output



#SIZE, CROP AND BORDERS PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
CLeft=32 CTop=32 CRight=32 CBottom=32 #crop values after Depan and before final resizing

W=720 H=576 #final size after cropping

bord_left=0 bord_top=0 bord_right=0 bord_bot=0 #720p= borders 150


#STABILISING PARAMETERS, YOU REALY MUST USE RESULTS7 TO CHECK STABILISATION!
#----------------------------------------------------------------------------------------------------------------------------
maxstabH=20
maxstabV=20 #maximum values for the stabiliser (in pixels) 20 is a good start value

est_left=20 est_top=60 est_right=60 est_bottom=60 #crop values for special Estimate clip

trust_value= 1.0 # scene change detection, higher= more sensitive
cutoff_value= 0.5 # no need to change this, but you can play with it and see what you get





#CLEANING PARAMETERS
#--------------------------------------------------------------------------------------------------------------

dirt_strenght=30 # set this lower for clean films.


#DENOISING PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------


denoising_strenght= 300 #denoising level of second denoiser: MVDegrainMulti()
denoising_frames= 3 #number of frames for averaging (forwards and backwards) 3 is a good start value
block_size= 16 #block size of MVDegrainMulti()
block_size_v= 16
block_over= 8 #block overlapping of MVDegrainMulti()




# SHARPENING PARAMETERS
#--------------------------------------------------------------------------------------------------------------------------------

USM_sharp_ness= 40 USM_radi_us=3 #this is the start value for the unsharpmask sharpening
#do not set radius less then 3
#the script will automatically add two other steps with lower radius



last_sharp= 0.1 #final sharpening step after interpolation

last_blur= 0.2 #this smooths out the heavy sharpening effects





# END VARIABLES, BEGIN SCRIPT
#=================================================================================================================================


SetMemoryMax(800) #set this to 1/3 of the available memory




LoadPlugin("plugins/Deflicker.dll")
Loadplugin("plugins/Depan.dll")
LoadPlugin("plugins/DepanEstimate.dll")
Loadplugin("plugins/removegrain.dll")
LoadPlugin("plugins/removedirt.dll")
LoadPlugin("plugins/MVTools.dll")
LoadPlugin("plugins/MVTools2.dll")
Loadplugin("plugins/warpsharp.dll")
LoadPlugin("plugins/autolevels_06.dll")
Import("plugins/03_RemoveDirtMC.avs")






source= AviSource(film).assumefps(play_speed).trim(trim_begin,0).converttoYV12()
trimming= framecount(source)-trim_end
source1= trim(source,0,trimming)






#STABILIZING/CROPPING
#...........................................................................................................................................

stab_reference= source1.crop(20,20,-20,-20).colorYUV(autogain=true).crop(est_left,est_top,-est_right,-est_bottom)

mdata=DePanEstimate(stab_reference,trust=trust_value,dxmax=maxstabH,dymax=maxstabV)
stab=DePanStabilize(source1,data=mdata,cutoff=cutoff_value,dxmax=maxstabH,dymax=maxstabV,method=0,mirror=15).deflicker()
stab2= stab.crop(CLeft,CTop,-CRight,-CBottom)
stab3=DePanStabilize(source1,data=mdata,cutoff=cutoff_value,dxmax=maxstabH,dymax=maxstabV,method=0,info=true)


WS= width(stab)
HS= height(stab)
stab4= stab3.addborders(10,10,10,10,$B1B1B1).Lanczos4Resize(WS,HS)
stab5= Lanczos4Resize(stab2,W,H).sharpen(0.5)


#UNSHARPMASK AUTO_PARAMETERS
#-------------------------------------------------------------------------------------------------------------------------------------------

USM_sharp_ness1 = USM_sharp_ness
USM_sharp_ness2 = USM_sharp_ness+(USM_sharp_ness/2)
USM_sharp_ness3 = USM_sharp_ness*2

USM_radi_us1 = USM_radi_us
USM_radi_us2 = USM_radi_us-1
USM_radi_us3 = USM_radi_us2-1


#CLEANING/PRESHARPENING/RESIZING
#..........................................................................................................................................


noise_baseclip= stab2.levels(0,gamma,255,0,255).tweak(sat=saturation)




cleaned= RemoveDirtMC(noise_baseclip,dirt_strenght).unsharpmask(USM_sharp_ness1,USM_radi_us1,0)\
.unsharpmask(USM_sharp_ness2,USM_radi_us2,0).Lanczos4Resize(W,H)



#DEGRAINING/SHARPENING
#...................................................................................................................................................................


vectors= cleaned.MVAnalyseMulti(refframes=denoising_frames, pel=2, blksize=block_size, blksizev= block_size_v, overlap=block_over, idx=1)
denoised= cleaned.MVDegrainMulti(vectors, thSAD=denoising_strenght, SadMode=1, idx=2).unsharpmask(USM_sharp_ness3,USM_radi_us3,0)






#CHANGING FRAME RATE WITH INTERPOLATION/FINALSHARPENING
#............................................................................................................................................................

super= denoised.MSuper()
backward_vec= MAnalyse(super, blksize=block_size, blksizev= block_size_v, overlap=block_over, isb=true)
forward_vec= MAnalyse(super,blksize=block_size, blksizev= block_size_v, overlap=block_over, isb= false)

interpolated= denoised.MFlowFps(super, backward_vec, forward_vec, num=numerator, den= denumerator, ml=100)\
.sharpen(last_sharp,mmx=false).sharpen(last_sharp,mmx=false).blur(last_blur,mmx=false)


#RESULT1: AUTOLEVELS,AUTOWHITE
#......................................................................................................................................................................
result1= interpolated.converttoRGB24().autolevels(output_low= autolev_low, output_high= autolev_high)\
.converttoYV12().coloryuv(autowhite=true).addborders(bord_left, bord_top, bord_right, bord_bot)

#RESULT2: MANUAL LEVELS, AUTOWHITE
#......................................................................................................................................................................
result2= interpolated.levels(black_level,1.0,white_level,0,255).coloryuv(autowhite=true)\
.addborders(bord_left, bord_top, bord_right, bord_bot)

#RESULT3: AUTOLEVELS, MANUAL COLOR CORRECTIONS
#.....................................................................................................................................................................
result3= interpolated.coloryuv(off_U=blue,off_V=red).converttoRGB24().autolevels(output_low= autolev_low, output_high= autolev_high)\
.converttoYV12().addborders(bord_left, bord_top, bord_right, bord_bot)

#RESULT4: MANUAL LEVELS, MANUAL COLOR CORRECTIONS
#.....................................................................................................................................................................
result4= interpolated.coloryuv(off_U=blue,off_V=red).levels(black_level,1.0,white_level,0,255)\
.addborders(bord_left, bord_top, bord_right, bord_bot)

#RESULT5: SPECIAL SERVICE CLIP FOR RESULT S5
#.....................................................................................................................................................................
result5= overlay(source1,greyscale(stab_reference),x=est_left,y=est_top).addborders(2,2,2,2,$FFFFFF).Lanczos4Resize(WS,HS)




#PARAMETERS FOR THE COMPARISONS
#.....................................................................................................................................................................
W2= W+bord_left+bord_right
H2= H+bord_top+bord_bot




final_framerate= numerator/denumerator
source4=Lanczos4Resize(source1,W2,H2).changeFPS(final_framerate)



#COMPARISONS: ORIGINAL VS RESULTS
#......................................................................................................................................................................
resultS1= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result1,"result1: autolevels, autowhite",size=28,align=2))
resultS2= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result2,"result2: autowhite, manual levels correction",size=28,align=2))
resultS3= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result3,"result3: autolevels, manual color correction",size=28,align=2))
resultS4= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result4,"result4: manual colors and levels correction",size=28,align=2))
resultS5= stackhorizontal(subtitle(result3,"result3: auto levels, manual color correction",size=28,align=2),subtitle(result4,"result4: manual colors and levels correction",size=28,align=2))
resultS6= stackhorizontal(subtitle(result1,"result1: autolevels, autowhite",size=28,align=2),subtitle(result2,"result2: manual levels, autowhite",size=28,align=2))

#SPECIAL COMPARISON CLIP FOR TESTING THE STABILIZER
#.........................................................................................................................................................................
resultS7= stackhorizontal(subtitle(result5,"baseclip for stabiliser -only the B/W clip is used",size=32,align=2),\
subtitle(stab4,"test stabiliser: dx=horizontal, dy=vertical",size=32,align=5)).converttoYUY2()




Eval(result)#.converttoRGB24()







The only I thing I changed in the above script (apart from sourcefile) was W=720 H=576 which I changed to W=720 H=540. This was because the aspect ratio looked wrong (people fatter) with 576, so I changed it to be exactly half of the original 1440x1080 ratio. I'll admit I am quite confused here as to what I should be doing regards output size!

I notice the output files from VirtualDub are quite huge (uncompressed RGB) - should I be changing to x264vfw-h.264? Also, if I do change output compression to x264vfw, am I right in thinking that I should also then change from "full processing mode" to "fast recompress" in VirtualDub?

I also still need to crop the borders properly!

johnmeyer
11th February 2018, 18:50
It sounds like you are doing everything right. I don't have any help to offer, other than to say that you need to find some way to store the original capture in something other than h.264, or at least find a way to change the compression setting used. It would be pretty strange if they completely hard-wired this setting. There must be a hack, .ini file, registry setting, or some other way to make these changes.

There are cropping options in VideoFred's script, and you can change those. I haven't looked at his script much since I branched off in my own direction, but I'm pretty sure his script crops and then re-sizes to whatever final size you have specified. Thus, you should be able to increase the crop at the top (that's where I saw the overhang from the previous frame). BTW, a better thing to do is adjust the framing control on the capture device so that the top and bottom frame border is roughly equal. Hopefully your transfer machine has such an adjustment.

camelopardis
12th February 2018, 22:58
thanks very much John. It is a shame about a compression but at least I'm getting them done after so many years. I think its better the film subjects that are still alive get to see them even if sub-par rather than not at all. I'll be keeping all the film so I can always get them re-done with better equipment at a later date.

poisondeathray
12th February 2018, 23:06
I order to use with AVISynth, the above clip was changed from MP4 to AVI by first extracting the raw h.264 using "My MP4Box" and then converting to AVI using AVC2AVI. If any of this is silly or wrong please let me know. I'm learning as I go along and am more than happy to be corrected!


You can use lsmash or ffms2 to open the MP4 directly . Both are external plugins separate from the main avisynth install.
e.g

LSmashVideoSource("video.mp4")

JoeSuper8
13th February 2018, 01:57
Hi Joe,

Welcome here :)

First of all, please try to capture as good as possible. Later, we can talk about Gammac etc....

About the Jpeg image sequence: you have not captured the full 0-255 range. It's more like 0-125. You have set red auto and blue auto off. Why? One of the great benefits of C2D is the exellent auto exposure feature. If you set the limit to 245 you will almost never get blown out whites.

Sharpness can be better also. Have you tried to find the 'sweet spot' from your lens? Every lens has a sweet spot. Easy to check: in C2D, use internal flashing and play with the lens aperture. At a certain point the image will look sharpest. This is your sweet spot. Leave it there forever. :) Then you can fine focus with your camera slide.

Also, there is no need to save as image sequence. I always save straight to AVI, at 15fps! I'm using the Canopus HQX codec for this but Lagarith etc.. will work fine too. Uncompressed is also an option but it creates huge files and why would we do it.. You will see no visual difference.

About the speed from the script: downscaling the source will speed up the script a lot. You can upscale again at the very end of the script.
https://forum.doom9.org/showthread.php?p=1810955#post1810955

many greetings,
Fred.

Thanks Fred and johnmeyer for your ideas - sorry I haven't been able to get to testing sooner. I noticed no significant change in Cine2Digits when I turned the Camera Settings - Analog - White Balance Blue and Red to Continuous instead of manual and left the other settings as described in my 8/22/17 post (the Cine2Digits manual suggested manual values for the camera white balance because the C2D program itself auto-adjusts the colors through its LED control). In both my attempt over the summer and my try this week, the C2D program LED control is set to auto.

I tried turning down the RGB dials from 1.47 to 1 but that did not affect overexposure. I also tried changing the pixel format (BayerRG8,16, YCBCR, RGB8) but that did not change the highlights.

I tried adjusting RGB gamma below 1 in C2D but the highlights did not seem to recover. Could the highlights be overexposed on the original film? Or another setting that's not right?

Fred as you suggested I adjusted my white level targets for Red, Green, and Blue to 245 in the "Exposure Options" C2D menu. I set auto exposure sensitiveity "Over" to 350 and Under to 650 (I did not notice a difference changing these values much lower and much higher).

I am still not sure how the range is closer to 0-125 in my capture.

johnmeyer and Fred I will look into the script issues and downsizing after fixing the highlights issue to achieve something closer to 0-255. Any settings I could be incorrectly setting somewhere?

Here is a video showing the C2D settings and gamma adjustments - please let me know if I might want to change anything in addition to AVI capture instead of TIFF:
https://player.vimeo.com/video/255482660

videoFred
13th February 2018, 11:22
Hi Joe,

It's a matter of settings, both camera settings and C2D settings.
Also, be sure that the ROI for the picture analysis is inside the black borders. Otherwise you wil get false results.

Fred.

videoFred
13th February 2018, 11:36
Here is a longer clip of the raw 1440x1080 output from the machine (you can't change the compression ratio, you can only adjust exposure, sharpness, and frame adjustment).

Hello Camelopardis,

We can not download this Vimeo clip. We need a "downloadable" clip :)

Also, do not use any camera sharpness (or other) settings. It is much better to do sharpening in post.

Fred.

camelopardis
16th February 2018, 01:04
Hello Camelopardis,

We can not download this Vimeo clip. We need a "downloadable" clip :)

Also, do not use any camera sharpness (or other) settings. It is much better to do sharpening in post.

Fred.

Hi Fred,

I've uploaded a raw output clip to my onedrive:
https://1drv.ms/v/s!Arqwxcq4sXstsA7drZ7CuhCNAQYD

The machine has 3 sharpness settings: low, medium, and high. You cant turn it completely off. I've set it to low.

poisondeathray
16th February 2018, 01:27
@camelopardis - why is it 23.976 fps AVI with blends ? Is it a 1:1 scanner ? I thought it recorded MP4 ? You mentioned 18FPS and 30FPS, but this clip 23.976 . Or does it scan at a fixed 30FPS rate without adjustments or variable speed ? I'm wondering at what stage are the blends being introduced

Are there options to bump up the bitrate on the machine or in software ? If that's 1st generation, there is significant quality loss from the compression. 7Mb/s for 1440x1080 isn't very much, even for final delivery formats let alone 1st gen transfer.

johnmeyer
16th February 2018, 02:09
Thanks for the upload.

Is this the unmodified, original video as it came directly from the Reflecta unit, or have you already done something to it, either with an AVISynth script, or something else? I ask this because what you posted is an awful mess and cannot possibly be used inside of VideoFred's script (or any other script designed to improve the transfer).

The problem is that you have blended fields. This is something you always see with a cheap transfer, where the person just points the video camera at the movie screen. However, I wouldn't think you would get it with a transfer unit that is frame accurate, which I thought was the case with the Reflecta.

So, unless you can upload something better, the short answer is that you cannot use VideoFred's script, or any other AVISynth script, because your movie frames are made up of blended fields.

JoeSuper8
16th February 2018, 06:43
Hi Joe,

It's a matter of settings, both camera settings and C2D settings.
Also, be sure that the ROI for the picture analysis is inside the black borders. Otherwise you wil get false results.

Fred.

Yep Fred I have set the ROI inside the Super 8 frame with room to spare, like in part 2 of your tutorial video.

As you saw in the link from my previous post, my histogram is very weak during the test capture (not much red, green, and blue area) whereas your tutorial shows significantly more R, G, and B in the C2D live histogram.

I have attempted to adjust the C2D and camera settings but I am still getting the same results.

Would you mind taking a look at the screen capture video link from my last post to see where I might want to change any settings to improve the histogram and range of capture?

videoFred
16th February 2018, 19:08
Would you mind taking a look at the screen capture video link from my last post to see where I might want to change any settings to improve the histogram and range of capture?

Every machine vision camera type has a different settings menu. In your case: I would try "black level". But even better: try them all and see what you get.

In C2D your gamma settings are to low.

And please try it on different films and/or other scenes too.

Fred.

camelopardis
17th February 2018, 13:19
Hi all.

My apologies! I realise now that wasnt the unmodified output from the Reflecta unit becuase I cut it into a short clip for upload in Sony Vegas (where it was then rendered as mpeg4 output.)

This time I uploaded a short clip DIRECT from the machine. This is the MP4 file it writes directly to the SDcard. I've done nothing to it and left it as the original 1440x1080 30fps MP4 file that the machine writes. (you cant change this output) I havent corrected the frame rate.

https://1drv.ms/v/s!Arqwxcq4sXstsA9RBsfWbucoH0By

clivesay
2nd April 2018, 23:30
Hey everyone. I joined this forum just for this thread!

Long story short, at the first of the year I learned I have a sister that no one (including my father) knew anything about. My dad has been gone for over 25yrs. Some slides that I never seen before that were tucked away in a closet helped to unlock some of the mystery.

This now has me on a mission. I bought a good scanner to get good copies of my dad's slides and then was informed my grandparent had some 8mm reels that needed to be digitized. So, I jumped in and bought a wolverine moviemaker-pro and have jumped into 8mm film restoration. I have the scripts from here up and running and have been tinkering with them.

First question: Some of you people here have an incredible amount of experience in film restoration. How does someone like myself gain enough knowledge to do some basic but effective editing? The scripts make a difference on some of my test clips but I have no idea what parameters to tweak to refine some of the results. Is there a good tutorial somewhere? Do I post clips here and some of you can give me some pointers?

I am all about learning and not afraid to get my hands dirty.

Would appreciate any guidance.

Oh, if anyone is interested in my experience with my sister you can google "Crawfordsville DNA" and see our story that was broadcast on the news.

Thank you.

`Orum
3rd April 2018, 02:52
First question: Some of you people here have an incredible amount of experience in film restoration. How does someone like myself gain enough knowledge to do some basic but effective editing?
I have never had the (dis)pleasure of having to restore analog footage, but I can tell you that there's no "one-size-fits-all" solution. That said his scripts are probably a good place to start.
The scripts make a difference on some of my test clips but I have no idea what parameters to tweak to refine some of the results. Is there a good tutorial somewhere? Do I post clips here and some of you can give me some pointers?
Posting clips will never hurt, and while we can give recommendations things are always best hand-tuned by the end user, as you know exactly what you want and we can only tune to what we think is best.
I am all about learning and not afraid to get my hands dirty.
Good! Sometimes the best way to learn what parameters to tune is by playing with them yourself. That said, when there's a lot of parameters to tune practiced hands can help, as they sometimes interact in important ways. There's also a lot to know about video (and a lot you probably don't need to know unless you are writing your own filters), but a good place to start is the wiki (http://avisynth.nl/index.php/Main_Page). There's a section right on the home page for getting started, but it sounds like you've already got the initial setup done.

Software like AvsPmod (https://forum.doom9.org/showthread.php?p=1801766#post1801766) can make things friendlier for those new to AviSynth and faster for those who are used to it, though it can be frustrating as it's far from "stable" and may crash on you (save your script frequently).

johnmeyer
3rd April 2018, 02:55
First, the slides. The best way to scan them is a Nikon Coolscan scanner. They don't make them anymore, but you can get them on eBay. You can sell it when you are finished in order to recoup the $1,000+ cost.

However, slide scanning is slow. It took me 3+ years to get through my dad's 10,000 slides.

I recently needed to scan 3,000 slides for a client whose dad is dying and wanted to see the slides one last time. So, I converted a Carousel projector into a very high-quality, extremely fast scanner. The results, when using my old Nikon D-70 as the capture device are probably 85-90% as good as the quality of my Nikon scanner, albeit without any automatic dirt or dust removal, although that only works well on Ektachrome and doesn't really do much with Kodachrome. The Nikon Coolscan takes about 1.5-2.0 minutes per scan. My Carousel/Digital Camera lashup can capture about 15-20 slides per minute. So, it is almost 40 times faster.

I can provide a few construction details on how to do this conversion in a way that gives you good results. You cannot simply point the projector at a screen and then snap the result with a digital camera. The result is absolutely awful. Instead, you point the camera directly at the Carousel lens, at point blank range. You have to use the correct lenses in both the projector and camera; dim the bulb; and add an additional diffuser in he projector's light path. It is actually quite easy to do, but figuring out which parts to use took me quite a bit of time and effort.

As for your other question, VideoFred put all the control variables for his script at the beginning. You just simply change them and then look at the result.

I created my own version of his script, which I optimized for speed, but with far less sharpening. My work involves mostly really old film and I find that my version's lower levels of sharpening and grain reduction give results which I find more pleasing when dealing with typical amateur film.

Here are the variables from my script. The comments are intended to tell you what they do. So, just get the script working and then start changing these variables. VideoFred's scripts work the same way.
#GENERAL PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
result="resultS1" #specify the wanted output here
trim_begin=0 play_speed=15 #trim frames and play speed (PAL: 16.6666 or 18.75)

#COLOR AND LEVELS PARAMATERS
#----------------------------------------------------------------------------------------------------------------------------
saturation=1.0 #for all outputs
gamma=1.0 #for all outputs
blue= -0 red=-0 #manual color adjustment, when returning result3 & result4. Values can be positive or negative
black_level=0 white_level=255 output_black=0 output_white=255 #manual levels, when returning result2 & result4


#SIZE, CROP AND BORDERS PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
CLeft=16 CTop=16 CRight=16 CBottom=16 #crop values after Depan and before final resizing
W=720 H=480 #final size after cropping
bord_left=0 bord_top=0 bord_right=0 bord_bot=0 #720p= borders 150
in_bord_left=0 in_bord_top=0 in_bord_right=0 in_bord_bot=0 #Borders around input that must be removed


#STABILISING PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
maxstabH=20 #maximum values for the stabiliser (in pixels) 20 is a good start value
maxstabV=20
est_left=40 est_top=40 est_right=40 est_bottom=40 est_cont=1.6 #crop and contast values for special Estimate clip


#DENOISING PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
denoising_strength=600 #denoising level of first denoiser: MVDegrain()
block_size= 16 #block size of MVDegrain
block_size_v= 16
block_over= 8 #block overlapping of MVDegrainMulti()
dirt_strength=23 #sets amount of dirt removal (big spots)
#dirt_strength=13 #sets amount of dirt removal (big spots)

#FOUR STEP SHARPENING PARAMETERS
#--------------------------------------------------------------------------------------------------------------------------------
PRE_sharp_ness= 120 PRE_radi_us= 3 #presharpening (UnsharpMask) just after first denoising
LSF_sharp_ness=160 LSF_radi_us=2 LSF_sub=1.5 #second sharpening parameters (LimitedSharpenFaster) sub=subsampling

#Alternative lower sharpening values
#PRE_sharp_ness= 120 PRE_radi_us= 3 #presharpening (UnsharpMask) just after first denoising
#LSF_sharp_ness=120 LSF_radi_us=2 LSF_sub=1.5 #second sharpening parameters (LimitedSharpenFaster) sub=subsampling


Sharp_Strength = 0.4


#AUTO LEVELS PARAMETER
#--------------------------------------------------------------------------------------------------------------------------------
X=4 #X is a special parameter for reducing the autolevels effect on the whites
X2=2 #X2 is a special parameter for reducing the autolevels effect on the blacks


# END VARIABLES, BEGIN SCRIPT

goodiesguy
25th July 2018, 16:09
What parts of VideoFred's script do I remove to stop the colour correction and auto gain/brightness?

I prefer to do this manually and my few attempts to stop the script from doing this have broken it.

johnmeyer
25th July 2018, 21:53
What parts of VideoFred's script do I remove to stop the colour correction and auto gain/brightness?

I prefer to do this manually and my few attempts to stop the script from doing this have broken it.You simply change the "result" parameter.

sys32768
2nd January 2019, 23:05
Was curious whether anyone had already done the work to modify Fred's original script here to use GAMMAC?

As an AVIsynth newbie, I find myself tripping up quite often and then starting over so I thought I'd ask.

johnmeyer
3rd January 2019, 04:52
I created my own branch of Fred's script and posted it many years ago. However, like Fred, I haven't tried to post all my changes and updates because I don't have time to support it when people ask questions.

With that as preface, here is what I am using. It is not really fit for publication (i.e., not many comments on the new stuff), and there are probably bugs all over the place. However, it works for me.

It will take two posts to get it all.

/*
Film restoration script by videoFred.
Denoising, resizing, stabilising, sharpening, auto-levels and auto-white balance.

Modified by John Meyer, October 7, 2012
Modified by John Meyer, July 7, 2015 (remove errors)
Modified by John Meyer, September 13, 2017

Changes made by Meyer (June 8, 2010):
1. Replaced the MVDegrainMulti function, which was part of the original MVTools
with the equivalent function using the newer and faster MVTools2.
2. Added RemoveDirt function prior to Degrain in order to eliminate large dust spots. This
substantially improves the dirt removal capabilities of this script. The user will need to
download this plugin at:
http://www.removedirt.de.tf/
3. Eliminated a great deal of sharpening. The original script did sharpening in at least four places.
With grainy film stock, this sometimes created objectionable grain. Also, the limitedSharpenFaster
function, while excellent for video, is uncessarily slow, and isn't really needed for this low
resolution source. Too much sharpening can make the film look too much like video.
4. Added multithreading. I was able to roughly triple the script performance. It may be possible to
substantially increase this, perhaps as much as 12x instead of 3x. However, the autolevels function
would have to be replaced.
5. Fixed several things I found. The result3 option didn't have the manual color correction code, so I
added that back in. All the numbered "stab" variables (stab1, stab2, etc.) aren't needed except
for providing a test function for stabilization. I eliminated all of this to streamline the script.
6. Deflicker seemed redundant, given all the averaging that takes place with MDegrain, and also the averaging
that is done when the autolevels outputs are selected.
7. I reduced the number of frames used for averaging autolevels from the default (which is 5) to 2.
I probably should add a variable in the header so the user can change this. Something else to do
in the future ...
8. I added yet another set of crop parameters. I did this because both my capture and my output are
done using NTSC DV AVI which is 720x480. However, 8mm film is almost exactly square, so the captured
720x480 video has black bars on the side. These need to be cropped off prior to doing motion
stabilization, but then added back prior to the final output, which must still be 720x480 with the
black bars on the side.
9. I reduced the default depan settings to 20, which is what was recommended in the original script. I
also reduced the post-depan cropping. I did this so I could keep as much of the original frame
as possible.
10. I removed the second denoising and sharpening function. It just seemed to be too much, and made the
result too artificial
11. I removed the MVFLowFPS interpolation. I did this during one of dozens and dozens of attempts
to improve the speed of the script. I should probably add this back, but if I do so, I also
need to make it work correctly for interlaced output. If the goal is to show this on an NTSC or PAL
television set, then it is not correct to convert from the film fps to 25 fps progressive (PAL) or
29.97 fps progressive (NTSC). Instead, this should be done as follows (example given is NTSC):

MFlowFPS(source,super,backward_vec, forward_vec, num=60000, den=1001,ml=200)
SeparateFields()
SelectEvery(4, 0, 3)
Weave()

This yields interlaced 29.97, which has twice the temporal resolution as 29.97 progressive, and will
therefore look correct on a TV set. I have done a lot of this as part of my Kinescope to video
conversion scripts. For those scripts, the goal is to make the filmed version of a TV show look
like it was actually videotaped. However, for something that originated on film, this "does violence"
to the original feel of the media. It is true that it can make horizontal pans less "juddery," but
it won't feel like film anymore. Also, this technique does break down, espcially with fast motion
in the foreground.
12. Removed the unecessary "coloryuv(off_U=blue,off_V=red)" statement from the denoising section.
13. Added killaudio() statement to prevent lockups when using SetMTMode().

Changes made on October 7, 2012

1. Modified RemoveDirtMC function to do estimation in two steps. This improves performance and quality.
2. Modified MDegrain to do estimation in two steps. This provides roughly the same quality with blocksize=8
as what I was getting with blocksize=4, but with virtually no performance penalty
3. Updated to use special build of MVTools2 that works with SVP.
4. Moved Autolevels inside special multi-threading section in order to improve performance with autolevels.
5. Removed all trim commands because I do all editing outside the script (in Vegas).
6. Included two alternative ways to do frame interpolation: SVP and InterFrame. The InterFrame script is probably better
but I included the SVP code because it may provide a starting point for more customized approaches. Neither is enabled by default.

Changes made on September 13, 2017

1. Replaced old useless color correction with GamMac.
2. Removed never-used manual controls.
3. Moved deflicker to end of chain because GamMac introduces flicker.
4. Moved RemoveDirtMC to happen AFTER denoising.
*/
#====================================================================================


#VIDEO FILE
#----------------------------------------------------------------------------------------------------------------------------
#Change the following line to point to your video file
film="e:\fs.avi"


#GENERAL PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
result="result2" #specify the wanted output here
play_speed=17.98201798 #play speed (8mm=16; Super8=18; 16mm sound=24)


#COLOR AND LEVELS PARAMATERS
#----------------------------------------------------------------------------------------------------------------------------
saturation = 1.0 #for all outputs
gamma = 1.0 #for all outputs

#GamMac Parameters
LockChan = 1 #(0=red channel)
LockVal = 128.0 #default 128 -- Used when LockChan = -1 (for flicker)
Scale = 2 #Fred recommended 2 instead of 1
RedMul = 1.0
GrnMul = 1.0
BluMul = 1.0
Th = 0.1
GMx = 0
GMy = 0
GMw = 0
GMh = 0
LOTH = 0.2
HITH = 0.2
OMIN = 0 #limiting the output a little bit makes it a little 'softer' to look at
OMAX = 255
Al2 = 20
autolev_bord1 = 50
borderV=10 borderH=10

#SIZE, CROP AND BORDERS PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
CLeft=8 CTop=8 CRight=8 CBottom=8 #crop values after Depan and before final resizing
W=720 H=480 #final size after cropping
bord_left=0 bord_top=0 bord_right=0 bord_bot=0 #720p= borders 150
in_bord_left=0 in_bord_top=0 in_bord_right=0 in_bord_bot=0 #Borders around input that must be removed

#STABILISING PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
maxstabH=10 #maximum values for the stabiliser (in pixels) 20 is a good start value
maxstabV=10
est_left=40 est_top=40 est_right=40 est_bottom=40 #crop and contast values for special Estimate clip
est_cont=1.1 #Too large a value defeats stabilization


#DENOISING PARAMETERS
#----------------------------------------------------------------------------------------------------------------------------
#denoising_strength=600 #denoising level of first denoiser: MVDegrain()
#block_size= 16 #block size of MVDegrain
#block_size_v= 16
#block_over= 8 #block overlapping of MVDegrainMulti()

#Alternate denoising using smaller block size
#denoising_strength= 600 #denoising level of first denoiser: MDegrain()
#block_size= 8 #block size of MVDegrain
#block_size_v= 8
#block_over= 4 #block overlapping of MVDegrainMulti()

#Alternate denoising using smalles block size
denoising_strength= 300 #denoising level of first denoiser: MDegrain()
block_size= 4 #block size of MVDegrain
block_size_v= 4
block_over= 2 #block overlapping of MVDegrainMulti()

dirt_strength=18 #sets amount of dirt removal (big spots)


#FOUR STEP SHARPENING PARAMETERS
#--------------------------------------------------------------------------------------------------------------------------------
#120 is pretty aggressive; 85 seems more subtle
#PRE_sharp_ness= 120 PRE_radi_us= 3 #presharpening (UnsharpMask) just after first denoising
PRE_sharp_ness= 85 PRE_radi_us= 3 #presharpening (UnsharpMask) just after first denoising

Sharp_Strength = 0.05 #0.05 is often better (avoid too much sharpening)


#AUTO LEVELS PARAMETER
#--------------------------------------------------------------------------------------------------------------------------------
X=4 #X parameter for reducing the autolevels effect on the whites
X2=4 #X2 parameter for reducing the autolevels effect on the blacks


#NUMBER OF THREADS
#--------------------------------------------------------------------------------------------------------------------------------
threads=3


# END VARIABLES, BEGIN SCRIPT
#=================================================================================================================================

johnmeyer
3rd January 2019, 04:53
[edit]Fixed errors in Mrecalculate lines
Script continued ...

SetMemoryMax(768)

AddAutoloadDir("E:\Documents\My Videos\AVISynth\AVISynth Plugins\plugins\Film Restoration\Script_and_Plugins",toFront=true)

/*
Here is a list of plugins used
Loadplugin("E:\Documents\My Videos\AVISynth\AVISynth Plugins\plugins\MVTools\mvtools2.dll")
LoadPlugin ("mvtools2.dll") #Version 2.5.11.9 2/24/2012
LoadPlugin("autolevels.dll") #Version 0.6.0.0 1/09/2011
LoadPlugin("Deflicker.dll") #Version 0.4.0.0 8/16/2004
Loadplugin("Depan.dll") #Version 1.10.0.0 4/09/2007
LoadPlugin("DepanEstimate.dll") #Version 1.9.2.0 3/25/2007
LoadPlugin("fft3dfilter.dll") #Version 2.1.1.0 2/20/2007
Loadplugin("mt_masktools.dll") #Version 2.0.23.0 3/14/2008
loadplugin("RemoveDirtSSE2.dll") #Version 0.9 5/05/2005
Loadplugin("RemoveGrainSSE2.dll") #Version 0.9 5/01/2005
Loadplugin("removegrain.dll") #Version 0.9 5/01/2005
Loadplugin("warpsharp.dll") # 4/05/2010
*/

source1= Avisource(film).killaudio().assumefps(play_speed).converttoYV12()
cropped_source=source1.crop(in_bord_left,in_bord_top,-in_bord_right,-in_bord_bot) #remove any black borders on input video
#cropped_source=filldrops(cropped_source) #Use this when removing bad frames that have been removed by duplicating previous frame


#STABILIZING
#....................................................................................................................................................................
stab_reference= cropped_source.crop(est_left,est_top,-est_right,-est_bottom).tweak(cont=est_cont).MT_binarize(threshold=80).greyscale().invert()
mdata=DePanEstimate(stab_reference,trust=1.0,dxmax=maxstabH,dymax=maxstabV)
#stab=DePanStabilize(cropped_source,data=mdata,cutoff=0.5,dxmax=maxstabH,dymax=maxstabV,method=1,mirror=15).deflicker()
stab=DePanStabilize(cropped_source,data=mdata,cutoff=0.5,dxmax=maxstabH,dymax=maxstabV,method=1,mirror=15)

#DENOISING
#...................................................................................................................................................................
input_to_removedirt=stab.crop(CLeft,CTop,-CRight,-CBottom)
stabcrop=RemoveDirtMC(input_to_removedirt,dirt_strength,false)

prefiltered = RemoveGrain(stabcrop,2)
superfilt = MSuper(prefiltered, hpad=32, vpad=32,pel=2)
super= MSuper(stabcrop, hpad=32, vpad=32,pel=2)

halfblksize= (block_size>4) ? block_size/2 : 4
halfoverlap= (block_over>2) ? block_over/2 : 2

bvec1 = MAnalyse(superfilt, isb = true, delta = 1, blksize=block_size, overlap=block_over,dct=0)
bvec1 = MRecalculate(super, bvec1, blksize=halfblksize, overlap=halfoverlap,thSAD=100)

fvec1 = MAnalyse(superfilt, isb = false, delta = 1, blksize=block_size, overlap=block_over,dct=0)
fvec1 = MRecalculate(super, fvec1, blksize=halfblksize, overlap=halfoverlap,thSAD=100)

bvec2 = MAnalyse(superfilt, isb = true, delta = 2, blksize=block_size, overlap=block_over,dct=0)
bvec2 = MRecalculate(super, bvec2, blksize=halfblksize, overlap=halfoverlap,thSAD=100)

fvec2 = MAnalyse(superfilt, isb = false, delta = 2, blksize=block_size, overlap=block_over,dct=0)
fvec2 = MRecalculate(super, fvec2, blksize=halfblksize, overlap=halfoverlap,thSAD=100)

denoised=stabcrop.MDegrain2(super, bvec1,fvec1,bvec2,fvec2,thSAD=denoising_strength).levels(0,gamma,255,0,255).tweak(sat=saturation).unsharpmask(PRE_sharp_ness,PRE_radi_us,0)


#SHARPENING
#...................................................................................................................................................................
sharp1=denoised.sharpen(Sharp_Strength)
PreBorderFrame = sharp1.Lanczos4Resize(W - bord_left - in_bord_left - bord_right - in_bord_right, H - bord_top - in_bord_top - bord_bot - in_bord_bot)

#FRAME INTERPOLATION (optional)
#...................................................................................................................................................................
#Everything in this section is commented out because I usually choose NOT to do frame interpolation because
#it causes too many unexpected artifacts on certain frames. It also makes the film look like video which
#aesthetically is not always pleasing.

/*
prefiltered = RemoveGrain(PreBorderFrame,2)
super = MSuper(PreBorderFrame,hpad=16, vpad=16, levels=1) # one level is enough for MRecalculate
superfilt = MSuper(prefiltered, hpad=16, vpad=16) # all levels for MAnalyse
backward = MAnalyse(superfilt, isb = true, blksize=16,overlap=8,search=3,dct=0)
forward = MAnalyse(superfilt, isb = false, blksize=16,overlap=8,search=3,dct=0)
forward_re = MRecalculate(super, forward, blksize=8, thSAD=100)
backward_re = MRecalculate(super, backward, blksize=8, thSAD=100)
PreBorderFrame = MFlowFps(PreBorderFrame,super, backward_re, forward_re, num=30000, den=1001,ml=200,mask=2)
*/

#Alternative interpolation
/*
superfps= MSuper(PreBorderFrame,pel=2)
backward_vec2 = MAnalyse(superfps, isb = true,blksize=16)
forward_vec2 = MAnalyse(superfps, isb = false,blksize=16)
PreBorderFrame = MFlowFps(PreBorderFrame,superfps, backward_vec2, forward_vec2, num=60000, den=1001, ml=200).SeparateFields().SelectEvery(4, 0, 3).Weave()
*/

#Yet another way to do interpolation
#The following alternative can provide synthesized frames for hi-def material that causes MSuper to choke
#////// Begin alternative to MFlowFPS ////
#SmoothFPS2(PreBorderFrame,threads)
#////// End alternative to MFlowFPS ////

#A final way to do interpolation, although Interframe is just a front-end to SmoothFPS, so I don't think the results are any different.
#The following is another alternative that can provide synthesized frames for hi-def material that causes MSuper to choke. Probably better than the one above.
#////// Begin alternative to MFlowFPS ////
#PreBorderFrame=InterFrame(NewNum=30000,NewDen=1001,PreBorderFrame,GPU=true,Cores=threads)
#////// End alternative to MFlowFPS ////

#RESULT1: AUTOLEVELS,AUTOWHITE
#......................................................................................................................................................................

Baseclip = PreBorderFrame.crop(borderV,borderH,-borderV,-borderH,align=true).bicubicresize(W,H)
blank_black = Blankclip(baseclip, width=autolev_bord1,height=autolev_bord1)
blank_white= Blankclip(baseclip, width=autolev_bord1,height=autolev_bord1, color=$FFFFFF)
Average= baseclip.FredAverage().invert()
over1 = overlay(baseclip,blank_black, x=40,y=300)
over2 = overlay (over1,blank_white, x=160, y=300) \
.bicubicresize(width(baseclip)-(al2)*2,height(baseclip)-(al2)*2)
Detect = (al2 >1) ? overlay (Average, over2,x=al2,y=al2) \
.converttoRGB24(matrix="rec709") : over2.converttoRGB24(matrix="rec709")

result1= PreBorderFrame.ConvertToRGB24.GamMac(verbosity=4,DC=Detect,Show=False, \
LockChan=LockChan, Th=Th, LockVal=LockVal, Scale=Scale, RedMul=RedMul,\
GrnMul=GrnMul, BluMul=BluMul, loTh=LOTH,hiTh=HITH,oMin=OMIN,oMax=OMAX,\
x=GMx,y=GMy,w=GMw,h=GMh).converttoYV12().deflicker().addborders(X,0,0,0,$FFFFFF) \
.addborders(0,0,X2,0,$000000).autolevels(filterRadius=2).crop(X,0,-X2,-0) \
.addborders(bord_left+in_bord_left, bord_top+in_bord_top, \
bord_right+in_bord_right, bord_bot+in_bord_bot)

#RESULT2: AUTOWHITE
#......................................................................................................................................................................
result2= PreBorderFrame.ConvertToRGB24.GamMac(DC=Detect,Show=False, Dither=TRUE,verbosity=5,LockChan=LockChan, \
Th=Th, LockVal=LockVal, Scale=Scale, RedMul=RedMul, GrnMul=GrnMul, BluMul=BluMul, \
loTh=LOTH,hiTh=HITH,oMin=OMIN,oMax=OMAX,x=GMx,y=GMy,w=GMw,h=GMh).converttoYV12() \
.deflicker().addborders(bord_left+in_bord_left, bord_top+in_bord_top, \
bord_right+in_bord_right, bord_bot+in_bord_bot)

#RESULT3: AUTOLEVELS
#.....................................................................................................................................................................
result3= PreBorderFrame.addborders(X,0,0,0,$FFFFFF).addborders(0,0,X2,0,$000000).autolevels(filterRadius=2).crop(X,0,-X2,-0).addborders(bord_left+in_bord_left, bord_top+in_bord_top, bord_right+in_bord_right, bord_bot+in_bord_bot)

#RESULT4: NO CORRECTIONS
#.....................................................................................................................................................................
result4= PreBorderFrame.addborders(bord_left+in_bord_left, bord_top+in_bord_top, bord_right+in_bord_right, bord_bot+in_bord_bot)

#PARAMETERS FOR THE COMPARISONS
#.....................................................................................................................................................................
W2= W+bord_left+bord_right
H2= H+bord_top+bord_bot
source4=Lanczos4Resize(source1,W2,H2)


#COMPARISONS: ORIGINAL VS RESULTS
#......................................................................................................................................................................
resultS1= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result1,"autolevels, GamMac",size=28,align=2))
resultS2= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result2,"GamMac",size=28,align=2))
resultS3= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result3,"autolevels",size=28,align=2))
resultS4= stackhorizontal(subtitle(source4,"original",size=28,align=2),subtitle(result4,"no level or color corrections",size=28,align=2))

Eval(result)
#return Detect
# Enable MT!
Prefetch(threads)


# END SCRIPT, BEGIN FUNCTIONS

#=================================================================================================================================
#REMOVE DIRT FUNCTION
#......................................................................................................................................................................
function RemoveDirt(clip input, int "limit", bool "_grey")
{
clensed=input.Clense(grey=_grey, cache=4)
alt=input.RemoveGrain(2)
return RestoreMotionBlocks(clensed,input,alternative=alt,pthreshold=6,cthreshold=8, gmthreshold=40,dist=3,dmode=2,debug=false,noise=limit,noisy=4, grey=_grey)

# Alternative settings
# return RestoreMotionBlocks(clensed,input,alternative=alt,pthreshold=4,cthreshold=6, gmthreshold=40,dist=1,dmode=2,debug=false,noise=limit,noisy=12,grey=_grey,show=true)
# return RestoreMotionBlocks(clensed,input,alternative=alt,pthreshold=6,cthreshold=8, gmthreshold=40,dist=3,tolerance= 12,dmode=2,debug=false,noise=limit,noisy=12,grey=_grey,show=false)
}

function RemoveDirtMC(clip,int "limit", bool "_grey")
{
_grey=default(_grey, false)
limit = default(limit,6)

# Alternative way to do pre-filtering.
# prefiltered = fft3dfilter(clip,sigma=1,sigma2=2,sigma3=3,sigma4=5,bw=64,bh=64)

prefiltered = RemoveGrain(clip,2)
superfilt = MSuper(prefiltered, hpad=32, vpad=32,pel=2)

super=MSuper(clip, hpad=32, vpad=32,pel=2)

bvec = MAnalyse(superfilt,isb=true, blksize=16, overlap=2,delta=1, truemotion=true)
fvec = MAnalyse(superfilt,isb=false, blksize=16, overlap=2,delta=1, truemotion=true)

# Increase thSAD if moving objects are being removed
bvec_re = Mrecalculate(super,bvec,blksize=8, overlap=0,thSAD=100)
fvec_re = Mrecalculate(super,fvec,blksize=8, overlap=0,thSAD=100)

backw = MFlow(clip,super,bvec_re)
forw = MFlow(clip,super,fvec_re)

clp=interleave(forw,clip,backw)
clp=clp.RemoveDirt(limit,_grey)
clp=clp.SelectEvery(3,1)
return clp
}

sys32768
26th January 2019, 00:18
Thanks, John. I finally got yours working on my ProRes .MOV files that are 1920 x 1080 but am unclear on size, crop and borders.

It appears that my .MOV files have a 150px left border and 150px right border. I assume for every filter to work correctly, those must be cropped.

If I set those to 150 on in_bord_, the script crashes with an out-of-bounds memory access error on RemoveDirtSSE2. If I set them to 120 it doesn't crash.

I'm also unclear on what my final W= and H= should be in light of the other cropping/border options.

videoFred
26th January 2019, 12:54
If I set those to 150 on in_bord_, the script crashes with an out-of-bounds memory access error on RemoveDirtSSE2. If I set them to 120 it doesn't crash.

I think this is a mod8 issue. 1920-150-150= 1620/8= 202.5.
I you crop 152 on both sides, it"s 1920-152-152= 1616/8= 202.



I'm also unclear on what my final W= and H= should be in light of the other cropping/border options.

It depends on the aspect ratio and the final result you want.
Do you want HD again? Then you must add borders again.

And what is your source? Transfered 8mm film or something else?
Because 8mm should be 4:3 and 1616x1080 is not 4:3.

1440x1080 is 4:3.


Fred.

johnmeyer
26th January 2019, 17:50
Fred,

Isn't 8mm (without the material between sprocket holes) closer to 1:1? Super 8 is most definitely 4:3, but I think 8mm is pretty close to square.

Also, to add to what Fred said about cropping: he is right that it is a mod issue, but I can't remember if it is mod4 or mod8. However, you'll be safe either way if you follow his suggestion and make the crop a multiple of 8. Also, I've never had good luck using a different crop size for the left and right so I always make the black borders equal on either side in my NLE before feeding it to the script so I can use the same crop size for both. Since you'll want it centered on the screen, this actually makes sense to do even if there wasn't a problem when the sizes are different on the left and the right.

sys32768
26th January 2019, 19:12
I think this is a mod8 issue. 1920-150-150= 1620/8= 202.5.
I you crop 152 on both sides, it"s 1920-152-152= 1616/8= 202.

It depends on the aspect ratio and the final result you want.
Do you want HD again? Then you must add borders again.

And what is your source? Transfered 8mm film or something else?
Because 8mm should be 4:3 and 1616x1080 is not 4:3.

1440x1080 is 4:3.
You are correct about 152...math is my weakest subject. Thank you!

My sources are HD 1920 x 1080 16FPS ProRes .MOV files from 8mm reels, transferred by a FlashScan system. They all have the black borders which if cropped makes the full frame about 1560 x 1080. I should look more closely to ensure each file has the same border width.

I was hoping to do everything with these scripts but some post-production editing in Vegas Pro is necessary. I also tend to have more luck with filters like unsharp mask in Vegas Pro because the feedback is so quick, allowing me to fine tune much easier.

I've attached an unprocessed HD frame capture roughly cropped.

John: I put trim beginning back into your script, and am going to attempt to add trim end back. It helps me a lot because several of my reels are more than 30 minutes and often contain half footage I don't want, so it speeds up my processing a great deal to have things split out from the get-go.