Log in

View Full Version : Analogue Camcorder Capture Denoising


Pages : [1] 2

Mr_Odwin
10th February 2007, 19:45
I'm having trouble with a capture I've made of some home camcorder footage, in that I don't really know how to clean it up.

Here's a 2 second Huffyuv sample (18mb):
http://homepages.nildram.co.uk/~pike/CapSeg.avi

There seems to be a lot of noise, and it just looks like there is lots of kind of blue/purple/orange colour everywhere.
The best results I've had are with
FFT3DFilter(sigma=1.8,sharpen=0.2,ow=24,oh=24,interlaced=true)


Just wondering if anyone else has suggestions?

Blue_MiSfit
10th February 2007, 22:30
Downloaded your sample.. I think 2 instances of fft3dfilter/fft3dgpu will be in order to clean and sharpen luma and chroma separately.

More in a minute or two..

[edit]
cute baby :D

So yeah, the blue/purple/orange colour everywhere is chroma noise. We need to denoise it heavily. The shot is also severely under-exposed, so hdr-agc might help a lot!

It's likely that you will need to deinterlace this footage at some point (if you plan on encoding to MPEG-4), so we might as well get that set up right now too...

Here's a suggested place to start with a script:

setmemorymax(512) #or whatever is apropriate
import(plugdir+"removedirt.avs")
loadplugin(plugdir+"fft3dgpu.dll")
loadplugin(plugdir+"agc.dll")
loadplugin(plugdir+"eedi2.dll")
loadplugin(plugdir+"removedirtsse2.dll")

avisource("C:\capseg.avi")

edeintted = last.AssumeTFF().SeparateFields().SelectEven().EEDI2(field=-1)
TDeint(order=1,edeint=edeintted)

ConvertToYV12()

removedirt()

hdragc(max_sat=1.0, corrector=1.0)

fft3dgpu(plane=3, sigma=7)
fft3dgpu(plane=0, sigma=3, sharpen=.5)


The RemoveDirt bit is optional. It's VERY strong, and I think it kills nose very effectively while preserving what little detail is in this source.

Some comparisons for you:

Raw Source (interlaced)
http://img77.imageshack.us/img77/2661/source0000lq1.png (http://imageshack.us)

Deinterlaced, shown script, but with no removedirt()
http://img504.imageshack.us/img504/9780/tweaked20000lr3.png (http://imageshack.us)

Shown script:
http://img70.imageshack.us/img70/221/tweaked0000be9.png (http://imageshack.us)

Anyway, I wasn't able to totally get rid of those evil purple spots. They're very nasty.

Maybe somebody else can help!

The script isn't fast (3-4 fps into HuffYUV on my machine), but It's not too bad. RemoveDirt could likely be tuned a bit, I'm a total noob with it.

