yup
11th March 2012, 14:22
mammo1789!
I try Your short clip with thicknessline=3,2,1 and see at some frames removing lines (not all).
Script can remove no more than 2 sequential lines at time line. If have 4 sequential lines at time line need 2 or 3 pass.
Also try new version
Global thicknessline=2# thickness horizontal spike in pixels at field scale (not frame)
Global radvertmed=2*thicknessline-1
Global distser=25# distance between short lines
Global halflength=3# detect line longer 2*halflength+1 pixels
#SetMemoryMax(768)
#SetMTMode(3,4)
source=AVISource("selnew.avi")
#source file
#SetMTMode(2,4)
source=source.AssumeTFF().ConvertToYV12(interlaced=true)
bobnn=source.nnedi3(field=-2,threads=1)
# bobbing for better motion estimation
bobnnmed=bobnn.mt_luts(bobnn,mode="median",pixels=mt_rectangle(0,radvertmed),U=3,V=3)
# vertical median filter
bobnnmedf=bobnnmed.dfttest(tbsize=1,ftype=1,sbsize=8,sosize=6,sigma=1000,U=false,V=false)
#dft filter remove segregation after median vertical filter
super=MSuper(bobnn)
superf=MSuper(bobnnmedf,chroma=false)
bw1 = MAnalyse(superf, blksize=8, isb = true, delta = 2, overlap=4, dct=5,chroma=false)
bw2 = MAnalyse(superf, blksize=8, isb = true, delta = 4, overlap=4, dct=5,chroma=false)
fw1 = MAnalyse(superf, blksize=8, isb = false,delta = 2, overlap=4, dct=5,chroma=false)
fw2 = MAnalyse(superf, blksize=8, isb = false,delta = 4, overlap=4, dct=5,chroma=false)
bc1 = MCompensate(bobnn, super, bw1, thSAD=16000, thSCD1=16000)
bc2 = MCompensate(bobnn, super, bw2, thSAD=16000, thSCD1=16000)
fc1 = MCompensate(bobnn, super, fw1, thSAD=16000, thSCD1=16000)
fc2 = MCompensate(bobnn, super, fw2, thSAD=16000, thSCD1=16000)
# motion estimation on filtered and compensating on source
bwabs1=mt_lutxy(bobnn,bc1,"x y - abs")
bwabs2=mt_lutxy(bobnn,bc2,"x y - abs")
fwabs1=mt_lutxy(bobnn,fc1,"x y - abs")
fwabs2=mt_lutxy(bobnn,fc2,"x y - abs")
# calculation absolute difference between source and compensated
SDIc=SDIAdapt(bwabs1,fwabs1)
SDIb=SDIAdapt(bwabs1,bwabs2)
SDIf=SDIAdapt(fwabs1,fwabs2)
# calculation spike detection index for center, forwad and backward
mb1sad=bobnnmedf.MMask(bw1,kind=1,ml=100,Ysc=255, thSCD1=16000)
mb2sad=bobnnmedf.MMask(bw2,kind=1,ml=100,Ysc=255, thSCD1=16000)
mf1sad=bobnnmedf.MMask(fw1,kind=1,ml=100,Ysc=255, thSCD1=16000)
mf2sad=bobnnmedf.MMask(fw2,kind=1,ml=100,Ysc=255, thSCD1=16000)
# calculating SAD for filtered for estimation better choice for motion compensation
centersad=mt_logic(mf1sad,mb1sad,"max")#,U=2,V=2)
# maximum SAD from forward and backward measure for quality center compensation
bwsad=mt_logic(mb1sad,mb2sad,"max")
#for backward compensation
fwsad=mt_logic(mf1sad,mf2sad,"max")
#for forward compensation
centermask=mt_invert(centersad)
bwmask=mt_invert(bwsad)
fwmask=mt_invert(fwsad)
# inverting mask for using mt_merge
mcfcenter=clense(bc1, bobnn,fc1,increment=0, grey=false)
mcfbw=clense(bc1, bobnn,bc2,increment=0, grey=false)
mcffw=clense(fc1, bobnn,fc2,increment=0, grey=false)
# motion compensated median filtering for center, backward and forward compensation
#
# sort SAD for finding better motion compensated median filtering, this approach can use without SDI for pixels and 1 line thickness stripes
mt_logic(mt_lutxy(centersad,bwsad,"x y <= "), mt_lutxy(centersad,fwsad,"x y <="),"and")
maskcentersad=mt_lutxy(last,centersad,"x 255 y - 0 ?")
# center filtered
mt_logic(mt_lutxy(bwsad,centersad,"x y < "), mt_lutxy(bwsad,fwsad,"x y <="),"and")
maskbwsad=mt_lutxy(last,bwsad,"x 255 y - 0 ?")
# backward filtered
mt_logic(mt_lutxy(fwsad,centersad,"x y < "), mt_lutxy(fwsad,bwsad,"x y < "),"and")
maskfwsad=mt_lutxy(last,fwsad,"x 255 y - 0 ?")
# forward filtered
#
mcfmaskedsad=mt_merge(bobnnmed,mcfbw,maskbwsad,luma=true)
mcfmaskedsad=mt_merge(mcfmaskedsad,mcffw,maskfwsad,luma=true)
mcfcentersad=mt_merge(mcfmaskedsad,mcfcenter,maskcentersad,luma=true)
#best value based on 3 motion compensated median time filtered value and spatial filtered
# where motion compensation bad, work only for one sequintial frame with spike
mcfbwsad=mt_merge(bobnnmed,mcfbw,maskbwsad,luma=true)
mcffwsad=mt_merge(bobnnmed,mcffw,maskfwsad,luma=true)
# backward and forward compensated full for SDI approach and spatial filtered where motion compensation bad
#end sort SAD
#
#
# sort SDI for choose center, forward or forward compensation work with 2 sequential frames, for 3 need 2 pass filtering, for 4 3 pass
maskcentersdi=mt_logic(mt_logic(mt_lutxy(SDIc,SDIb,"x y >= "), mt_lutxy(SDIc,SDIf,"x y >="),"and"),SDIc,"and").mt_lut("x 255 0 ?")
# center SDI
maskbwsdi=mt_logic(mt_lutxy(SDIb,SDIc,"x y > "), mt_lutxy(SDIb,SDIf,"x y >="),"and").mt_lut("x 255 0 ?")
# backward SDI
maskfwsdi=mt_logic(mt_lutxy(SDIf,SDIc,"x y > "), mt_lutxy(SDIf,SDIb,"x y >"),"and").mt_lut("x 255 0 ?")
# forward SDI
#
maskedsdi=mt_merge(bobnn,mcfcentersad,maskcentersdi,luma=true)
maskedsdi=mt_merge(maskedsdi,mcffwsad,maskfwsdi,luma=true)
maskedsdi=mt_merge(maskedsdi,mcfbwsad,maskbwsdi,luma=true)
#end sort SDI
#
# this place for repair now I am thinking
fieldmaskedsdi=maskedsdi.AssumeTFF().SeparateFields().SelectEvery(4,0,3)
#fieldmaskedsdi=SDIc.AssumeTFF().SeparateFields().SelectEvery(4,0,3)
StackVertical(Separatefields(source),fieldmaskedsdi,mt_makediff(fieldmaskedsdi,Separatefields(source),u=3,v=3))
#StackVertical(Separatefields(source),mt_makediff(fieldmaskedsdi,Separatefields(source),u=3,v=3))
#Weave(fieldmaskedsdi)
# some kind comparing and weave for interlaced source, may be at double rate and for second pass not need bobbing
# Spike Detection Function
#
function SDIAdapt(clip b1,clip b2)
{
threshsp=10
# threshold for pixels value absolute difference from 2 sequitial frames for spike detection
THP=string(threshsp)
threshavg=2
# threshold how much times actual SDI greater avearage and decimated SDI for remove false alarm for bad motion compensation
THAVG=string(threshavg)
SDI=mt_lutxy(b1,b2,"x "+THP+" > y "+THP+" > | 1 x y - x y + / abs - 255 * 0 ? ")
# SDI calculation
SDIavg=SDI.mt_luts(SDI,mode="avg",pixels=mt_square(5))
# SDI averaging
SDIAvgblk=SDIavg.PointResize(90,72)# for PAL (90,72), FOR NTSC (90,60)
# decimation
SDIavgblkX=SDIAvgblk.mt_luts(SDIAvgblk,mode="median",pixels="1 -1 0 0 -1 1 1 1 -1 -1")
# median point at X position
SDIavgblkCross=SDIAvgblk.mt_luts(SDIAvgblk,mode="median",pixels="1 0 0 0 -1 0 0 1 0 -1")
#median point at Cross position
SDIAvgblk=clense(SDIAvgblk,SDIavgblkCross,SDIavgblkX,increment=0, grey=true).mt_lut("x")
# multi median filtering for remove false alarm SDI
SDIavg=SDIAvgblk.PointResize(720,576)# for PAL (720,576), FOR NTSC (720,480)
# backward resize to original frame size
SDIad=mt_lutxy(SDI,SDIavg,"x "+THAVG+" y * > x 128 > & 255 0 ?")
# comparing with actual SDI and if greater it is real spike, value 128 can increase to 192
# be carefull I can not find this at original paper, big value can loose spike, small false alarm
SDIad = (radvertmed>1) ? SDIad.mt_luts(SDIad,mode="median",pixels=mt_rectangle(0,radvertmed-1)) : SDIad
# rectangle size could one less than for bobnnmed, for thinner lines need additional pass with thiknessline=thicknessline-1 until thicknessline=1
SDIad = SDIad.mt_luts(SDIad,mode="median",pixels=mt_rectangle(thicknessline,0))
#remove line shotter than thicknessline+1
SDIadleft=SDIad.mt_luts(SDIad,mode="max",pixels=mt_freerectangle(-distser,0,0,0))
# fill distser pixels from spike left side
SDIadright=SDIad.mt_luts(SDIad,mode="max",pixels=mt_freerectangle(0,0,distser,0))
# fill distser pixels from spike right side
SDIadser=mt_logic(SDIadleft,SDIadright,"min")
# if pixels exist at SDIadleft and SDIadright fill pixels between 2 short lines
SDIadser = (radvertmed>1) ? SDIadser.mt_luts(SDIadser,mode="median",pixels=mt_rectangle(0,radvertmed-1)) : SDIadser
# ADDITIONAL VERTICAL MEDIAN FILTER FOR REMOVE THIN JOIN PART
SDImask=SDIadser.mt_luts(SDIadser,mode="min",pixels=mt_rectangle(halflength,0))
# remove spikes shorter than 2*halflength+1 pixels tune for source
SDImask=SDImask.mt_luts(SDImask,mode="max",pixels=mt_rectangle(halflength,0))
# expand after shrinking
SDIad=mt_logic(SDIad,SDImask,"min")
# combination source and adapting SDI for better robustness
# SDIad = SDIad.mt_luts(SDIad,mode="median",pixels=mt_rectangle(thicknessline,0))
# additional remove short spikes which can be artefacts
return(SDIad)
}
Now I am not ready, but result better than before.
yup.
I try Your short clip with thicknessline=3,2,1 and see at some frames removing lines (not all).
Script can remove no more than 2 sequential lines at time line. If have 4 sequential lines at time line need 2 or 3 pass.
Also try new version
Global thicknessline=2# thickness horizontal spike in pixels at field scale (not frame)
Global radvertmed=2*thicknessline-1
Global distser=25# distance between short lines
Global halflength=3# detect line longer 2*halflength+1 pixels
#SetMemoryMax(768)
#SetMTMode(3,4)
source=AVISource("selnew.avi")
#source file
#SetMTMode(2,4)
source=source.AssumeTFF().ConvertToYV12(interlaced=true)
bobnn=source.nnedi3(field=-2,threads=1)
# bobbing for better motion estimation
bobnnmed=bobnn.mt_luts(bobnn,mode="median",pixels=mt_rectangle(0,radvertmed),U=3,V=3)
# vertical median filter
bobnnmedf=bobnnmed.dfttest(tbsize=1,ftype=1,sbsize=8,sosize=6,sigma=1000,U=false,V=false)
#dft filter remove segregation after median vertical filter
super=MSuper(bobnn)
superf=MSuper(bobnnmedf,chroma=false)
bw1 = MAnalyse(superf, blksize=8, isb = true, delta = 2, overlap=4, dct=5,chroma=false)
bw2 = MAnalyse(superf, blksize=8, isb = true, delta = 4, overlap=4, dct=5,chroma=false)
fw1 = MAnalyse(superf, blksize=8, isb = false,delta = 2, overlap=4, dct=5,chroma=false)
fw2 = MAnalyse(superf, blksize=8, isb = false,delta = 4, overlap=4, dct=5,chroma=false)
bc1 = MCompensate(bobnn, super, bw1, thSAD=16000, thSCD1=16000)
bc2 = MCompensate(bobnn, super, bw2, thSAD=16000, thSCD1=16000)
fc1 = MCompensate(bobnn, super, fw1, thSAD=16000, thSCD1=16000)
fc2 = MCompensate(bobnn, super, fw2, thSAD=16000, thSCD1=16000)
# motion estimation on filtered and compensating on source
bwabs1=mt_lutxy(bobnn,bc1,"x y - abs")
bwabs2=mt_lutxy(bobnn,bc2,"x y - abs")
fwabs1=mt_lutxy(bobnn,fc1,"x y - abs")
fwabs2=mt_lutxy(bobnn,fc2,"x y - abs")
# calculation absolute difference between source and compensated
SDIc=SDIAdapt(bwabs1,fwabs1)
SDIb=SDIAdapt(bwabs1,bwabs2)
SDIf=SDIAdapt(fwabs1,fwabs2)
# calculation spike detection index for center, forwad and backward
mb1sad=bobnnmedf.MMask(bw1,kind=1,ml=100,Ysc=255, thSCD1=16000)
mb2sad=bobnnmedf.MMask(bw2,kind=1,ml=100,Ysc=255, thSCD1=16000)
mf1sad=bobnnmedf.MMask(fw1,kind=1,ml=100,Ysc=255, thSCD1=16000)
mf2sad=bobnnmedf.MMask(fw2,kind=1,ml=100,Ysc=255, thSCD1=16000)
# calculating SAD for filtered for estimation better choice for motion compensation
centersad=mt_logic(mf1sad,mb1sad,"max")#,U=2,V=2)
# maximum SAD from forward and backward measure for quality center compensation
bwsad=mt_logic(mb1sad,mb2sad,"max")
#for backward compensation
fwsad=mt_logic(mf1sad,mf2sad,"max")
#for forward compensation
centermask=mt_invert(centersad)
bwmask=mt_invert(bwsad)
fwmask=mt_invert(fwsad)
# inverting mask for using mt_merge
mcfcenter=clense(bc1, bobnn,fc1,increment=0, grey=false)
mcfbw=clense(bc1, bobnn,bc2,increment=0, grey=false)
mcffw=clense(fc1, bobnn,fc2,increment=0, grey=false)
# motion compensated median filtering for center, backward and forward compensation
#
# sort SAD for finding better motion compensated median filtering, this approach can use without SDI for pixels and 1 line thickness stripes
mt_logic(mt_lutxy(centersad,bwsad,"x y <= "), mt_lutxy(centersad,fwsad,"x y <="),"and")
maskcentersad=mt_lutxy(last,centersad,"x 255 y - 0 ?")
# center filtered
mt_logic(mt_lutxy(bwsad,centersad,"x y < "), mt_lutxy(bwsad,fwsad,"x y <="),"and")
maskbwsad=mt_lutxy(last,bwsad,"x 255 y - 0 ?")
# backward filtered
mt_logic(mt_lutxy(fwsad,centersad,"x y < "), mt_lutxy(fwsad,bwsad,"x y < "),"and")
maskfwsad=mt_lutxy(last,fwsad,"x 255 y - 0 ?")
# forward filtered
#
mcfmaskedsad=mt_merge(bobnnmed,mcfbw,maskbwsad,luma=true)
mcfmaskedsad=mt_merge(mcfmaskedsad,mcffw,maskfwsad,luma=true)
mcfcentersad=mt_merge(mcfmaskedsad,mcfcenter,maskcentersad,luma=true)
#best value based on 3 motion compensated median time filtered value and spatial filtered
# where motion compensation bad, work only for one sequintial frame with spike
mcfbwsad=mt_merge(bobnnmed,mcfbw,maskbwsad,luma=true)
mcffwsad=mt_merge(bobnnmed,mcffw,maskfwsad,luma=true)
# backward and forward compensated full for SDI approach and spatial filtered where motion compensation bad
#end sort SAD
#
#
# sort SDI for choose center, forward or forward compensation work with 2 sequential frames, for 3 need 2 pass filtering, for 4 3 pass
maskcentersdi=mt_logic(mt_logic(mt_lutxy(SDIc,SDIb,"x y >= "), mt_lutxy(SDIc,SDIf,"x y >="),"and"),SDIc,"and").mt_lut("x 255 0 ?")
# center SDI
maskbwsdi=mt_logic(mt_lutxy(SDIb,SDIc,"x y > "), mt_lutxy(SDIb,SDIf,"x y >="),"and").mt_lut("x 255 0 ?")
# backward SDI
maskfwsdi=mt_logic(mt_lutxy(SDIf,SDIc,"x y > "), mt_lutxy(SDIf,SDIb,"x y >"),"and").mt_lut("x 255 0 ?")
# forward SDI
#
maskedsdi=mt_merge(bobnn,mcfcentersad,maskcentersdi,luma=true)
maskedsdi=mt_merge(maskedsdi,mcffwsad,maskfwsdi,luma=true)
maskedsdi=mt_merge(maskedsdi,mcfbwsad,maskbwsdi,luma=true)
#end sort SDI
#
# this place for repair now I am thinking
fieldmaskedsdi=maskedsdi.AssumeTFF().SeparateFields().SelectEvery(4,0,3)
#fieldmaskedsdi=SDIc.AssumeTFF().SeparateFields().SelectEvery(4,0,3)
StackVertical(Separatefields(source),fieldmaskedsdi,mt_makediff(fieldmaskedsdi,Separatefields(source),u=3,v=3))
#StackVertical(Separatefields(source),mt_makediff(fieldmaskedsdi,Separatefields(source),u=3,v=3))
#Weave(fieldmaskedsdi)
# some kind comparing and weave for interlaced source, may be at double rate and for second pass not need bobbing
# Spike Detection Function
#
function SDIAdapt(clip b1,clip b2)
{
threshsp=10
# threshold for pixels value absolute difference from 2 sequitial frames for spike detection
THP=string(threshsp)
threshavg=2
# threshold how much times actual SDI greater avearage and decimated SDI for remove false alarm for bad motion compensation
THAVG=string(threshavg)
SDI=mt_lutxy(b1,b2,"x "+THP+" > y "+THP+" > | 1 x y - x y + / abs - 255 * 0 ? ")
# SDI calculation
SDIavg=SDI.mt_luts(SDI,mode="avg",pixels=mt_square(5))
# SDI averaging
SDIAvgblk=SDIavg.PointResize(90,72)# for PAL (90,72), FOR NTSC (90,60)
# decimation
SDIavgblkX=SDIAvgblk.mt_luts(SDIAvgblk,mode="median",pixels="1 -1 0 0 -1 1 1 1 -1 -1")
# median point at X position
SDIavgblkCross=SDIAvgblk.mt_luts(SDIAvgblk,mode="median",pixels="1 0 0 0 -1 0 0 1 0 -1")
#median point at Cross position
SDIAvgblk=clense(SDIAvgblk,SDIavgblkCross,SDIavgblkX,increment=0, grey=true).mt_lut("x")
# multi median filtering for remove false alarm SDI
SDIavg=SDIAvgblk.PointResize(720,576)# for PAL (720,576), FOR NTSC (720,480)
# backward resize to original frame size
SDIad=mt_lutxy(SDI,SDIavg,"x "+THAVG+" y * > x 128 > & 255 0 ?")
# comparing with actual SDI and if greater it is real spike, value 128 can increase to 192
# be carefull I can not find this at original paper, big value can loose spike, small false alarm
SDIad = (radvertmed>1) ? SDIad.mt_luts(SDIad,mode="median",pixels=mt_rectangle(0,radvertmed-1)) : SDIad
# rectangle size could one less than for bobnnmed, for thinner lines need additional pass with thiknessline=thicknessline-1 until thicknessline=1
SDIad = SDIad.mt_luts(SDIad,mode="median",pixels=mt_rectangle(thicknessline,0))
#remove line shotter than thicknessline+1
SDIadleft=SDIad.mt_luts(SDIad,mode="max",pixels=mt_freerectangle(-distser,0,0,0))
# fill distser pixels from spike left side
SDIadright=SDIad.mt_luts(SDIad,mode="max",pixels=mt_freerectangle(0,0,distser,0))
# fill distser pixels from spike right side
SDIadser=mt_logic(SDIadleft,SDIadright,"min")
# if pixels exist at SDIadleft and SDIadright fill pixels between 2 short lines
SDIadser = (radvertmed>1) ? SDIadser.mt_luts(SDIadser,mode="median",pixels=mt_rectangle(0,radvertmed-1)) : SDIadser
# ADDITIONAL VERTICAL MEDIAN FILTER FOR REMOVE THIN JOIN PART
SDImask=SDIadser.mt_luts(SDIadser,mode="min",pixels=mt_rectangle(halflength,0))
# remove spikes shorter than 2*halflength+1 pixels tune for source
SDImask=SDImask.mt_luts(SDImask,mode="max",pixels=mt_rectangle(halflength,0))
# expand after shrinking
SDIad=mt_logic(SDIad,SDImask,"min")
# combination source and adapting SDI for better robustness
# SDIad = SDIad.mt_luts(SDIad,mode="median",pixels=mt_rectangle(thicknessline,0))
# additional remove short spikes which can be artefacts
return(SDIad)
}
Now I am not ready, but result better than before.
yup.