I've been working with a lot of VHS material lately, and I can't help noticing that the optimal VHS script is... well, a little dated.
There are lots of great YV12 noise filters now that weren't available (or at least mature) when that script was written, so I've been playing around with some of them to see what I can come up with. I've cobbled together a VHS script that I'm reasonably happy with, and at this point I'd like to toss it onto the table for review and comment by the KVCD community.
My first concern is optimum visual quality, considering the generally poor quality of VHS material, so I don't want to over-filter it and destroy what few details there are to begin with. My secondary concern is, of course, compressability.
I have tentatively settled on deen as my main denoiser because it's fast, it works in YV12, and I find the results to be comparable to dust without the blockiness in high-motion scenes that I occasionally see with dust. However, I'm not committed to deen if anybody knows something better.
I'm also assuming interlaced material.
With all that being said, here it is:
Code:
################################
##### AviSynth 2.53 Script #####
################################
### AVI SOURCE(S) ###
cap1=Trim(AVISource("T:\Capturea.avi"),79,70190)
cap2=Trim(AVISource("T:\Captureb.avi"),93,13226)
#cap3=Trim(AVISource("[DRIVE]:\[PATH]\[FILENAME].avi"),0,0)
clip = AlignedSplice(cap1,cap2)
##### Set Variables #####
# Top: Pixels to crop from the top
# Bottom: Pixels to crop from the bottom
# Left: Pixels to crop from the left
# Right: Pixels to crop from the right
# Width: Target width
# Height: Target height
Top = 8
Bottom = 10
Left = 8
Right = 8
Width = 352
Height = 480
#Set VirtualDub plugin directory
global VirtualDub_plugin_directory="C:\Program \
Files\GordianKnot\VirtualDubMod\plugins"
##### Main Script #####
### Work in Yv12 colorspace
clip = ConverttoYV12(clip)
### Insert 1 second of black before and after the clip
clip = BlankClip(clip,30)+clip+BlankClip(clip,30)
### Bob for temporal filtering on interlaced material
clip = ComplementParity(clip).Bob(0,0.5)
### Noise reduction filters
clip = Undot(clip).CNR2("xxx",4,5,255).Deen("a3d",1,5,8)
### KVCD filters for compressability
clip = KVCD(clip)
### Interleave to restore 29.97i
clip = SeparateFields(clip).SelectEvery(4,1,2).Weave()
### Resize with Lanczos to preserve sharpness
clip = LanczosResize(clip,width,height)
### Adjust color levels as necessary
clip = Levels(clip, 0, 1.1, 255, 0, 255)
###Restrict luma and chroma values for CCIR-601 compliance
clip = Limiter(clip, 16, 235, 16, 240)
### Use shadowsmoother to reduce swim in black areas
clip = ConvertToRGB(clip,interlaced=true)
clip = VD_ShadowSmoother(clip,5,1,3,true,true,true)
### Crop off VHS head noise and add black borders for overscan
Clip = Crop(clip, Left, Top, -Right, -Bottom)
clip = AddBorders(clip, Left, Top, Right, Bottom)
return clip
##### Functions #####
function VD_ShadowSmoother(clip clip, \
int "threshold", \
int "strength", \
int "difference", \
bool "pixellock", \
bool "noiselock", \
bool "postsmooth") {
LoadVirtualdubPlugin(VirtualDub_plugin_directory+"\shadowsmoother07.vdf", \
"_VD_ShadowSmoother")
return clip._VD_ShadowSmoother(default(threshold,4), \
default(strength,15), \
default(difference,2), \
default(pixellock,false)?1:0, \
default(noiselock,false)?1:0, \
default(postsmooth,false)?1:0) }
function KVCD(clip c){
undot(c)
asharp(1,4)
STMedianFilter(3, 3, 1, 1)
MergeChroma(blur(1.5))
#MergeLuma(blur(0.1))
ScriptClip(" nf = YDifferenceToNext()" +chr(13)+ "unfilter( \
-(fmin(round(nf)*2, 100)), -(fmin(round(nf)*2, 100)) ).TemporalSoften( \
fmin( round(2/nf), 6), round(1/nf) , round(3/nf) , 1, 1) ")
return last}
function fmin( int f1, int f2) {
return ( f1<f2 ) ? f1 : f2}
function fmin( int f1, int f2) {
return ( f1<f2 ) ? f1 : f2
}
Suggestions? Comments?