Video Link (http://www.oxedion.com/index.php/download/4723486e255c41e18db4724ed5eae232)

~MiSfit

Mr_Odwin
10th February 2007, 23:39
Thanks, that's a great improvement.
The end product is dvd/mpeg2 (I should have explained that initially) so I removed the two lines concerned with deinterlacing but everything else is great.

Blue_MiSfit
11th February 2007, 00:44
Ok that's all good, but be sure to separate fields before doing hdragc and fft3dgpu, and weave after :)

Pookie
11th February 2007, 01:24
100% DidéeScript - You might want to continue tweaking the color splotches a bit. Oh yeah, better have a Cray :D

http://img145.imageshack.us/img145/5071/exampleyd2.th.png-- (http://img145.imageshack.us/my.php?image=exampleyd2.png)http://img402.imageshack.us/img402/5185/ex2zs5.th.png (http://img402.imageshack.us/my.php?image=ex2zs5.png)

setmemorymax(512)

LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\fluxsmooth.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\MedianBlur.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\mt_masktools.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\MVTools.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\RemoveGrain.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\Repair.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\TTempSmooth.dll")

aviSource("E:\CapSeg.avi")
converttoyv12()

Bob(0,0.5)

bobbed = last
base = last.minblur(2).FluxSmoothT(9)

bw4_vec = base.MVAnalyse(isb=true, truemotion=false,delta=4,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
bw3_vec = base.MVAnalyse(isb=true, truemotion=false,delta=3,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
bw2_vec = base.MVAnalyse(isb=true, truemotion=false,delta=2,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
bw1_vec = base.MVAnalyse(isb=true, truemotion=false,delta=1,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw1_vec = base.MVAnalyse(isb=false, truemotion=false,delta=1,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw2_vec = base.MVAnalyse(isb=false, truemotion=false,delta=2,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw3_vec = base.MVAnalyse(isb=false, truemotion=false,delta=3,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw4_vec = base.MVAnalyse(isb=false, truemotion=false,delta=4,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)

bw4_comp = bobbed.MVCompensate(bw4_vec,idx=2)
bw3_comp = bobbed.MVCompensate(bw3_vec,idx=2)
bw2_comp = bobbed.MVCompensate(bw2_vec,idx=2)
bw1_comp = bobbed.MVCompensate(bw1_vec,idx=2)
fw1_comp = bobbed.MVCompensate(fw1_vec,idx=2)
fw2_comp = bobbed.MVCompensate(fw2_vec,idx=2)
fw3_comp = bobbed.MVCompensate(fw3_vec,idx=2)
fw4_comp = bobbed.MVCompensate(fw4_vec,idx=2)

Interleave(bw4_comp,bw3_comp,bw2_comp,bw1_comp,bobbed,fw1_comp,fw2_comp,fw3_comp,fw4_comp)
MedianBlurT(0,0,0,4)
SelectEvery(9,4)

base2 = last
bobbed2 = last

bw4_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=4,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
bw3_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=3,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
bw2_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=2,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
bw1_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=1,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw1_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=1,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw2_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=2,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw3_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=3,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw4_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=4,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)

bw4_comp2 = bobbed2.MVCompensate(bw4_vec2,idx=3)
bw3_comp2 = bobbed2.MVCompensate(bw3_vec2,idx=3)
bw2_comp2 = bobbed2.MVCompensate(bw2_vec2,idx=3)
bw1_comp2 = bobbed2.MVCompensate(bw1_vec2,idx=3)
fw1_comp2 = bobbed2.MVCompensate(fw1_vec2,idx=3)
fw2_comp2 = bobbed2.MVCompensate(fw2_vec2,idx=3)
fw3_comp2 = bobbed2.MVCompensate(fw3_vec2,idx=3)
fw4_comp2 = bobbed2.MVCompensate(fw4_vec2,idx=3)

Interleave(bw4_comp2,bw3_comp2,bw2_comp2,bw1_comp2,bobbed2,fw1_comp2,fw2_comp2,fw3_comp2,fw4_comp2)
ttempsmooth(4,8,8,2,2,strength=5,pfclip=last.RemoveGrain(11))
SelectEvery(9,4)

maxx = bobbed.mt_logic(bw1_comp,"max")
\ .mt_logic(fw1_comp,"max")
minn = bobbed.mt_logic(bw1_comp,"min")
\ .mt_logic(fw1_comp,"min")
#.mt_logic(bw2_comp,"max").mt_logic(bw3_comp,"max")
#.mt_logic(fw2_comp,"max").mt_logic(fw3_comp,"max")
#.mt_logic(bw2_comp,"min").mt_logic(bw3_comp,"min")
#.mt_logic(fw2_comp,"min").mt_logic(fw3_comp,"min")

ssharp = mt_lutxy(last,last.RemoveGrain(11), \
"x x y - abs 12 / 1 4 / ^ 12 * x y - 2 ^ x y - 2 ^ 2.3 + / * x y - x y - abs 0.0001 + / * 1 x y - abs 16 / 1 4 / ^ + / +",U=2,V=2)

ssharp.mt_Clamp(maxx,minn,0,0,U=2,V=2)

SeparateFields().SelectEvery(4,0,3).Weave() # before or after,

interleave( selectevery(5,0).FluxSmoothT(7),selectevery(5,1).FluxSmoothT(7),
\ selectevery(5,2).FluxSmoothT(7),selectevery(5,3).FluxSmoothT(7),
\ selectevery(5,4).FluxSmoothT(7) )

# SeparateFields().SelectEvery(4,0,3).Weave() # that's a question

return(last)

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

# Nifty Gauss/Median combination
function MinBlur(clip clp, int r, int "uv")
{
uv = default(uv,3)
uv2 = (uv==2) ? 1 : uv
rg4 = (uv==3) ? 4 : -1
rg11 = (uv==3) ? 11 : -1
rg20 = (uv==3) ? 20 : -1
medf = (uv==3) ? 1 : -200

RG11D = (r==1) ? mt_MakeDiff(clp,clp.RemoveGrain(11,rg11),U=uv2,V=uv2)
\ : (r==2) ? mt_MakeDiff(clp,clp.RemoveGrain(11,rg11).RemoveGrain(11,rg11),U=uv2,V=uv2)
\ : mt_MakeDiff(clp,clp.RemoveGrain(11,rg11).RemoveGrain(20,rg20).RemoveGrain(20,rg20),U=uv2,V=uv2)
RG4D = (r==1) ? mt_MakeDiff(clp,clp.RemoveGrain(4,rg4),U=uv2,V=uv2)
\ : (r==2) ? mt_MakeDiff(clp,clp.medianblur(2,2*medf,2*medf),U=uv2,V=uv2)
\ : mt_MakeDiff(clp,clp.medianblur(3,3*medf,3*medf),U=uv2,V=uv2)
DD = mt_lutxy(RG11D,RG4D,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=uv2,V=uv2)
(r==0) ? clp : clp.mt_MakeDiff(DD,U=uv,V=uv)
return(last)
}
#end

Blue_MiSfit
11th February 2007, 02:59
<3 didee and pookie... wow thats an amazing script. No joke. Just throw in an hdragc(max_sat=1.0, corrector=1.0) to brighten things up a bit and voila.

Pookie
11th February 2007, 03:17
I don't know how Didée does it. I wonder if his quip about aliens in UFOs giving him the scripts has an air of truth :p

Boulder
11th February 2007, 10:51
For a small speed gain, substitute Bob(0,0.5) with LeakKernelBob(order=x,threshold=0), replace x with 0 for BFF or 1 for TFF video.

If you have a dual-core CPU and a lot of memory, you might want to try splitting the video in two halves, process them simultaneously and save to a lossless format such as HuffYUV. Then combine the lossless clips and encode to MPEG2.

Spuds
12th February 2007, 04:44
I have some basic question on removing noise from an analog capture. I have a VHS tape which I pulled onto the computer with a Canopus capture card. The source has lots of noise and I have several scripts which have worked wonders on footage but in all my reading have become somewhat confused.

First the video is 100% interlaced, 29.97 frame after frame of interlaced beauty, be glad to upload some footage if anyone was interested. I’ve read that moving this to a progressive source prior to running any spatial filters or tempo-spatial filters is the proper thing to do. My intention is to convert the old VHS tape to DVD so it in the end I will re-interlace the cleaned footage.

With a fully interlaced source and with the intention of re-interlacing the video at the end is a simple dumb bob or tdeint(mode=1) + filters + weave (or is it interleave) the correct thing to do. Am I correct that this will half the vertical resolution but double the frame rate and then return to the original frame rate and vertical resolution when I re-interlace the footage?

Would I gain in quality using a smart-bob or a motion compensated bob given I’m going back to interlaced?

I’ve been reading the forums for hours and hours and every time I think I have a grasp on things I read yet another posting or guide with more info that my poor brain is trying to deal with!

Blue_MiSfit
12th February 2007, 08:02
Not quite.

A simple SeparateFields() will return half height, double rate video.

A bob deinterlace interpolates these half height frames to full size, and compensates for the up and down bobbing effect that would be associated with simple SeparateFields().LanczosResize(720,480) - or whatever your full height is.

A dumb bob() is the fastest way of doing this, but it's pretty bad! Tdeint (mode=1) is a good way of bobbing.

I usually bob deinterlace if I have interlaced material that needs a progressive-only filter. Of course, I generally deinterlace everything anyway :)

You can probably separatefields().applyProgressiveFilter().weave() if you get my drift... In fact I think this is how you're supposed to do it...

Don't take my word for it :)

I don't care about interlaced display devices. Everything for me is for a progressive CRT, so it all gets deinterlaced :D

You may get better results with something like MVBob or another 'high powered' bobber, filtering, and then reinterlacing, but I'm not sure :) IIRC, the 'alchemist' thread was using this method for standards conversions at the max possible quality.

Welcome to doom9! You sound Intelligent and willing to learn. It's a wonderful world.

~MiSfit

Alain2
12th February 2007, 09:37
You can probably separatefields().applyProgressiveFilter().weave() if you get my drift... In fact I think this is how you're supposed to do it...
No, Didee explained this recently here (http://forum.doom9.org/showthread.php?p=931181#post931181) (especially his second long post)

Blue_MiSfit
12th February 2007, 09:49
Thanks for the link! Very informative posts.


An interlaced stream can't shouldn't be processed by spatial filters directly (because the vertical neighbor pixels in fact are temporal neighbors)


and


However, it's not a very good idea to use temporal filtering after doing SeparateFields(), because temporal neighbors then are spatially misaligned (up-down-jumping) ... in fact, temporal filtering after SeparateFields() is partially similar to spatial filtering of interlaced frames


particularly stood out to me.

Everyone should read those posts, seriously.

So it looks like bob-deinterlacing, then filtering, then re-interlacing is the way to do it!!

~MiSfit

halsboss
12th February 2007, 11:28
# SeparateFields().SelectEvery(4,0,3).Weave() # that's a question
yes it is ... if I wanted to use this script too, what would this do, return it to PAL 25i ? (ie is the output 25p or 25i without it ?)

Didée
12th February 2007, 12:14
@ halsboss: that's the 3rd part of good old "first bob, then filter, then re-weave fields back to the original interlaced format."

So yes, the line is there to return 25i if the output was 25i. If you leave it out, the script returns 50p. However, the re-weaving is already done at another place:

You snipped that line out-of-context ... the full context is
[...]
SeparateFields().SelectEvery(4,0,3).Weave() # before or after,

interleave( [a special combo here, to somehow make a 3-frame
\ temporal filter work on a looong temporal window] )

# SeparateFields().SelectEvery(4,0,3).Weave() # that's a question
[...]
I.e. the re-weaving is already done before the commented line. I just wasn't sure if it was better to re-weave before or after the special filter combo. Of course, only one of those Separate...Weave lines must be activated at once. Never both.


BTW: the script was made for a special-case video, with very strong noise, and a fully static camera ...

It uses plain bob() instead of smart bobbing, contrary to what I had said in other places. :)
Reason is that with such strong noise like the target video had, smart bobbing would have made little sense. (The smart bobber would have seen everything as 'motion', because of the noise.)

The script offers no protection at all against artefacts from erroneous motion compensation. I had left that part out because with it, the script's speed would have become, erh, incredible. (And the available means of SAD-guided protection would've been useless, with such strong noise.)

The script was OK for that particular source. For general usage, it is not recommended. It was an answer to a Q like "can *this* noise somehow be removed?", and I tried to really remove it while leaving detail intact, where other filters or combos would've done only a partial so-so noiseremoval with harmed detail.

It is not a ready-for-usage script, because artefacts during motion *will* happen at times.

Blue_MiSfit
12th February 2007, 12:15
never mind.. Didee beat me to it and offered a much more complete explanation

halsboss
12th February 2007, 12:47
Ah, thanks for the explanation Didee. Silly me, should have taken more care to spot that... just went and got all excited by the high quality of the result with that source :) Can't hurt to experiment/tinker I guess... acknowledging static camera scenario plus motion challenges plus uniqueness of this clip characteristics... whats a few trillion cpu cycles here or there :) ? Thanks for the pointer on deblocking with the other thread by the way (been very busy with work).

Chainmax
14th February 2007, 03:13
Wow, Didée's script produced some amazing results :eek:.
For what is worth, when the chroma noise is so intense that not even FFT3DFilter and/or BiFrost+DeCross can eliminate it, using TemporalSoften(x,0,y,scenechange=1,mode=2) where x is the radius and y is the strength (I usually set x to 4 and y to 60+). That was a recommendation made by scharfis_brain for dealing with a 3rd generation VHS copy compressed to DV


P.S: maybe including something like AddGrain(5,0,0) on that amazing script would help in creating an illusion of detail.

rkr1958
14th February 2007, 07:27
@Pookie & Didee' - great script! I applied it to some 1961 8mm transfer to VHS to DV. It really cleaned it up. You guys do incredible work.

@Pookie you're also right that it takes a Cray. On my machine it took approximately 7-hours to process a 3.5-minute clip. Again, great results ...

Before
http://www.knology.net/~benrunyan/2795-Pre.jpeg

After
http://www.knology.net/~benrunyan/2795-Post.jpeg

A couple of questions though ...

I tried to run the script exactly as shown in the 10th February 2007 18:24 post; however, I got an error in the MVAnalyse commands. The errors I got were that this function did not have named arguements Sharp & Overlap. I was able to run the script after I removed both these from all the MVAnalyse commands. Is this a plugin version issue or something else?

Also, in frames with motion or camera panning I get blocks as shown in this frame,

http://www.knology.net/~benrunyan/4076-Blocks.jpeg

Is this expected given the amount of cleanup or are there some adjustments I can make to minimize these blocks?

By the way, that's me (age 3) at Christmas 1961.

Boulder
14th February 2007, 07:35
You need to update your MVTools plugin. http://avisynth.org.ru/mvtools/mvtools.html

Those blocks look like errors(?) from the motion compensation.

Pookie
14th February 2007, 13:00
I hope it is that Boulder, but I believe Didée mentioned in his post above that the script would display artifacts in faster moving scenes. It seemed OK to me on the original clip of the baby, but there isn't much movement going on there. Now look at the clip of the kid running...

Thanks for your kind words, rkr1958, but the accolades belong to Didée :o ..... "Klaatu Burata Niktau":D

That exact script was used for the Avisynth hardware performance benchmark test conducted some weeks ago. If you plan on doing a lot of motion compensated denoising and deinterlacing, we discovered the Intel E6600 and the lower end E4300 were far ahead the leaders in encoding speed - almost 6 times faster than a Pentium P4 2.4 . Even RAM didn't have as much impact on performance.

Boulder
14th February 2007, 13:11
MVCompensate may produce blocking, the alternative, MVFlow, may cause distortion. Choose yer poison ;)

ChrisW77
15th February 2007, 03:55
Thats one amazing script.
I tried this script on some random vhs to DVD caps, I've been doing, and the results blew my old scripts away.
Just to ask,
Is there any way of speeding this script up ? Short of buying a 32-Core Conroe :p
Any tips ? Optimizations ?
Is there anything that can be changed to be able to use motion ?

And, how would you deinterlace, crop, and resize, right at the end ?
Say, for example, to add

LeakKernelDeint(order=1,threshold=0,sharp=true)
Crop(4,4,-4,-10,align=true)
Lanczos4Resize(640,480)

Sorry to sound a bit thick :p Still learning all this video stuff.

rkr1958
15th February 2007, 05:06
@Boulder, thanks for the MVTools update link. That did the trick.

@Pookie, I have a 2.6-Gz P4 w/hyperthreading and 1024-MB of DDR3200 (match pair, dual channel). I encoded using VirtualDub and compression with Huffyuv v2.1.1. Watching performance under task manager, memory pegged out a 1-GB but total CPU usage stayed under 55% and VirtualDub process usage stayed at 50%. Even when I changed VirtualDub process to realtime, its process usage still stayed around 50%. I interperted this (maybe incorrectly though) to mean that the amount of RAM I had was my bottleneck. So, I order another 1024-MB (matched pair) of DDR3200 sticks from newegg. So this will give me 2048-MB of DDR3200 RAM running dual channel mode. I was hoping this would give me faster encode speeds - but your findings indicate that doubling my RAM probably won't make that much of a difference. Interesting though that a core-duo CPU at 1.8-GHz w/800MHZ FSB (e.g., E4300) is six times faster than a P4 2.4-GHz.

R3Z
15th February 2007, 07:00
@Boulder, thanks for the MVTools update link. That did the trick.

@Pookie, I have a 2.6-Gz P4 w/hyperthreading and 1024-MB of DDR3200 (match pair, dual channel). I encoded using VirtualDub and compression with Huffyuv v2.1.1. Watching performance under task manager, memory pegged out a 1-GB but total CPU usage stayed under 55% and VirtualDub process usage stayed at 50%. Even when I changed VirtualDub process to realtime, its process usage still stayed around 50%. I interperted this (maybe incorrectly though) to mean that the amount of RAM I had was my bottleneck. So, I order another 1024-MB (matched pair) of DDR3200 sticks from newegg. So this will give me 2048-MB of DDR3200 RAM running dual channel mode. I was hoping this would give me faster encode speeds - but your findings indicate that doubling my RAM probably won't make that much of a difference. Interesting though that a core-duo CPU at 1.8-GHz w/800MHZ FSB (e.g., E4300) is six times faster than a P4 2.4-GHz.

Different architecture thats all.

Blue_MiSfit
15th February 2007, 07:18
Right. Still, we're not fully utilizing the Core 2 Duo with this script, given the lack of multi threading that MVTools implies... Unless this has changed recently??? I suppose you could just trim the file into two pieces and run two scripts and two instances of VirtualDub..

2GB of RAM pls. :D

~MiSfit

Boulder
15th February 2007, 07:19
Thats one amazing script.
I tried this script on some random vhs to DVD caps, I've been doing, and the results blew my old scripts away.
Just to ask,
Is there any way of speeding this script up ? Short of buying a 32-Core Conroe :p
Any tips ? Optimizations ?
Is there anything that can be changed to be able to use motion ?I don't know how important the "4 frames backward, 4 frames forward" approach is, maybe it would be effective even with a radius of 3 frames. However, I'm not the one to tweak the function at the moment.

EDIT: I also wonder whether setting chroma=false in MVAnalyse would make any difference in the motion search with a noisy source.

If you want to deinterlace the video, you must do it before any denoising. Try this script:
setmemorymax(512)

LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\fluxsmooth.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\MedianBlur.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\mt_masktools.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\MVTools.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\RemoveGrain.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\Repair.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\TTempSmooth.dll")

aviSource("E:\CapSeg.avi")
converttoyv12()

LeakKernelDeint(order=1,threshold=0,sharp=true)
Crop(4,4,-4,-10,align=true)
Lanczos4Resize(640,480)

bobbed = last
base = last.minblur(2).FluxSmoothT(9)

bw4_vec = base.MVAnalyse(isb=true, truemotion=false,delta=4,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
bw3_vec = base.MVAnalyse(isb=true, truemotion=false,delta=3,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
bw2_vec = base.MVAnalyse(isb=true, truemotion=false,delta=2,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
bw1_vec = base.MVAnalyse(isb=true, truemotion=false,delta=1,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw1_vec = base.MVAnalyse(isb=false, truemotion=false,delta=1,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw2_vec = base.MVAnalyse(isb=false, truemotion=false,delta=2,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw3_vec = base.MVAnalyse(isb=false, truemotion=false,delta=3,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw4_vec = base.MVAnalyse(isb=false, truemotion=false,delta=4,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)

bw4_comp = bobbed.MVCompensate(bw4_vec,idx=2)
bw3_comp = bobbed.MVCompensate(bw3_vec,idx=2)
bw2_comp = bobbed.MVCompensate(bw2_vec,idx=2)
bw1_comp = bobbed.MVCompensate(bw1_vec,idx=2)
fw1_comp = bobbed.MVCompensate(fw1_vec,idx=2)
fw2_comp = bobbed.MVCompensate(fw2_vec,idx=2)
fw3_comp = bobbed.MVCompensate(fw3_vec,idx=2)
fw4_comp = bobbed.MVCompensate(fw4_vec,idx=2)

Interleave(bw4_comp,bw3_comp,bw2_comp,bw1_comp,bobbed,fw1_comp,fw2_comp,fw3_comp,fw4_comp)
MedianBlurT(0,0,0,4)
SelectEvery(9,4)

base2 = last
bobbed2 = last

bw4_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=4,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
bw3_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=3,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
bw2_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=2,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
bw1_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=1,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw1_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=1,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw2_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=2,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw3_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=3,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw4_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=4,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)

bw4_comp2 = bobbed2.MVCompensate(bw4_vec2,idx=3)
bw3_comp2 = bobbed2.MVCompensate(bw3_vec2,idx=3)
bw2_comp2 = bobbed2.MVCompensate(bw2_vec2,idx=3)
bw1_comp2 = bobbed2.MVCompensate(bw1_vec2,idx=3)
fw1_comp2 = bobbed2.MVCompensate(fw1_vec2,idx=3)
fw2_comp2 = bobbed2.MVCompensate(fw2_vec2,idx=3)
fw3_comp2 = bobbed2.MVCompensate(fw3_vec2,idx=3)
fw4_comp2 = bobbed2.MVCompensate(fw4_vec2,idx=3)

Interleave(bw4_comp2,bw3_comp2,bw2_comp2,bw1_comp2,bobbed2,fw1_comp2,fw2_comp2,fw3_comp2,fw4_comp2)
ttempsmooth(4,8,8,2,2,strength=5,pfclip=last.RemoveGrain(11))
SelectEvery(9,4)

maxx = bobbed.mt_logic(bw1_comp,"max")
\ .mt_logic(fw1_comp,"max")
minn = bobbed.mt_logic(bw1_comp,"min")
\ .mt_logic(fw1_comp,"min")
#.mt_logic(bw2_comp,"max").mt_logic(bw3_comp,"max")
#.mt_logic(fw2_comp,"max").mt_logic(fw3_comp,"max")
#.mt_logic(bw2_comp,"min").mt_logic(bw3_comp,"min")
#.mt_logic(fw2_comp,"min").mt_logic(fw3_comp,"min")

ssharp = mt_lutxy(last,last.RemoveGrain(11), \
"x x y - abs 12 / 1 4 / ^ 12 * x y - 2 ^ x y - 2 ^ 2.3 + / * x y - x y - abs 0.0001 + / * 1 x y - abs 16 / 1 4 / ^ + / +",U=2,V=2)

ssharp.mt_Clamp(maxx,minn,0,0,U=2,V=2)

# SeparateFields().SelectEvery(4,0,3).Weave() # before or after,

interleave( selectevery(5,0).FluxSmoothT(7),selectevery(5,1).FluxSmoothT(7),
\ selectevery(5,2).FluxSmoothT(7),selectevery(5,3).FluxSmoothT(7),
\ selectevery(5,4).FluxSmoothT(7) )

# SeparateFields().SelectEvery(4,0,3).Weave() # that's a question

return(last)

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

# Nifty Gauss/Median combination
function MinBlur(clip clp, int r, int "uv")
{
uv = default(uv,3)
uv2 = (uv==2) ? 1 : uv
rg4 = (uv==3) ? 4 : -1
rg11 = (uv==3) ? 11 : -1
rg20 = (uv==3) ? 20 : -1
medf = (uv==3) ? 1 : -200

RG11D = (r==1) ? mt_MakeDiff(clp,clp.RemoveGrain(11,rg11),U=uv2,V=uv2)
\ : (r==2) ? mt_MakeDiff(clp,clp.RemoveGrain(11,rg11).RemoveGrain(11,rg11),U=uv2,V=uv2)
\ : mt_MakeDiff(clp,clp.RemoveGrain(11,rg11).RemoveGrain(20,rg20).RemoveGrain(20,rg20),U=uv2,V=uv2)
RG4D = (r==1) ? mt_MakeDiff(clp,clp.RemoveGrain(4,rg4),U=uv2,V=uv2)
\ : (r==2) ? mt_MakeDiff(clp,clp.medianblur(2,2*medf,2*medf),U=uv2,V=uv2)
\ : mt_MakeDiff(clp,clp.medianblur(3,3*medf,3*medf),U=uv2,V=uv2)
DD = mt_lutxy(RG11D,RG4D,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=uv2,V=uv2)
(r==0) ? clp : clp.mt_MakeDiff(DD,U=uv,V=uv)
return(last)
}
#end
I would use a better deinterlacer than LeakKernelDeint, such as TDeint, or at least raise the threshold a bit.

ChrisW77
15th February 2007, 13:12
Thanks, Boulder, I'll give that a try.

I would use a better deinterlacer than LeakKernelDeint, such as TDeint, or at least raise the threshold a bit.

I use Leakkernel, as it's a bit faster than TDeint, and with a threshold of 0, produces almost artifact-free interlacing. My PAL VHS tapes have recordings about 15+ years old, in Long Play, and with a lot of noise and dots crawling all over the place. I find that, if I raise the threshold to 10+, tiny little lines start to appear, which look like combing effects.

Thanks for your help, anyway. :)

Boulder
15th February 2007, 13:17
10+ is way too large, I was thinking something along the lines of 3-4.

Chainmax
15th February 2007, 15:31
rkr1958: the change looks great indeed, but I would add something like LimitedSharpenFaster(SMode=4).Tweak(sat=1.3).AddGrainC(5,2) at the end of the script in order to make it look a bit more detailed. I would also consider trying DeSpot right after Didée's script and before my suggestion in order to get rid of those black spots on the last frame you posted.

rkr1958
16th February 2007, 04:46
rkr1958: the change looks great indeed, but I would add something like LimitedSharpenFaster(SMode=4).Tweak(sat=1.3).AddGrainC(5,2) at the end of the script in order to make it look a bit more detailed. I would also consider trying DeSpot right after Didée's script and before my suggestion in order to get rid of those black spots on the last frame you posted.Thanks. I've give both of those a try. After I updated MVTools and added back the two arguments (sharp & overlap) that I had to take out to get it two run the blocks that I got before went away. However, my processing time SIGNIFICANTLY slowed down. It takes approximately 10-minutes of processing per 30-frames (1-second) of video ... 10-hours for 1-minute.

Boulder
16th February 2007, 07:35
Overlapping makes the processing much slower as there are more blocks to process. It does make the motion estimation more accurate but it's up to you to decide if it's worth the extra time spent.

Pookie
16th February 2007, 09:28
Hardware is going to make the difference between "not usable in the physical world" and "very slow, but I really want this to look nice". The upgrade to an Intel E4300 and motherboard is pretty affordable, as it supports AGP video cards and DDR1 RAM - you can reuse most of your existing hardware. BigDid posted his results in the hardware forum. Impressive gains in performance for around $260. Took him 82 seconds to process 30 frames, takes a P4 2.4 244 seconds to do the same.

The results from the hardware benchmark thread show that this script runs fastest when the SetMemoryMax() value is set to 50% of the total RAM installed. It ran much slower if it was set to less, and there was no speed improvement if it was set to more.

rkr1958
17th February 2007, 04:32
Got the 1-GB of RAM today that I order from newegg. I installed it (matched pairs) which gives me a total of 2048-MB RAM running in dual channel. I changed setmemorymax(512) to setmemorymax(1024) ... and I couldn't believe the results ... with everything else held constant ... I got a factor of 5 speed increase in running the script. Instead of 10-hours of processing per minute of video it now takes me 2-hours per minute. RAM was defintely my bottleneck ... task manager still shows CPU usage around 50% but now memory is around 1.4 to 1.5-GB instead of pegging out at 1-GB before.

Pookie
17th February 2007, 12:00
That's great :)

ChrisW77
17th February 2007, 14:18
I've had a little play with a script, trying to use similar settings to Didée's script. I still don't quite know what I'm doing, but I'm trying to learn, and read, and learn.
This gives me almost as good results as Didée's script, but I can now get around 15-20fps, with my E6300 Core2Duo, 2GB 667 RAM, ASRock board.

setmemorymax(768)
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\fluxsmooth.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\MedianBlur.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\RemoveGrainSSE2.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\TTempSmooth.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\MVTools.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\DeGrainMedian.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\DGDecode.dll")
LoadPlugin("C:\Program Files\AviSynth 2.5\plugins\mpasource.dll")
Import("C:\Program Files\AviSynth 2.5\Examples\Minblur.avs")

video = mpeg2source("D:\VHSrips\vhstest1.d2v", cpu=6, iPP=true, idct=5)
audio = MPASource("D:\VHSrips\vhstest1 T01 DELAY 0ms.mpa", normalize = false)
AudioDub(video, audio)
ConvertToYV12(interlaced=true)

AssumeTFF()
#last=last.LeakKernelDeint(order=1,threshold=4,sharp=true)
last=last.TDeint(Order=1,mthreshL=4,mthreshC=4,mtnmode=0,denoise=true,sharp=true)
last=last.Crop(8,4,-14,-12,align=true) # Left,Top,Right,Bottom.
last=last.Spline36Resize(480,384)
#last=last.Lanczos4Resize(480,384)
#fields=last.DeGrainMedian(limitY=10,limitUV=10,mode=0,interlaced=true).RemoveGrain(mode=5)
fields=last.minblur(2).FluxSmoothT(9)
compy1=last

bw_vec2 = fields.MVAnalyse(isb=true, lambda=512,delta=2,pel=2,blksize=16,overlap=16/2,sharp=2,idx=1)
bw_vec1 = fields.MVAnalyse(isb=true, lambda=512,delta=1,pel=2,blksize=16,overlap=16/2,sharp=2,idx=1)
fw_vec1 = fields.MVAnalyse(isb=false, lambda=512,delta=1,pel=2,blksize=16,overlap=16/2,sharp=2,idx=1)
fw_vec2 = fields.MVAnalyse(isb=false, lambda=512,delta=2,pel=2,blksize=16,overlap=16/2,sharp=2,idx=1)

bw2_comp = compy1.MVCompensate(bw_vec2,idx=2)
bw1_comp = compy1.MVCompensate(bw_vec1,idx=2)
fw1_comp = compy1.MVCompensate(fw_vec1,idx=2)
fw2_comp = compy1.MVCompensate(fw_vec2,idx=2)

Interleave(bw2_comp,bw1_comp,compy1,fw1_comp,fw2_comp)

fields2=last
compy2=last

bw2_vec2 = fields2.MVAnalyse(isb=true, lambda=256,delta=2,pel=2,blksize=8,overlap=8/2,sharp=2,idx=3)
bw2_vec1 = fields2.MVAnalyse(isb=true, lambda=256,delta=1,pel=2,blksize=8,overlap=8/2,sharp=2,idx=3)
fw2_vec1 = fields2.MVAnalyse(isb=false, lambda=256,delta=1,pel=2,blksize=8,overlap=8/2,sharp=2,idx=3)
fw2_vec2 = fields2.MVAnalyse(isb=false, lambda=256,delta=2,pel=2,blksize=8,overlap=8/2,sharp=2,idx=3)

bw2_comp2 = compy2.MVCompensate(bw2_vec2,idx=3)
bw1_comp2 = compy2.MVCompensate(bw2_vec1,idx=3)
fw1_comp2 = compy2.MVCompensate(fw2_vec1,idx=3)
fw2_comp2 = compy2.MVCompensate(fw2_vec2,idx=3)

Interleave(bw2_comp2,bw1_comp2,compy2,fw1_comp2,fw2_comp2)
last=fields.MVDegrain2(bw_vec2,bw_vec1,fw_vec1,fw_vec2,thSAD=300,idx=1)

Tweak(sat=0.9)



I'm not sure if theres any obvious errors in there. I borrowed Didée's Minblur script, and used it as an import rather than actually in the script.

Didée
17th February 2007, 20:12
I'm not sure if theres any obvious errors in there.
Well ... there are no real "errors" as such in your script.
However,

had a little play with a script, trying to use similar settings to Didée's script.
your script has nothing to do with mine. I'm posting your script again, with all not-used parts marked in red:
video = mpeg2source("D:\VHSrips\vhstest1.d2v", cpu=6, iPP=true, idct=5)
audio = MPASource("D:\VHSrips\vhstest1 T01 DELAY 0ms.mpa", normalize = false)
AudioDub(video, audio)
ConvertToYV12(interlaced=true)

AssumeTFF()
#last=last.LeakKernelDeint(order=1,threshold=4,sharp=true)
last=last.TDeint(Order=1,mthreshL=4,mthreshC=4,mtnmode=0,denoise=true,sharp=true)
last=last.Crop(8,4,-14,-12,align=true) # Left,Top,Right,Bottom.
last=last.Spline36Resize(480,384)
#last=last.Lanczos4Resize(480,384)
#fields=last.DeGrainMedian(limitY=10,limitUV=10,mode=0,interlaced=true).RemoveGrain(mode=5)
fields=last.minblur(2).FluxSmoothT(9)
compy1=last

bw_vec2 = fields.MVAnalyse(isb=true, lambda=512,delta=2,pel=2,blksize=16,overlap=16/2,sharp=2,idx=1)
bw_vec1 = fields.MVAnalyse(isb=true, lambda=512,delta=1,pel=2,blksize=16,overlap=16/2,sharp=2,idx=1)
fw_vec1 = fields.MVAnalyse(isb=false, lambda=512,delta=1,pel=2,blksize=16,overlap=16/2,sharp=2,idx=1)
fw_vec2 = fields.MVAnalyse(isb=false, lambda=512,delta=2,pel=2,blksize=16,overlap=16/2,sharp=2,idx=1)

bw2_comp = compy1.MVCompensate(bw_vec2,idx=2)
bw1_comp = compy1.MVCompensate(bw_vec1,idx=2)
fw1_comp = compy1.MVCompensate(fw_vec1,idx=2)
fw2_comp = compy1.MVCompensate(fw_vec2,idx=2)

Interleave(bw2_comp,bw1_comp,compy1,fw1_comp,fw2_comp)

fields2=last
compy2=last

bw2_vec2 = fields2.MVAnalyse(isb=true, lambda=256,delta=2,pel=2,blksize=8,overlap=8/2,sharp=2,idx=3)
bw2_vec1 = fields2.MVAnalyse(isb=true, lambda=256,delta=1,pel=2,blksize=8,overlap=8/2,sharp=2,idx=3)
fw2_vec1 = fields2.MVAnalyse(isb=false, lambda=256,delta=1,pel=2,blksize=8,overlap=8/2,sharp=2,idx=3)
fw2_vec2 = fields2.MVAnalyse(isb=false, lambda=256,delta=2,pel=2,blksize=8,overlap=8/2,sharp=2,idx=3)

bw2_comp2 = compy2.MVCompensate(bw2_vec2,idx=3)
bw1_comp2 = compy2.MVCompensate(bw2_vec1,idx=3)
fw1_comp2 = compy2.MVCompensate(fw2_vec1,idx=3)
fw2_comp2 = compy2.MVCompensate(fw2_vec2,idx=3)

Interleave(bw2_comp2,bw1_comp2,compy2,fw1_comp2,fw2_comp2)
last=fields.MVDegrain2(bw_vec2,bw_vec1,fw_vec1,fw_vec2,thSAD=300,idx=1)

Tweak(sat=0.9)

You see, all that fiddling in the middle is completely redundant. It does just nothing, since the results are never used. Effectively, you're just using MVDegrain2 with some stronglord pre-processing, that's all.

Then, before the MV stuff, you're using Minblur(2).FluxSmooth(9) for pre-denoising. Oops ...
Minblur() with radius 2 is a pretty aggressive spatial cleaner. I use it only for creating "analyser" clips, that contain the main structures, but only little detail (and noise). I'd never use it directly to process the output. Moreover you applied it to the already downsized source (480x384), which makes the clean-out effect even stronger.
Then, after having filtered out most of any detail, you're handing over to MVDegrain. Not quite sure what's left over to do for MVDegrain at that point, since most detail-related frequencies have already gone. Probably it gives more stabilizing to the emptied-out hull.

If the result looks OK to you, then it looks OK. Processing of poor-quality VHS sources is always a big matter of taste.

My playground this is not. ;)

rkr1958
17th February 2007, 21:22
@ Didee, hope you don't mind but I functionalized your script and added to my collection of avs plugin scripts.

@Chainmax, I included your recommendations (Despot & LimitedSharpenFaster).

@ Pookie, Boulder & others, thanks for your invaluable help and patience.


#
# Powerful but slow denoiser & restoration script
#
# A functionalized and nearly verbatim copy of script by Didee.
# http://forum.doom9.org/showthread.php?p=952831#post952831
#
# Includes recommended additions from Chainmax.
#
# Deviations from Didee's original script are noted.
#
function PBSdenoiser(clip a)
{
# Set memory
setmemorymax(1024) # setmemorymax(512) (Original command ... set to 1/2 of total RAM)

# load necessary plugins
LoadPlugin(plugin_dir+"fluxsmooth.dll")
LoadPlugin(plugin_dir+"MedianBlur.dll")
LoadPlugin(plugin_dir+"mt_masktools.dll")
LoadPlugin(plugin_dir+"MVTools.dll")
LoadPlugin(plugin_dir+"RemoveGrain.dll")
LoadPlugin(plugin_dir+"Repair.dll")
LoadPlugin(plugin_dir+"TTempSmooth.dll")
LoadPlugin(plugin_dir+"despot.dll")
Import(plugin_dir+"LimitedSharpenFaster.avs")
LoadPlugin(plugin_dir+"AddGrainC.dll")

a.converttoyv12() # converttoyv12() (Original command ... changed to functionalize script)

last.Bob(0,0.5) # Bob(0,0.5) (Original command ... changed to functionalize script)

bobbed = last
base = last.minblur(2).FluxSmoothT(9)

bw4_vec = base.MVAnalyse(isb=true, truemotion=false,delta=4,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
bw3_vec = base.MVAnalyse(isb=true, truemotion=false,delta=3,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
bw2_vec = base.MVAnalyse(isb=true, truemotion=false,delta=2,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
bw1_vec = base.MVAnalyse(isb=true, truemotion=false,delta=1,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw1_vec = base.MVAnalyse(isb=false, truemotion=false,delta=1,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw2_vec = base.MVAnalyse(isb=false, truemotion=false,delta=2,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw3_vec = base.MVAnalyse(isb=false, truemotion=false,delta=3,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)
fw4_vec = base.MVAnalyse(isb=false, truemotion=false,delta=4,lambda=512,pel=2,sharp=2,blksize=16,overlap=16/2,pnew=32,idx=1)

bw4_comp = bobbed.MVCompensate(bw4_vec,idx=2)
bw3_comp = bobbed.MVCompensate(bw3_vec,idx=2)
bw2_comp = bobbed.MVCompensate(bw2_vec,idx=2)
bw1_comp = bobbed.MVCompensate(bw1_vec,idx=2)
fw1_comp = bobbed.MVCompensate(fw1_vec,idx=2)
fw2_comp = bobbed.MVCompensate(fw2_vec,idx=2)
fw3_comp = bobbed.MVCompensate(fw3_vec,idx=2)
fw4_comp = bobbed.MVCompensate(fw4_vec,idx=2)

Interleave(bw4_comp,bw3_comp,bw2_comp,bw1_comp,bobbed,fw1_comp,fw2_comp,fw3_comp,fw4_comp)
MedianBlurT(0,0,0,4)
SelectEvery(9,4)

base2 = last
bobbed2 = last

bw4_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=4,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
bw3_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=3,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
bw2_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=2,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
bw1_vec2 = base2.MVAnalyse(isb=true, truemotion=false,delta=1,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw1_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=1,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw2_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=2,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw3_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=3,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)
fw4_vec2 = base2.MVAnalyse(isb=false, truemotion=false,delta=4,lambda=256,pel=2,sharp=2,blksize=8,overlap=8/2,pnew=32,idx=3)

bw4_comp2 = bobbed2.MVCompensate(bw4_vec2,idx=3)
bw3_comp2 = bobbed2.MVCompensate(bw3_vec2,idx=3)
bw2_comp2 = bobbed2.MVCompensate(bw2_vec2,idx=3)
bw1_comp2 = bobbed2.MVCompensate(bw1_vec2,idx=3)
fw1_comp2 = bobbed2.MVCompensate(fw1_vec2,idx=3)
fw2_comp2 = bobbed2.MVCompensate(fw2_vec2,idx=3)
fw3_comp2 = bobbed2.MVCompensate(fw3_vec2,idx=3)
fw4_comp2 = bobbed2.MVCompensate(fw4_vec2,idx=3)

Interleave(bw4_comp2,bw3_comp2,bw2_comp2,bw1_comp2,bobbed2,fw1_comp2,fw2_comp2,fw3_comp2,fw4_comp2)
ttempsmooth(4,8,8,2,2,strength=5,pfclip=last.RemoveGrain(11))
SelectEvery(9,4)

maxx = bobbed.mt_logic(bw1_comp,"max")
\ .mt_logic(fw1_comp,"max")
minn = bobbed.mt_logic(bw1_comp,"min")
\ .mt_logic(fw1_comp,"min")
#.mt_logic(bw2_comp,"max").mt_logic(bw3_comp,"max")
#.mt_logic(fw2_comp,"max").mt_logic(fw3_comp,"max")
#.mt_logic(bw2_comp,"min").mt_logic(bw3_comp,"min")
#.mt_logic(fw2_comp,"min").mt_logic(fw3_comp,"min")

ssharp = mt_lutxy(last,last.RemoveGrain(11), \
"x x y - abs 12 / 1 4 / ^ 12 * x y - 2 ^ x y - 2 ^ 2.3 + / * x y - x y - abs 0.0001 + / * 1 x y - abs 16 / 1 4 / ^ + / +",U=2,V=2)

ssharp.mt_Clamp(maxx,minn,0,0,U=2,V=2)

SeparateFields().SelectEvery(4,0,3).Weave() # before or after,

interleave( selectevery(5,0).FluxSmoothT(7),selectevery(5,1).FluxSmoothT(7),
\ selectevery(5,2).FluxSmoothT(7),selectevery(5,3).FluxSmoothT(7),
\ selectevery(5,4).FluxSmoothT(7) )

# SeparateFields().SelectEvery(4,0,3).Weave() # that's a question

# Added commands per recommendations by Chainmax ------------------------------------------------
DeSpot()
LimitedSharpenFaster(SMode=4).Tweak(sat=1.3).AddGrainC(5,2)
# --------------------------------------------------------------------------------------

return(last)
}

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

# Nifty Gauss/Median combination
function MinBlur(clip clp, int r, int "uv")
{
uv = default(uv,3)
uv2 = (uv==2) ? 1 : uv
rg4 = (uv==3) ? 4 : -1
rg11 = (uv==3) ? 11 : -1
rg20 = (uv==3) ? 20 : -1
medf = (uv==3) ? 1 : -200

RG11D = (r==1) ? mt_MakeDiff(clp,clp.RemoveGrain(11,rg11),U=uv2,V=uv2)
\ : (r==2) ? mt_MakeDiff(clp,clp.RemoveGrain(11,rg11).RemoveGrain(11,rg11),U=uv2,V=uv2)
\ : mt_MakeDiff(clp,clp.RemoveGrain(11,rg11).RemoveGrain(20,rg20).RemoveGrain(20,rg20),U=uv2,V=uv2)
RG4D = (r==1) ? mt_MakeDiff(clp,clp.RemoveGrain(4,rg4),U=uv2,V=uv2)
\ : (r==2) ? mt_MakeDiff(clp,clp.medianblur(2,2*medf,2*medf),U=uv2,V=uv2)
\ : mt_MakeDiff(clp,clp.medianblur(3,3*medf,3*medf),U=uv2,V=uv2)
DD = mt_lutxy(RG11D,RG4D,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=uv2,V=uv2)
(r==0) ? clp : clp.mt_MakeDiff(DD,U=uv,V=uv)
return(last)
}
#end

rkr1958
17th February 2007, 21:43
I got the ideal for the following comparison script from watching the extras from the 1959 film, "Journey to the Center of the Earth". I thought I'd post the script and some screenshots from applying to my 1961 video.
# subtitle values
# xsub location = (720 - x_crop)/2 - 40
xsub = 140
ysub = 432
ssub = 24

# Original video
a = AviSource("G:\Home-Movie-1961\Home_8mm_Movies.avi",audio = false).trim(0,6073)
a = a.ConvertToRGB32()

# Restored video
b = AviSource("G:\Home-Movie-1961\f0-f6073.avi",audio = false)

#
# Restored video on the left and original on the right
#

# Original video
# a1 = a.crop(360,0,0,0)
# a1 = a1.subtitle("Original", text_color=color_white, x=xsub, y=ysub, size=ssub)

# Restored video
# b1 = b.crop(0,0,-360,0)
# b1 = b1.subtitle("Restored", text_color=color_yellow, x=xsub, y=ysub, size=ssub)

# Combine (stack videos)
# c = StackHorizontal(b1,a1)

#
# Original on the left and restored video on the right
#

# Original video
a2 = a.crop(0,0,-360,0)
a2 = a2.subtitle("Original", text_color=color_white, x=xsub, y=ysub, size=ssub)

# Restored video
b2 = b.crop(360,0,0,0)
b2 = b2.subtitle("Restored", text_color=color_yellow, x=xsub, y=ysub, size=ssub)

# Combine (stack videos)
c = StackHorizontal(a2,b2)

http://www.knology.net/~benrunyan/compare0000.jpeg

http://www.knology.net/~benrunyan/compare0001.jpeg

http://www.knology.net/~benrunyan/compare0002.jpeg

TechMage89
17th February 2007, 22:17
If you didn't know about it before, NeatVideo (www.neatvideo.com) does the best noise reduction I've ever seen (the samples on the site give you an idea.) The filter is made for VirtualDub, but can be used in AviSynth, too. The only downside is that you have to pay for the full version. But I would say it's well worth the money.

ChrisW77
17th February 2007, 22:57
You see, all that fiddling in the middle is completely redundant. It does just nothing, since the results are never used. Effectively, you're just using MVDegrain2 with some stronglord pre-processing, that's all.

I took all that out, and you are right, it made no difference to the final result.

Then, before the MV stuff, you're using Minblur(2).FluxSmooth(9) for pre-denoising. Oops ...

Yep, it was way too aggressive. I replaced it with
fields=last.DeGrainMedian(limitY=10,limitUV=10,mode=2,interlaced=true).RemoveGrain(mode=5)

which now looks pretty good.

If the result looks OK to you, then it looks OK. Processing of poor-quality VHS sources is always a big matter of taste.

My playground this is not

It certainly looks a lot better than my old script, but like I said, I'm still learning this, as it's still quite alien to me. :D

Thanks for post, Didée, I always like reading what you post, and your great scripts, even if it is like reading Japanese, to a newbie like me. ;)

R3Z
18th February 2007, 14:14
Dumb comment :(

ChrisW77
18th February 2007, 22:46
What he is saying is why are you denoising it twice ? The detail is all removed before it gets to MVDegrain2 so its really redundant having it there !

Dont just lump as many filters as you can, try and be very, very selective

Why the aggressive post ?
I know what he said, I'm not stupid.

Please realise that, I'm a complete amateur at this, I really don't know a lot about video, and sometimes I need a helping hand to get me started, then I'll hopefully go from there.

Didée
19th February 2007, 01:00
What he is saying is why are you denoising it twice ? The detail is all removed before it gets to MVDegrain2 so its really redundant having it there !
Slowly. That is *not* what I said.

I did not question that some denoising is happening before MVDegrain. It's not even redundant: often one can achieve more stable motion vectors by doing some pre-denoising, especially for blocksize=8 (size 16 is more robust).

The only thing I nagged about was that the pre-denoising was too strong.

It's another story when motion search and motion compensation are de-coupled, i.e. are done on different clips. That's how my script worked. In the script of ChrisW77, this was not the case:
In my script, the very strong filtering was only used for the motion search, it did not-at-all affect the output. In the script of ChrisW77, it did. That makes a major difference.

R3Z
19th February 2007, 05:57
@ChrisW77 - mate i wasnt trying to sound that way ~! I am not an agressive person, it was just late at night :(

@Didée - its not like you needed someone to paraphrase for you, i dont know what the hell i was thinking.

Sorry guys !

tranfa
20th February 2007, 00:17
...

Here's a suggested place to start with a script:

setmemorymax(512) #or whatever is apropriate
import(plugdir+"removedirt.avs")
loadplugin(plugdir+"fft3dgpu.dll")
loadplugin(plugdir+"agc.dll")
loadplugin(plugdir+"eedi2.dll")
loadplugin(plugdir+"removedirtsse2.dll")

avisource("C:\capseg.avi")

edeintted = last.AssumeTFF().SeparateFields().SelectEven().EEDI2(field=-1)
TDeint(order=1,edeint=edeintted)

ConvertToYV12()

removedirt()

hdragc(max_sat=1.0, corrector=1.0)

fft3dgpu(plane=3, sigma=7)
fft3dgpu(plane=0, sigma=3, sharpen=.5)


The RemoveDirt bit is optional. It's VERY strong, and I think it kills nose very effectively while preserving what little detail is in this source.




Hi Blue MiSfit,

I'm a newbie trying to practice a little.

Can I ask you if the version of RemoveDirt.avs is the one you can find at the middle of this page: http://www.removedirt.de.tf/ , or not?

Because using this version of RemoveDirt.avs, with your script, I get an error: "AviSynth open failure: Evaluate: System Exception - 0xc000001e (your script, line corresponding to hdragc)".

Without RemoveDirt, the script works...

Thank you for your help.

Blue_MiSfit
20th February 2007, 03:13
function RemoveDirt(clip input, bool "_grey", int "repmode")
{
_grey=default(_grey, false)
repmode=default(repmode, 16)
clmode=17
clensed=Clense(input, grey=_grey, cache=4)
sbegin = ForwardClense(input, grey=_grey, cache=-1)
send = BackwardClense(input, grey=_grey, cache=-1)
alt=Repair(SCSelect(input, sbegin, send, clensed, debug=true), input, mode=repmode, modeU = _grey ? -1 : repmode )
restore=Repair(clensed, input, mode=repmode, modeU = _grey ? -1 : repmode)
corrected=RestoreMotionBlocks(clensed, restore, neighbour=input, alternative=alt, gmthreshold=70, dist=1, dmode=2, debug=false, noise=10, noisy=12, grey=_grey)
return RemoveGrain(corrected, mode=clmode, modeU = _grey ? -1 : clmode )
}


is my script.

Note that RemoveDirt.dll is also necessary - I have the SSE2 version..

tranfa
20th February 2007, 20:27
It's exactly my same script, but unfortunately I get that error message.
Thank you anyway for your help!

tranfa
21st February 2007, 23:41
Having added a "return last" before removedirt (), it seems to work, so I suppose the problem must be in how the function interacts with other plugins I must have installed.

Boulder
22nd February 2007, 07:57
Are you sure the filters after return last are applied? IIRC the items after the return statement are not processed.

tranfa
22nd February 2007, 09:30
Are you sure the filters after return last are applied? IIRC the items after the return statement are not processed.

Sorry Boulder, let me clarify: I assume the filters after return last are excluded.
Therefore, since if I put return last after removedirt() the script crashes, while if I put it before it the script doesn't crash, I think this means that it's the removedirt function - and nothing else in the script - to collide with something in my PC, giving the error message reported above.