View Full Version : SpotLess for UV
Mounir
8th January 2021, 11:09
Is there a way to make it work for UV , i can't seem to make it work "invalid arguments". I like it a lot for Luma so perhaps... i found a new gem
AVISource("MyVideo.avi")
assumetff()
trim(184,6727)
ConvertToYV16(interlaced=true)
orig=last
ev=orig.assumetff().separatefields().selecteven()
od=orig.assumetff().separatefields().selectodd()
ev
ue_chroma = UToY(ev).SpotLess(last)
ve_chroma = VToY(ev).SpotLess(last)
YToUV(ue_chroma, ve_chroma)
MergeLuma(ev)
ev_filtered=last
od
uo_chroma = UToY(od).SpotLess(last)
vo_chroma = VToY(od).SpotLess(last)
YToUV(uo_chroma, vo_chroma)
MergeLuma(od)
od_filtered=last
interleave(ev_filtered,od_filtered)
assumefieldbased().assumetff().weave()
converttoyv12(interlaced=true)
#########
####################################
Function SpotLess(clip c,int "RadT",int "ThSAD",int "ThSAD2",int "pel",bool "chroma", int "BlkSz",Int "Olap",bool "tm",Bool "glob",Float "bBlur") {
RadT = Default(RadT,1) # Temporal radius. (MCompensate arg)
ThSAD = Default(ThSAD,10000) # SAD threshold at radius 1 (Default Nearly OFF).
ThSAD2 = Default(ThSAD2,ThSAD) # SAD threshold at radius RadT.
Pel = Default(pel,2) # Default 2. 1, 2, or 4. Maybe set 1 for HD+. (1=precision to pixel, 2=precision to half pixel, 4=quarter pixel)
Chroma = Default(chroma,True) # MAnalyse chroma arg. If set to true, use chroma in block matching.
BlkSz = Default(BlkSz,8) # Default 8. MAnalyse BlkSize. Bigger blksz quicker and perhaps better, esp for HD clips. Maybe also better where BIG noise.
OLap = Default(OLap, BlkSz/2) # Default half of BlkSz.
Tm = Default(tm,True) # TrueMotion, Some folk swear MAnalyse(truemotion=false) is better.
Glob = Default(glob,Tm) # Default Tm, Allow set MAnalyse(global) independently of TrueMotion.
Bblur = Default(bblur,0.0) # Default OFF
Assert(1 <= RadT,"SpotLess: 1 <= RadT")
pad = max(BlkSz,8)
sup = (bBlur<=0.0 ? c : c.blur(bblur)).MSuper(hpad=pad,vpad=pad,pel=pel,sharp=2)
sup_rend = (bBlur<=0.0) ? sup : c.MSuper(hpad=pad,vpad=pad,pel=pel,sharp=2,levels=1) # Only 1 Level required where not MAnalyse-ing.
MultiVec = sup.MAnalyse(multi=true, delta=RadT,blksize=BlkSz,overlap=OLap,search=4,chroma=Chroma,truemotion=Tm,global=Glob)
c.MCompensate(sup_rend,MultiVec,tr=RadT,thSad=ThSAD,thSad2=ThSAD2)
MedianBlurTemporal(radiusY=0,radiusU=0,radiusV=0,temporalradius=RadT) # Temporal median blur only [not spatial]
SelectEvery(RadT*2+1,RadT) # Return middle frame
}
StainlessS
8th January 2021, 18:04
Mournir,
Was nearly there but not quite,
ue_chroma = UToY(ev).SpotLess(last) # UToY(ev) already given clip to SpotLess
I've made a coupla changes to script to prevent any possibility of [grey due to UToY] chroma contributing to vector calcs.
[EDIT: Original chroma is in luma channel due to eg UToY]
Also, I've just changed default Spotless(Glob) to true, rather than same as TrueMotion.
#AVISource("MyVideo.avi")
AVISource("D:\Parade.avi")
assumetff()
trim(184,6727)
orig=last # Remember YV12 Luma
ConvertToYV16(interlaced=true)
ev=assumetff().separatefields().selecteven()
od=assumetff().separatefields().selectodd()
ev
ue_chroma = UToY.SpotLess(chroma=false) # Dont use Chroma in vector creation. Chroma is grey : WAS:- ue_chroma = UToY(ev).SpotLess(last)
ve_chroma = VToY.SpotLess(chroma=false) #
ev_filtered=YToUV(ue_chroma, ve_chroma) # Luma is grey 50%
od
uo_chroma = UToY.SpotLess(chroma=false)
vo_chroma = VToY.SpotLess(chroma=false)
od_filtered=YToUV(uo_chroma, vo_chroma)
interleave(ev_filtered,od_filtered)
assumefieldbased().assumetff().weave()
converttoyv12(interlaced=true)
MergeLuma(orig) # Restore Luma
Return Last
####################################
/*
SpotLess v1.06. temporal spot/noise remover, by StainlessS @ Doom9. https://forum.doom9.org/showthread.php?t=181777
Original idea from Didée post :- https://forum.doom9.org/showthread.php?p=1402690#post1402690
Req:- Pinterf MvTools2(), Pinterf Medianblur2() with MedianBlurTemporal rather than the MedianBlurT() from Didée post.
With appropriate plugins, will be AVS+ colorspace and x64 compatible.
Fine using Avs+ Prefetch() so long as current Pinterf plugins, and Frame Accurate source. RequestLinear() following the source filter might suffice as frame accurate source filter.
NOT FOR cartoon/anime, live video only, sorry.
v1.01, Remove RadT Max check. Add MSuper(hpad=16,vpad=16). Add BlkSz arg.
v1.02, Add some stuff.
v1.03, Frame size auto config of args removed (found instances where caused problems). Added Glob and bBlur args.
v1.04, Script breaking changes, I guess is more flexible if can also set ThSAD, inserted ThSAD 3rd arg. RadT now default 1, was 2, dont over denoise unless requested.
v1.05, Additional checks on args.
v1.06, Glob Default true, Almost always better.
SpotLess(clip c,int "RadT"=1,int "ThSAD"=10000,int "ThSAD2"=ThSAD,int "pel"=2,bool "chroma"=true, int "BlkSz"=8,Int "Olap"=BlkSz/2,
\ bool "tm"=true,Bool "glob"=True,Float "bBlur"=0.0)
RadT, 1 or more, Default 1. Removes Spots on up to RadT [Temporal Radius] consecutive frames.
RadT > 2 will usually be overkill. Setting too high could possibly result in blurring.
Each pixel in result frame is median pixel value of (2*RadT+1) motion compensated frames (including source, ie current_frame-RadT to current_frame+RadT).
ThSAD, Default 10000=NEARLY OFF(ie ignore hardly any bad blocks), 0 < ThSAD < 16320(8*8*255). 8x8 block SAD threshold at radius 1 (ie at current_frame +- 1) [SAD, Sum of Absolute (pixelwise) Differences].
ThSAD and ThSAD2 suggested absolute minimum of maybe about 400.
ThSAD and ThSAD2 thresholds are based on 8 bit 8x8 block, irrespective of colorspace depth or BlkSz, max=8x8x255=16320, use same thresholds where High Bit Depth.
In mvTools MCompensate(), when creating a compensated block the SAD between compensated block and the same original block in current_frame, the 8 bit SAD is measured and if
greater than SAD threshold then that block is ignored and uses original block from current frame instead. [The compensated block is judged too different, so ignored & original block used instead
in the result MCompensated frame].
Where eg ThSAD=64, AVERAGE absolute single pixel difference threshold would be 64/(8*8)=1, so AVERAGE absolute pixel difference greater than 1 would ignore that mcompensated block and use the
block from current frame in the resulting mcompensated frame instead. This example allows for all pixels in a 8x8 block to be different by 1, or a single pixel in 8x8 block to be different by 64,
or some other mixture.
A problem with above is, if a low ThSAD and current_frame block is mostly noise, so compensated blocks could be judged bad because they are too different to the bad noisey block, and the result
block may/will be just as bad as the noisy source block. A possible solution to this problem is to have a higher SAD threshold and/or have a bigger BlkSize so that the number of bad source pixels
after converting/scaling to as if an 8x8 block, will contain fewer bad noise pixels. So, SpotLess BlkSz arg would ideally maybe 4 or more times the area of the largest spots that you have, and a SAD
threshold big enough so as to not ignore the block [ wild guess minimum SAD threshold for big spot sizes of (8x8x255)/4 = 4080 ].
Where a complete source frame is bad, then maybe should have very high (eg 10000) SAD threshold, and BlkSz may not really matter too much.
It is not the end of the world if some of the compensated blocks are ignored and swapped for the original current_frame block. Nor is it the end of the world if
no blocks were ignored because of high SAD threshold. The final result pixel is median pixel value of (2*RadT+1) motion compensated blocks, so allowing for some mistakes by choosing the
middle pixel value.
I've just tested real bad double frame, full frame luma and chroma corruption, with below line:
SpotLess(RadT=5,ThSAD=1000000,ThSAD2=1000000,pel=2,chroma=false,BlkSz=8,Olap=4,tm=false,glob=false,bBlur=0.0)
And although both SAD thresholds of 1 million, are totally impossible and so no blocks could possibly be ignored and yet we still got pretty good results, all frames were fixed
as we still had the temporal median filter to fall back on and pick the middle pixel value.
From mvtools2 docs:
ThSAD is SAD threshold for safe (dummy) compensation.
If block SAD is above the thSAD, the block is bad, and we use source block instead of the compensated block. Default is 10000 (practically disabled).
ThSAD2, Default ThSAD, 0 < ThSAD2 < 16320(8*8*255), Lower removes fewer spots, but less chance of blurring.
ThSAD2 sets the SAD [Sum of Absolute Differences] threshold for most distant frame from current_frame at distance RadT, with those frames that are distances in-between 1 and RadT
acquiring a SAD threshold linearly interpolated between the two.
From mvtools2 docs:
ThSAD2:
Defines the SAD soft threshold for the furthest frames at current_frame +- RadT.
The actual SAD threshold for each reference frame is a smooth interpolation between the original thSAD (close to the current frame)
and thSAD2. Setting thSAD2 lower than thSAD allows large temporal radii and good compensation for low SAD blocks while reducing the global error and the
risk of bluring when the result of MCompensate is passed to a temporal denoising filter.
EDIT: Although I have said that SAD threshold being too high could result in blurred frames, that is really taken from above "risk of bluring" line from mvtools docs,
however, that warning says "temporal denoising filter", which might suggest pixel averaging, whereas we are using pixel median. I'm not sure that blurring would be the result
of having too high a SAD threshold.
Pel, Default 2. 1, 2, or 4. Maybe set 1 for HD+. (1=precision to pixel, 2=half pixel, 4=quarter pixel)
Chroma, Default True. MAnalyse chroma arg. If true, use chroma in block matching when creating vectors. Maybe use False if source B&W or color noise.
BlkSz, Default 8. MAnalyse BlkSize. Bigger blksz quicker and perhaps better for HD clips. [Info: current Pinterf MvTools allows for BlkSize=12, and overlap=6]
OLap, Default half BlkSz, Block overlap.
Tm, TrueMotion Default True. Some folk swear truemotion=false is better.
Glob, Default True (True v1.06, was same as Tm, true almost always better), Allow set MAnalyse(global) independently of TrueMotion.
From MvTools2 docs for MAnalyse,
global
Estimate global motion (at every level) and use it as an additional predictor.
Only pan shift is estimated (no zoom and rotation).
Use false to disable, use true to enable.
bBlur, Default 0.0 [OFF]. If used, Suggest about 0.6, where MAnalyse create vectors is performed on denoised (blurred) super clip.
*/
Function SpotLess(clip c,int "RadT",int "ThSAD",int "ThSAD2",int "pel",bool "chroma", int "BlkSz",Int "Olap",bool "tm",Bool "glob",Float "bBlur") {
myName = "SpotLess: "
RadT = Default(RadT,1) # Temporal radius. (MCompensate arg)
ThSAD = Default(ThSAD,10000) # SAD threshold at radius 1 (Default Nearly OFF).
ThSAD2 = Default(ThSAD2,ThSAD) # SAD threshold at radius RadT.
Pel = Default(pel,2) # Default 2. 1, 2, or 4. Maybe set 1 for HD+. (1=precision to pixel, 2=precision to half pixel, 4=quarter pixel)
Chroma = Default(chroma,True) # MAnalyse chroma arg. If set to true, use chroma in block matching.
BlkSz = Default(BlkSz,8) # Default 8. MAnalyse BlkSize. Bigger blksz quicker and perhaps better, esp for HD clips. Maybe also better where BIG noise.
OLap = Default(OLap, BlkSz/2) # Default half of BlkSz.
Tm = Default(tm,True) # TrueMotion, Some folk swear MAnalyse(truemotion=false) is better.
Glob = Default(glob,True) # Default True, Allow set MAnalyse(global) independently of TrueMotion.
Bblur = Default(bblur,0.0) # Default OFF
Assert(1 <= RadT,myName + " 1 <= RadT")
Assert(0.0 <= bblur <= 1.58, myName + "0.0 <= bblur <= 1.58")
Assert(pel==1 || pel==2 || pel==4, myName + "pel==1 || pel==2 || pel==4")
pad = max(BlkSz,8)
sup = (bBlur<=0.0 ? c : c.blur(bblur)).MSuper(hpad=pad,vpad=pad,pel=pel,sharp=2)
sup_rend = (bBlur<=0.0) ? sup : c.MSuper(hpad=pad,vpad=pad,pel=pel,sharp=2,levels=1) # Only 1 Level required where not MAnalyse-ing.
MultiVec = sup.MAnalyse(multi=true, delta=RadT,blksize=BlkSz,overlap=OLap,chroma=Chroma,truemotion=Tm,global=Glob)
c.MCompensate(sup_rend, MultiVec, tr=RadT, thSad=ThSAD, thSad2=ThSAD2)
MedianBlurTemporal(radiusY=0,radiusU=0,radiusV=0,temporalradius=RadT) # Temporal median blur only [not spatial]
SelectEvery(RadT*2+1,RadT) # Return middle frame
}
Think it should be about right.
EDIT: Also delayed restore of luma till end of script.
Mounir
8th January 2021, 19:55
@ Stainless
It's not working for me i get weird result (the source is pal 720x576i), see picture (i used your last script), tested with avisynth 2.6 MT
StainlessS
8th January 2021, 20:12
OK, can you post a bit of your failing clip please (10 secs with movement), I dont keep interlaced stuff at hand. [I probably cocked up somewhere]
EDIT: If you just remove the "last"'s from below, then is your original script [minus mistakes], dont know if will work [does it work ok ?]
Quote:
AVISource("MyVideo.avi")
assumetff()
trim(184,6727)
ConvertToYV16(interlaced=true)
orig=last
ev=orig.assumetff().separatefields().selecteven()
od=orig.assumetff().separatefields().selectodd()
ev
ue_chroma = UToY(ev).SpotLess(last)
ve_chroma = VToY(ev).SpotLess(last)
YToUV(ue_chroma, ve_chroma)
MergeLuma(ev)
ev_filtered=last
od
uo_chroma = UToY(od).SpotLess(last)
vo_chroma = VToY(od).SpotLess(last)
YToUV(uo_chroma, vo_chroma)
MergeLuma(od)
od_filtered=last
interleave(ev_filtered,od_filtered)
assumefieldbased().assumetff().weave()
converttoyv12(interlaced=true)
Mounir
8th January 2021, 20:31
Ok, now it's working if i remove (last), thanks you rock !
Mounir
8th January 2021, 20:53
If you could do that with ttempsmooth aswell.... Now that i got spotless working i noticed that it is just about right when i compare to the original whereas ttempsmooth miss something (problem with grey ?)
avisource("myvideo.avi")
assumetff()
ConvertToYV16(interlaced=true)
orig=last
ev=orig.assumetff().separatefields().selecteven()
od=orig.assumetff().separatefields().selectodd()
ev
ue_chroma = UToY(ev).ttempsmooth(maxr=1,lthresh=150, strength=2)
ve_chroma = VToY(ev).ttempsmooth(maxr=1,lthresh=150, strength=2)
YToUV(ue_chroma, ve_chroma)
MergeLuma(ev)
ev_filtered=last
od
uo_chroma = UToY(od).ttempsmooth(maxr=1,lthresh=150, strength=2)
vo_chroma = VToY(od).ttempsmooth(maxr=1,lthresh=150, strength=2)
YToUV(uo_chroma, vo_chroma)
MergeLuma(od)
od_filtered=last
interleave(ev_filtered,od_filtered)
assumefieldbased().assumetff().weave()
converttoyv12(interlaced=true)
StainlessS
8th January 2021, 21:05
First things first,
can you post a bit of your original script [EDIT:clip] causing probs, I want to find the prob in my mod of your script [if there was one].
I obtained an interlaced clip, and tried, not brilliant but nothing like your posted image.
Is likely that using only on [single plane] chroma, is using well out-of-good-range args for thresholds,
because Chroma generally does not change very far from center $80, so ThSAD and ThSAD2, maybe also BlkSz and Overlap should be modified.
All above Thresh args should maybe be reduced, and BlkSz/Overlap modified.
EDIT: Also, did you use Pinterf MvTools with 2.6 MT ?
StainlessS
8th January 2021, 21:31
I'm not seeing any difference between your [fixed] script and mine [identical], maybe you made small change to posted script.
They are not exhibiting anything similar to your image.
MPEG2Source("D:\DVD\P\VIDEO_TS\P.d2v")
#####################
assumetff()
#trim(184,6727)
original=last
ConvertToYV16(interlaced=true)
orig=last
ev=orig.assumetff().separatefields().selecteven()
od=orig.assumetff().separatefields().selectodd()
ev
ue_chroma = UToY(ev).SpotLess
ve_chroma = VToY(ev).SpotLess
YToUV(ue_chroma, ve_chroma)
MergeLuma(ev)
ev_filtered=last
od
uo_chroma = UToY(od).SpotLess
vo_chroma = VToY(od).SpotLess
YToUV(uo_chroma, vo_chroma)
MergeLuma(od)
od_filtered=last
interleave(ev_filtered,od_filtered)
assumefieldbased().assumetff().weave()
converttoyv12(interlaced=true)
Result_1=Last
####################
orig
ev=assumetff().separatefields().selecteven()
od=assumetff().separatefields().selectodd()
ev
ue_chroma = UToY.SpotLess(chroma=false) # Dont use Chroma in vector creation. Chroma is grey : WAS:- ue_chroma = UToY(ev).SpotLess(last)
ve_chroma = VToY.SpotLess(chroma=false) #
ev_filtered=YToUV(ue_chroma, ve_chroma) # Luma is grey 50%
od
uo_chroma = UToY.SpotLess(chroma=false)
vo_chroma = VToY.SpotLess(chroma=false)
od_filtered=YToUV(uo_chroma, vo_chroma)
interleave(ev_filtered,od_filtered)
assumefieldbased().assumetff().weave()
converttoyv12(interlaced=true)
MergeLuma(original) # Restore Luma
Result_2=Last
############
Top=StackHorizontal(Result_1,Result_2)
D1=ClipDelta(Result_1,Result_2)
D2=ClipDelta(Result_1,Result_2,Amp=true)
Bot=StackHorizontal(D1,D2)
StackVertical(Top,Bot)
Return Last
# Return Clip Difference of input clips (amp==true = Amplified, show==true = show background)
Function ClipDelta(clip clip1,clip clip2,bool "amp",bool "show") {
amp=Default(amp,false)
show=Default(show,false)
c2=clip1.levels(128-32,1.0,128+32,128-32,128+32).greyscale()
c1=clip1.subtract(clip2)
c1=(amp)?c1.levels(127,1.0,129,0,255):c1
return (show)?c1.Merge(c2):c1
}
https://i.postimg.cc/jwbycGSs/M-00.png (https://postimg.cc/jwbycGSs)
EDIT: Above, left bottom is Result_1 subtract result_2, right bottom same but difference amplified greatly,
the left one using subtract is centered at 126 [TV_Levels middle] whereas right is 128 centered,
so they look slightly different but both signify no difference at all.
Mounir
9th January 2021, 00:11
If you still need the sample: https://mega.nz/file/3AYRiArZ#eE7FakTIH1g466BULL99IVYuUu4JWrWoFQUMrPXmloo
check on frames 35,36 for the horizontal chroma stripes
StainlessS
9th January 2021, 02:10
Cheers Mounir, I'll have a look.
StainlessS
9th January 2021, 13:33
check on frames 35,36 for the horizontal chroma stripes
I obtained an interlaced clip, and tried, not brilliant but nothing like your posted image.
Is likely that using only on [single plane] chroma, is using well out-of-good-range args for thresholds,
because Chroma generally does not change very far from center $80, so ThSAD and ThSAD2, maybe also BlkSz and Overlap should be modified.
All above Thresh args should maybe be reduced, and BlkSz/Overlap modified.
Even without looking, I think that your "horizontal chroma stripes" are probably down to the ThSAD and ThSAD2 being way too high for chroma,
wild guess that maybe about ThSAD=800, ThSAD2=2500, might be more like it [but that is indeed a totally wild guess].
When too high, does not detect when eg scene change, and counts non current scene frames where it should ignore them,
StainlessS
9th January 2021, 22:19
Wanna try this Mounir,
Implemented as two sets or args and results, so can see difference between settings.
Might want to try further process some frames with SpotLess() on Luma, ONLY, maybe select specific frames via ClipClop or ReplaceFramesSimple.
AviSource(".\sample-sages_po.avi") # HUFFYUV YUY2
Assumetff()
Original=last
####### CONFIG ###############################
### RESULT_1 SPOTLESS Defaults
RADT_1 = 1
ThSAD_1 = 10000
ThSAD2_1 = 10000
BLKSZ_1 = 8
OLAP_1 = 4
TM_1 = True
GLOB_1 = True
BBLUR_1 = 0.0
###### RESULT_2 Args
RADT_2 = 3
ThSAD_2 = 3000
ThSAD2_2 = 5000
BLKSZ_2 = 4
OLAP_2 = 2
TM_2 = True
GLOB_2 = True # SUGGEST, DO NOT CHANGE
BBLUR_2 = 0.6 # SUGGEST, DO NOT CHANGE
####### END CONFIG ############################
Result_1 = Original.SpotLess_U_V(radt=RADT_1,thsad=THSAD_1,thsad2=THSAD2_1,BlkSz=BLKSZ_1,Olap=OLAP_1,tm=TM_1,glob=GLOB_1,bBlur=BBLUR_1)
#######
Result_2 = Original.SpotLess_U_V(radt=RADT_2,thsad=THSAD_2,thsad2=THSAD2_2,BlkSz=BLKSZ_2,Olap=OLAP_2,tm=TM_2,glob=GLOB_2,bBlur=BBLUR_2)
#######
SORG ="Original"
SD = "Results Diff Amplified"
SR1=SpotStr("Result_1: ",RADT_1,THSAD_1,THSAD2_1,BLKSZ_1,OLAP_1)
SR2=SpotStr("Result_2: ",RADT_2,THSAD_2,THSAD2_2,BLKSZ_2,OLAP_2)
###
D=Subtract(Result_2,Result_1).levels(127-8,1.0,129+8,0,255)
LFT=StackVertical(Original.TSub(SORG),D.TSub(SD))
RGT=StackVertical(Result_1.TSub(SR1),Result_2.TSub(SR2))
StackHorizontal(LFT,RGT)
Return Last
Function SpotStr(String s,int radt,int th,int th2,int bsz,int olap) {
Return s+String(RADT," %.0f")+String(th," %.0f")+String(th2," %.0f")+String(bsz," %.0f")+String(olap," %.0f")
}
# Stack Overhead Subtitle Text, with optional FrameNumber shown.
Function TSub(clip c,string Tit,Bool "ShowFrameNo",Int "Col"){
c.BlankClip(height=20,Color=Default(Col,0))
(Default(ShowFrameNo,False))?ScriptClip("""Subtitle(String(current_frame,"%.f] """+Tit+""""))"""):Trim(0,-1).Subtitle(Tit)
Return StackVertical(c).AudioDubEx(c)
}
Function SpotLess_U_V(clip c,int "radt",int "thsad",int "thsad2",int "BlkSz",Int "Olap",bool "tm",Bool "glob",Float "bBlur") {
# Returns YUY2 (interlaced)
cyv=c.ConvertToYV24(interlaced=true) # Should be slightly better results if YV24, but somewhat slower, convert to YV16 if too slow
cyv.SeparateFields.SelectEven.AssumeFrameBased
ue_chroma = UToY.SpotLess(radt=radt,thsad=thsad,thsad2=thsad2,chroma=false,blksz=blksz,olap=olap,tm=tm,glob=glob,bblur=bblur)
ve_chroma = VToY.SpotLess(radt=radt,thsad=thsad,thsad2=thsad2,chroma=false,blksz=blksz,olap=olap,tm=tm,glob=glob,bblur=bblur)
ev_filtered=YToUV(ue_chroma, ve_chroma)
###
cyv.SeparateFields.SelectOdd.AssumeFrameBased
uo_chroma = UToY.SpotLess(radt=radt,thsad=thsad,thsad2=thsad2,chroma=false,blksz=blksz,olap=olap,tm=tm,glob=glob,bblur=bblur)
vo_chroma = VToY.SpotLess(radt=radt,thsad=thsad,thsad2=thsad2,chroma=false,blksz=blksz,olap=olap,tm=tm,glob=glob,bblur=bblur)
od_filtered=YToUV(uo_chroma, vo_chroma)
###
Interleave(ev_filtered,od_filtered)
AssumeFieldBased.weave
MergeLuma(cyv)
ConvertToYUY2(interlaced=true)
}
EDIT: Result_2 are better settings, maybe have a bit more tinker. [settings used are probably not optimal]
Frame 35
https://i.postimg.cc/sQQN7vgY/M-01.jpg (https://postimg.cc/sQQN7vgY)
Above there is a bit of a line in luma that could probably be removed via Spotless on Luma [restore the fixed chroma afterwards].
EDIT: I've processed as YV24, results definitely better than YV16, even though converted to YUY2 on output [same as input avi].
EDIT: Changed order of subtract to D=Subtract(Result_2,Result_1).levels(127-8,1.0,129+8,0,255)
Was the other way around. No big deal either way.
If Amplified diff is eg Green, then Result_2 is more Green than Result_1.
StainlessS
10th January 2021, 05:45
Bit more play,
Args are probably not optimal, I've spent plenty of time on script, now its your turn. :)
Can Process UV, or Y, or UV + Y, with comparison set of args for tweaking.
It is SLOOOOW. :( ... [ but looks like a music vid, so probably not that long :) ]
# SpotLessI_UV_Y.avs
AviSource(".\sample-sages_po.avi") # HUFFYUV YUY2
Assumetff()
ConvertToYV24(Interlaced=True) # we're gonna Proc in YV24
###############################################
####### CONFIG ###############################
###############################################
PROC = 1 # 1 = PROCESS UV, 2 = PROCESS Y, 3 = PROCESS UV+Y
FINAL = False # If True, then returns RESULT_2 [UV or or Y or UV+Y] (No Stack)
COLORSPC = "ConvertToYUY2" # Return ColorSpace, YUY2, Same as Input Clip. [Adds "(Interlaced=True)"]
### RESULT_1 SPOTLESS Defaults [Can use to see difference between 2 sets of args]
RADT_1_UV = 1
ThSAD_1_UV = 10000
ThSAD2_1_UV = 10000
BLKSZ_1_UV = 8
OLAP_1_UV = 4
TM_1_UV = True
GLOB_1_UV = True
BBLUR_1_UV = 0.0
#
RADT_1_Y = 1
ThSAD_1_Y = 10000
ThSAD2_1_Y = 10000
BLKSZ_1_Y = 8
OLAP_1_Y = 4
TM_1_Y = True
GLOB_1_Y = True
BBLUR_1_Y = 0.0
###### RESULT_2 args (Actual Result)
RADT_2_UV = 3 # Radius, Number of even or Odd Fields
ThSAD_2_UV = 3000
ThSAD2_2_UV = 5000
BLKSZ_2_UV = 4
OLAP_2_UV = 2
TM_2_UV = True
GLOB_2_UV = True # SUGGEST, DO NOT CHANGE
BBLUR_2_UV = 0.6 # SUGGEST, DO NOT CHANGE
#
RADT_2_Y = 6 # Radius, Number of even or Odd Fields
ThSAD_2_Y = 1000
ThSAD2_2_Y = 10000
BLKSZ_2_Y = 8
OLAP_2_Y = 2
TM_2_Y = True
GLOB_2_Y = True # SUGGEST, DO NOT CHANGE
BBLUR_2_Y = 0.6 # SUGGEST, DO NOT CHANGE
###############################################
####### END CONFIG ############################
###############################################
Original=last
Assert(1 <= PROC <= 3,"1 <= PROC <= 3")
Result_1_UV = Original.SpotLess_UV(radt=RADT_1_UV,thsad=THSAD_1_UV,thsad2=THSAD2_1_UV,BlkSz=BLKSZ_1_UV,Olap=OLAP_1_UV,tm=TM_1_UV,glob=GLOB_1_UV,bBlur=BBLUR_1_UV)
Result_1_YUV = Result_1_UV.SpotLess_Y(radt=RADT_1_Y,thsad=THSAD_1_Y,thsad2=THSAD2_1_Y,BlkSz=BLKSZ_1_Y,Olap=OLAP_1_Y,tm=TM_1_Y,glob=GLOB_1_Y,bBlur=BBLUR_1_Y)
#######
Result_2_UV = Original.SpotLess_UV(radt=RADT_2_UV,thsad=THSAD_2_UV,thsad2=THSAD2_2_UV,BlkSz=BLKSZ_2_UV,Olap=OLAP_2_UV,tm=TM_2_UV,glob=GLOB_2_UV,bBlur=BBLUR_2_UV)
Result_2_YUV = Result_2_UV.SpotLess_Y(radt=RADT_2_Y,thsad=THSAD_2_Y,thsad2=THSAD2_2_Y,BlkSz=BLKSZ_2_Y,Olap=OLAP_2_Y,tm=TM_2_Y,glob=GLOB_2_Y,bBlur=BBLUR_2_Y)
#######
RESULT_1 = (PROC==1) ? Result_1_UV : (PROC==2) ? Result_1_YUV.MergeChroma(Original) : Result_1_YUV
RESULT_2 = (PROC==1) ? Result_2_UV : (PROC==2) ? Result_2_YUV.MergeChroma(Original) : Result_2_YUV
S_ORG = "Original"
S_YUV = (PROC==1) ? "UV" : (PROC==2) ? "Y" : "YUV"
S_D = "Results Diff Amplified_" + S_YUV
S_R1=SpotStr(PROC,"Result_1_" + S_YUV + " ::: ",radt_1_UV,thsad_1_UV,thsad2_1_UV,blksz_1_UV,olap_1_UV, radt_1_y,thsad_1_y,thsad2_1_y,blksz_1_y,olap_1_y)
S_R2=SpotStr(PROC,"Result_2_" + S_YUV + " ::: ",radt_2_UV,thsad_2_UV,thsad2_2_UV,blksz_2_UV,olap_2_UV, radt_2_y,thsad_2_y,thsad2_2_y,blksz_2_y,olap_2_y)
###
D=Subtract(Result_2,Result_1).levels(127-8,1.0,129+8,0,255)
LFT=StackVertical(Original.TSub(S_ORG),D.TSub(S_D))
RGT=StackVertical(Result_1.TSub(S_R1),Result_2.TSub(S_R2))
StackHorizontal(LFT,RGT)
(FINAL) ? RESULT_2 : Last
Return Last.Eval(COLORSPC+"(Interlaced=True)")
Function SpotStr(Int PROC,String s,int radt,int th,int th2,int bsz,int olap, int radt_y,int th_y,int th2_y,int bsz_y,int olap_y) {
sa = "UV=" + String(RADT," %.0f")+String(th," %.0f")+String(th2," %.0f")+String(bsz," %.0f")+String(olap," %.0f")
sb = "Y =" + String(RADT_Y," %.0f")+String(th_Y," %.0f")+String(th2_Y," %.0f")+String(bsz_Y," %.0f")+String(olap_Y," %.0f")
Return s + (PROC==1 ? sa : PROC==2 ? sb : (sa + " ::: " + sb))
}
# Stack Overhead Subtitle Text, with optional FrameNumber shown.
Function TSub(clip c,string Tit,Bool "ShowFrameNo",Int "Col"){
c.BlankClip(height=20,Color=Default(Col,0))
(Default(ShowFrameNo,False))?ScriptClip("""Subtitle(String(current_frame,"%.f] """+Tit+""""))"""):Trim(0,-1).Subtitle(Tit)
Return StackVertical(c).AudioDubEx(c)
}
Function SpotLess_UV(clip c,int "radt",int "thsad",int "thsad2",int "BlkSz",Int "Olap",bool "tm",Bool "glob",Float "bBlur") {
# In and Out YV24
c.SeparateFields.SelectEven.AssumeFrameBased
ue_chroma = UToY.SpotLess(radt=radt,thsad=thsad,thsad2=thsad2,chroma=false,blksz=blksz,olap=olap,tm=tm,glob=glob,bblur=bblur)
ve_chroma = VToY.SpotLess(radt=radt,thsad=thsad,thsad2=thsad2,chroma=false,blksz=blksz,olap=olap,tm=tm,glob=glob,bblur=bblur)
ev_filtered=YToUV(ue_chroma, ve_chroma) # Y = 50% Grey
###
c.SeparateFields.SelectOdd.AssumeFrameBased
uo_chroma = UToY.SpotLess(radt=radt,thsad=thsad,thsad2=thsad2,chroma=false,blksz=blksz,olap=olap,tm=tm,glob=glob,bblur=bblur)
vo_chroma = VToY.SpotLess(radt=radt,thsad=thsad,thsad2=thsad2,chroma=false,blksz=blksz,olap=olap,tm=tm,glob=glob,bblur=bblur)
od_filtered=YToUV(uo_chroma, vo_chroma) # Y = 50% Grey
###
Interleave(ev_filtered,od_filtered)
AssumeFieldBased.weave
MergeLuma(c)
}
Function SpotLess_Y(clip c,int "radt",int "thsad",int "thsad2",int "BlkSz",Int "Olap",bool "tm",Bool "glob",Float "bBlur") {
# In and Out YV24
c.SeparateFields.SelectEven.AssumeFrameBased
e_Y = SpotLess(radt=radt,thsad=thsad,thsad2=thsad2,chroma=false,blksz=blksz,olap=olap,tm=tm,glob=glob,bblur=bblur)
###
c.SeparateFields.SelectOdd.AssumeFrameBased
o_Y = SpotLess(radt=radt,thsad=thsad,thsad2=thsad2,chroma=false,blksz=blksz,olap=olap,tm=tm,glob=glob,bblur=bblur)
Interleave(e_Y,o_Y)
AssumeFieldBased.weave
MergeChroma(c)
}
EDIT: Or, alternative.
AviSource(".\sample-sages_po.avi") # HUFFYUV YUY2
Assumetff()
ConvertToYV24(Interlaced=True) # we're gonna Proc in YV24 [or YV16]
###############################################
####### CONFIG ###############################
###############################################
BOBBER = "Bob" # Some Bob, eg "Bob()" or "" = no bob
DBLRATE= false # Only used if BOBBER != "". True=doublerate progressive, else re-interlaced
### Bob, No Bob, will require different sets of args.
RADT = 6
ThSAD = 1000
ThSAD2 = 5000
PEL = 2
CHROMA = false
BLKSZ = 8
OLAP = 4
TM = false
GLOB = True
BBLUR = 0.6
############### END CONFIG #########
Original=Last
(BOBBER!="")
\ ? SpotLessI(Bobber,DBLRATE,RadT,ThSAD,ThSAD2,pel,chroma,BlkSz,Olap,tm,glob,bBlur)
\ : SpotLess2i2(RadT,ThSAD,ThSAD2,pel,chroma,BlkSz,Olap,tm,glob,bBlur)
ConvertToYUY2(Interlaced=(BOBBER=="" || !DBLRATE))
Return last
Function SpotLessI(clip c,String "Bobber",Bool "DblRate",int "RadT",int "ThSAD",int "ThSAD2",int "pel",bool "chroma", int "BlkSz",Int "Olap",bool "tm",Bool "glob",Float "bBlur") {
/*
SpotLess use on Interlaced material.
Input requires correct parity, use AssumeTFF/AssumeBFF before use.
RadT etc applied to Bobbed fields rather than frames, Might want to use at least RadT=2 (default is 1).
*/
c
Bobber = Default(Bobber,"Bob") # Your Favourite Bob deinterlacer whotsit
DblRate=Default(DblRate,False)
Last.Eval(Bobber)
SpotLess(RadT,ThSAD,ThSAD2,pel,chroma,BlkSz,Olap,tm,glob,bBlur)
Return (DblRate) ? Last : SeparateFields.SelectEvery(4,0,3).Weave
}
Function SpotLess2i2(clip c,int "RadT",int "ThSAD",int "ThSAD2",int "pel",bool "chroma", int "BlkSz",Int "Olap",bool "tm",Bool "glob",Float "bBlur") {
/*
SpotLess use on Interlaced material, fields filtered separately.
Input requires correct parity, use AssumeTFF/AssumeBFF before use.
*/
c
e=Separatefields.SelectEven.AssumeFrameBased.SpotLess(RadT,ThSAD,ThSAD2,pel,chroma,BlkSz,Olap,tm,glob,bBlur)
o=Separatefields.SelectOdd.AssumeFrameBased.SpotLess(RadT,ThSAD,ThSAD2,pel,chroma,BlkSz,Olap,tm,glob,bBlur)
Return interleave(e.AssumeFieldBased,o.AssumeFieldBased).Weave
}
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.