Another (better?) AVISynth noise reduction script

johnmeyer wrote on 8/26/2009, 9:58 PM
Back in early 2003 I first posted about how to reduce chroma and luma noise in VHS video captures. The original technology I used then seems pretty crude now.

I guess all of us have experienced this feeling as digital video technology has progressed.

I wanted to share my latest technique which is significantly superior to both Neat Video and to fft3dfilter (an AVISynth plugin). I have mostly been using fft3dfilter. This new technique not only produces amazingly good quality, but it is also MUCH faster than anything I have used previously. On my computer (a 3.2 GHz i7), I can clean SD interlaced video at 3x real time.

Anyone who uses Neat Video should be impressed with that.

This noise reduction uses AVISynth. If that isn't your cup of tea, you don't need to read any further.

Here's the "recipe" for cleaning interlaced SD video. It can easily be adapted to HD and/or progressive. Interlaced is harder to do correctly which is why I am posting that.

1. Download AVISynth.

2. Install AVISynth.

3. Download the MVTools v2.5.2 plugin. Put the MVTools2 DLL in the AVISynth plugin folder (make sure it is MVTools2.DLL and not MVTools.DLL: you want the one with the "2" at the end).

4. Download the MT plugin. This provides multi-threading capability to AVISynth. Put the MT DLL in the plugins folder. Then, go to the C:\WINDOWS\SYSTEM32 folder and rename the AVISynth.DLL file. Once renamed, copy the "special" AVISynth.DLL file contained in the MT zip file to the SYSTEM32 folder

5. Copy the script below to Notepad and save it with the extension "AVS."

6. In the AVISource line in the script, replace the video file name with the path and name of the video file you want to improve.

7. Open the AVS script in VirtualDub and edit and save the results. If you prefer to edit and render in Vegas, you can open the AVS file in VFAPIConv and then save the result to a signpost AVI file (this takes a few minutes for a two hour file). Open the resulting AVI file in Vegas.

Here's the script:

#Denoiser script for interlaced video
Loadplugin("C:\Program Files\AviSynth 2.5\plugins\mvtools2.dll")
loadPlugin("c:\Program Files\AviSynth 2.5\plugins\Cnr2.dll")
loadPlugin("c:\Program Files\AviSynth 2.5\plugins\MT.dll")

#The following line sets the simplest multi-threading mode
SetMTMode(5)
#Modify this line to point to your video file
source=AVISource("E:\Disney Films\Winning Inline Hockey0001.avi")

#The following line sets a faster multi-threading mode
SetMTMode(2,0)

#CNR reduces VHS chroma noise. Not needed for digital sources (like DV)
chroma=source.Cnr2("oxx",8,16,191,100,255,32,255,false) #VHS
#chroma=source.Cnr2("oxx",8,14,191,75,255,20,255,false) #Laserdisc

#This next line calls the actual noise reduction function
#Change the overlap paramater (the first "0" in the line below) to 0, 1, 2, 3, or 4
#to get different reduction characteristics.
#Change the second "0" to "1" if you want to remove flicker in video
output=MDegrain2i2(chroma,0,0)

#This next line can be uncommented if you want to compare before and after
#If you remove the comment, comment out the “return output” line below it.
#stackhorizontal(source,output)
return output


#The following is the function which actually performs the noise reduction.
function MDegrain2i2(clip source, int "overlap", int "dct")
{
overlap=default(overlap,0) # overlap value (0 to 4 for blksize=8)
dct=default(dct,0) # use dct=1 for clip with light flicker
fields=source.SeparateFields() # separate by fields
super = fields.MSuper()
backward_vec2 = super.MAnalyse(isb = true, delta = 2, overlap=overlap, dct=dct)
forward_vec2 = super.MAnalyse(isb = false, delta = 2, overlap=overlap, dct=dct)
backward_vec4 = super.MAnalyse(isb = true, delta = 4, overlap=overlap, dct=dct)
forward_vec4 = super.MAnalyse(isb = false, delta = 4, overlap=overlap, dct=dct)
fields.MDegrain2(super, backward_vec2,forward_vec2,backward_vec4,forward_vec4,thSAD=400)
Weave()
}
The only variable you might want to change is the thSAD number. Higher numbers provides stronger filtering.

The reason I think this is so good is that noise reduction is mostly about following the most famous line in the Hippocratic Oath: "Above all, do no harm." As I have trekked through dozens of noise reduction technologies over the past half dozen years, the main improvement has not been in the amount of noise removed, but in the elimination of all the unwanted artifacts that noise reduction technologies always seem to introduce, including ghosting, smearing, loss of detail, color shifts, and more. This technology has by far least artifacting of anything I have used.

If anyone wants to post some problem video, I'd be happy to run it through this filter and post the results.

BTW, I certainly didn't invent any of this, and much of it has been discussed for quite awhile over at the doom9.org forum. I hadn't tried any of these newer techniques because I was reasonably happy with fft3Dfilter. However, I just transferred about thirty VHS tapes and became increasingly aware of shortcomings in the fft3Dfilter, most notably in the loss of detail on large almost-uniform backgrounds.

Also, fft3Dfilter is slow. A key bonus with MVTools2/MT is performance. With the addition of the multi-threaded hack, which MVTools2 has been specifically designed to utilize, I can now use 100% of all eight cores on my i7, and as a result can achieve sustained 94 fps on 30 fps SD interlaced material, or 3x realtime speed. (I get this in VirtualDub; the VFAPIConv overhead makes the performance in Vegas somewhat slower). For reference, I just tried the Neat plugin and got about 9 fps, so this is a full order of magnitude (10x) faster.

Comments

Grazie wrote on 8/26/2009, 11:03 PM
Outstanding work John. You really should get some kind of "SONY Assist" award.

OK, questions?

Q1: Each time I use this I would need to alter the script to accommodate the new file to be acted upon? I can see the line in the script.

Q2: "Put the MT DLL in the plugins folder." That would be which plugin folder?

Q3: "Then, go to the C:\WINDOWS\SYSTEM32 folder and rename the AVISynth.DLL file." Is this a way to protect the existing file and keep it? What do I rename it as?

Q4: "Once renamed, copy the "special" AVISynth.DLL file contained in the MT zip file to the SYSTEM32 folder " What is the "special" file?

Always looking to learn new ways: "Above all, do no harm" I like that too. If the detail is there leave it alone.

Grazie
johnmeyer wrote on 8/27/2009, 7:15 AM
Q1: Each time I use this I would need to alter the script to accommodate the new file to be acted upon?

Yes, there is no GUI in AVISynth, so you have to edit and save the script. There is a GUI add-on that lets you do this, but I have never used it.

Q2: "Put the MT DLL in the plugins folder." That would be which plugin folder?

The AVISynth plugin folder.

Q3: "Then, go to the C:\WINDOWS\SYSTEM32 folder and rename the AVISynth.DLL file." Is this a way to protect the existing file and keep it? What do I rename it as?

The point of renaming the exisiting file is so you can keep it and go back to it. You can name it anything you want. "AVISynth.ORIGINAL" is a good choice.

Q4: "Once renamed, copy the "special" AVISynth.DLL file contained in the MT zip file to the SYSTEM32 folder " What is the "special" file?

The MT.Zip file you download contains its own AVISynth.DLL file. It is special because it contains extra code to permit multithreading. The whole point of the exercise about which you have these questions is to use this version of AVISynth rather than the version from the original author.
JoeMess wrote on 8/27/2009, 7:41 AM
Have you seen any situation where AVISynth was not working with multi-threading enabled? (i.e. will reverting back and forth between MT and not be required?)

Joe
johnmeyer wrote on 8/27/2009, 9:18 AM
Have you seen any situation where AVISynth was not working with multi-threading enabled?I have only used the MT plugin with this one script. I read a lot about it before using it, and it clearly does not work well with many plugins. However, the MVTools author specifically designated MVTools2 to work with the MT plugin, and I used his script fragments in my script. As a result, the thing worked the first time.
LReavis wrote on 8/27/2009, 3:45 PM
I'm really interested in this, but I'm getting this error message:

"Error during script execution at line 1, column 2: parse error

#<!>Denoiser script for interlaced video"

I thought the error message might refer to the Cnr2.dll plugin, which I don't have; so I commented-out its "loadplugin" line, but that didn't change the error message.

I've used Vdub & AVIsynth in the past, but not often; probably I'm doing something wrong?
johnmeyer wrote on 8/27/2009, 4:14 PM
Make sure you edit the script, if necessary, to point to the correct location for the MVTools plugin. I have mine in a slightly non-standard location. I probably should have edited the script to change that. Actually, I think that with the current versions of AVISynth, I don't even know if it is necessary to explicitly load the plugins. I do it just because in the old days we had to declare all variables, explicitly load plugins, etc., and old habits die hard.

[Edit] I just went back to the original post and changed the script so that both the MVTools2.DLL line and also the CNR2.dll line now point to the default AVISynth plugins folder. Hopefully this will help others avoid the problem you had.
craftech wrote on 8/27/2009, 4:57 PM
Thanks as always John for another valuable contribution to the forum.

Much appreciated.

John
RedEyeRob wrote on 8/27/2009, 6:11 PM
I know nothing about AVIsynth but followed the instructions and replaced my file location and name in the script. I get an error when trying to open the videofile in virtualdub...

Avisynth open failure:
Script error:syntax error
(C:\Documents and Settings\Rob\My Documents\DeNoiser.avs. line1, column 11)

I called the avs file DeNoiser
johnmeyer wrote on 8/27/2009, 7:20 PM
Make sure you edit the script, if necessary, so that the actual location of your plugin files matches what is in the script. Alternatively, you can comment out the plugin loading lines (the first lines of the script) by placing a "#" in the first column..

Finally, make sure you edit and save using Notepad. If you use Word or some other program, if you don't save as a TXT file, but with the AVS extension, the file will contain extraneous characters.

To make this easier, and to avoid these problems, here is a link to a version of the script that has the plugin loading lines commented out, and is ready to run as is. I just tested it, after moving my CNR and MVTools2 plugins to the regular plugin folder (I didn't realize that I also had the CNR plugin in a non-standard folder). It works fine.

Noise Reduction Script

Link good for seven days.
RedEyeRob wrote on 8/27/2009, 7:55 PM
Now i got farthur but got the message about not having decompressor for fourcc dvsd so I researched that and found I had to add the dvsd codec to my system which I did. Now when opening the modified avs file from VDub I get a different error which says

Cnr2: YV12 and YUY2 colorspace only!

it references line 10

I am sure it's me, Ive never used avisynth or vdub before so I dont expect you to spend your time trying to debug it for me.
plasmavideo wrote on 8/27/2009, 8:00 PM
How timely John. I'm getting ready to do some VHS stuff shortly, and have been playing with some NR settings in Virtualdub and elsewhere. This looks like a winner, and I'll let you know how things turn out once I get the project started.
LReavis wrote on 8/27/2009, 8:43 PM
I downloaded and tried the new script, but still get the same error message "Error ,.. script execution ... line 1, col 2 ... parse error"

Next I commented out this line:
"#chroma=source.Cnr2("oxx",8,16,191,100,255,32,255,false) #VHS"
and saved/exited notepad

but still got the same error message.

Next, I double-checked to make sure that I had the special avisynth.dll that had the same date that was in the .ZIP file and different than the renamed avisynth.dll; and that my 2 plugins (mvtools2.dll & MT.dll) were in c:\program files\avisynth 2.5\plugins. Isn't that where they should be?

Finally, I cut-and-pasted my .AVI file location pointer into a new instance of Notepad and saved it as a .BAT file - just to make sure that I had typed it correctly. When I double clicked the .BAT file, the .AVI opened just fine in my media player.

I also downloaded the latest version of Vdub and also tried the version that the New DeShaker uses, but still no luck. . . . That's about all that I can think of;
???
johnmeyer wrote on 8/27/2009, 9:32 PM
For those still having troubles, let's try to reduce the number of variables. The big potential problem here is the multi-threaded add-on. It can depend on your computer configuration. So, use the original AVISynth.DLL file (you can just delete the one you copied from the MT.zip file and then "un-rename" the original one).

Then, use the following script instead. It is identical to the one I posted above, but with the MT stuff remove. I tested it and it works fine.
#Denoiser script for interlaced video
loadplugin("C:\Program Files\AviSynth 2.5\plugins\mvtools2.dll")
loadPlugin("c:\Program Files\AviSynth 2.5\plugins\Cnr2.dll")
loadPlugin("c:\Program Files\AviSynth 2.5\plugins\MT.dll")

#Modify this line to point to your video file
source=AVISource("E:\Disney Films\Oscars0006.avi").killaudio().ConvertToYV12()
chroma=source.Cnr2("oxx",8,16,191,100,255,32,255,false) #VHS
#chroma=source.Cnr2("oxx",8,14,191,75,255,20,255,false) #Laserdisc
output=MDegrain2i2(chroma)
stackhorizontal(source,output)
#return output


function MDegrain2i2(clip source, int "overlap", int "dct")
{
overlap=default(overlap,0) # overlap value (0 to 4 for blksize=8)
dct=default(dct,0) # use dct=1 for clip with light flicker
fields=source.SeparateFields() # separate by fields
super = fields.MSuper()
backward_vec2 = super.MAnalyse(isb = true, delta = 2, overlap=overlap, dct=dct)
forward_vec2 = super.MAnalyse(isb = false, delta = 2, overlap=overlap, dct=dct)
backward_vec4 = super.MAnalyse(isb = true, delta = 4, overlap=overlap, dct=dct)
forward_vec4 = super.MAnalyse(isb = false, delta = 4, overlap=overlap, dct=dct)
fields.MDegrain2(super, backward_vec2,forward_vec2,backward_vec4,forward_vec4,thSAD=300)
Weave()
}


This will run more slowly (I get about 20 fps instead of 90 fps on my computer), but it should eliminate all the other issues. Also, I added a colorspace conversion on the AVISource line. This may help with some of the other errors. I didn't specify what sort of video files can be used with this, but the AVISynth filters do not like RGB.
johnmeyer wrote on 8/27/2009, 9:42 PM
OK, I couldn't find any references to "parse error" when I Googled it, but I know this stuff works. I then decided to try to see if I could intentionally do some incorrect things in VirtualDub and make the error appear.

I got it on my first attempt.

What you are doing wrong is that you are using the wrong command in VirtualDub to open the script. You are using the File -> Load processing settings. This is not correct, although I can understand why you might have decided to do this. I tried opening the script file using this incorrect option, and I got exactly the error message you reported.

The correct way to use the AVS script is to use the File -> Open Video File menu (the very first option in the File menu). This is because, through the magic of AVISynth, that text file you created with the script that I gave you is actually treated just as if it were a video file, like an AVI file, or MPEG-2 file, or MP4 file, etc.

So, us the File -> Open Video File option, and I think you will find that it works.

LReavis wrote on 8/27/2009, 9:53 PM
Actually, I was using "run script" command in Vdub;

Now I get new errors - needed to comment out Cnr2.dll lines, but that yielded still other errors; too late to continue tonight, but will try again tomorrow

But I'm so grateful for you patient help, johnmeyer - Larry Reavis
Rory Cooper wrote on 8/27/2009, 11:14 PM
John as always thanks for your time and effort

Also some more questions

The tools for cleaning are the same as your slow motion technique

1.is it possible to run both scripts on one event at the same time or do I have to run separately render out then do the next script render again to timeline

2. for 720p clips what do I need to change in the script for it to work on HD PROGRESSIVE

I have set some time aside this Saturday to get myself familiar with your workflow as your results are impressive
to say the least and it’s worth the time and effort……this aint gonna be pretty I am expecting some serious head banging ….but want to get it right

Thanks for the inspiration and scripts

Rory
johnmeyer wrote on 8/28/2009, 9:01 AM
The tools for cleaning are the same as your slow motion techniqueYes, this noise reduction is part of the "motion estimation" technology. The whole concept behind this technology is to first of all identify which pixels are part of some coherent block (i.e., some actual object in the real picture) while ignoring pixels that come and go from one frame to the next (noise). Once identified, the technology tracks these groups of pixels as they move from frame to frame. Once you do all of this, you can then remove the pixels that aren't part of some coherent block (i.e., noise reduction); or you can synthesize intermediate frames (for slow motion, or other frame rate change scenarios); or you can recreate missing frames (to eliminate frames that are missing or have noise). Many other things are possible.

what do I need to change in the script for it to work on HD PROGRESSIVEAs for HD, I don't think you need to do anything special for HD, although you may need to change the thSAD parameter. You'll just have to experiment with it until you find a result you like. Lower values mean less noise reduction. You may also want to play around with the overlap parameter (see my notes below).

For progressive, you need to remove the separatefields and subsequent weave statement. Also, when generating the motion estimation parameters, you need to look at the adjacent frames rather than looking at two and four fields away, as is done in the interlaced clip example (note the deltas of "2" and "4" in the original script vs. the "1" and "2" in this script). This is a very, very clever way of making sure that odd fields are only compared to odd fields and even fields are only compared with even fields. When doing any restoration with interlaced, you always have to make sure to maintain both the spatial and temporal integrity of the even and odd fields.

Here is a script that you can use with progressive. Note that I have also changed the call to the degrain function to:

output=MDegrain2i2(chroma,0,0)

This specifies a block overlap of 0, which is the default. You can play around with this and see if you like the results with an overlap of 0, 1, 2, 3, or 4. Higher overlaps could be better, but are slower.

If you have flicker, change the second parameter from 0 to 1. I should have included this in the original script. You can definitely add these parameters to that script.


#Denoiser script for PROGRESSIVE video
Loadplugin("C:\Program Files\AviSynth 2.5\plugins\mvtools2.dll")
LoadPlugin("c:\Program Files\AviSynth 2.5\plugins\Cnr2.dll")
LoadPlugin("c:\Program Files\AviSynth 2.5\plugins\MT.dll")

SetMTMode(5)
#Modify this line to point to your video file
source=AVISource("E:\Disney Films\Oscars0010.avi").killaudio()
SetMTMode(2,0)

#Only use chroma restoration for analog source material
chroma=source.Cnr2("oxx",8,16,191,100,255,32,255,false) #VHS
#chroma=source.Cnr2("oxx",8,14,191,75,255,20,255,false) #Laserdisc

#Change the overlap paramater (the first "0" in the line below) to 0, 1, 2, 3, or 4
#to get different reduction characteristics.
#Change the second parameter from 0 to 1 if you want to remove slight flicker
output=MDegrain2i2(chroma,0,0)

#Uncomment the following line and add a comment to the line after that
#to see the "before" and "after" on the screen at the same time.
#stackhorizontal(source,output)
return output


function MDegrain2i2(clip source, int "overlap", int "dct")
{
overlap=default(overlap,0) # overlap value (0 to 4 for blksize=8)
dct=default(dct,0) # use dct=1 for clip with light flicker
super = MSuper(source,pel=2, sharp=1)
backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=overlap, dct=dct)
backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=overlap, dct=dct)
forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=overlap, dct=dct)
forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=overlap, dct=dct)
source.MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400)
}
LReavis wrote on 8/28/2009, 11:58 AM
I got it to work! I downloaded Cnr2.dll from
http://www.volter.net/avisynth_en/externalfilters/cnr2.htm

Never could make it work without Cnr2.dll even after commenting out the Cnr2 and related lines. Now the fast denoiser works fine on my interlaced files. Will experiment with progressive later.

So many thanks.

RedEyeRob wrote on 8/28/2009, 3:54 PM
This script works fine for me. Thanks John.
john-beale wrote on 8/29/2009, 12:13 PM
Thanks for this info. I just tried out the MVTools for another use, generating slow motion. It works amazingly well, with some occasional motion-detect error artifacts which might be fixed by playing with some of the many(!) parameters available. Very impressive program overall.
johnmeyer wrote on 8/29/2009, 1:05 PM
I just tried out the MVTools for another use, generating slow motion. It works amazingly well, with some occasional motion-detect error artifacts which might be fixed by playing with some of the many(!) parameters available.When using MVTools for slow motion (or Twixtor or Steadyhand or Motionperfect) you will always have a few places where the slow motion "breaks down." What I suggest is that you put the MVTools slo-mo on the Vegas timeline. Then, put the original footage on the track above, and slow it down by the identical amount (using Vegas's slo-mo settings) and line it up with the MVTools footage. Solo the MVTools track. When you find an area where the slow mo has problems, us the mask tool on the track above, and feather in the slo-mo from Vegas, but just for the areas where the slo mo is having problems. Usually it is someone's arms or legs or other similar situation where there is either motion across some strong vertical object (like a fencepost), or else someone's limbs are moving in opposition to the general movement of the body, or movement of the camera. If you do this right, the mask doesn't have to be very precise, although you may have to keyframe several versions of it. When the artifacts disappear, just cut the event that has the Vegas slo-mo, and make sure there is not mask after that point. Since masks are slow to render, I actually cut the events on the Vegas slo-mo timeline, and delete all events where no masking is needed. That way I am 100% certain that no unwanted masking will be done.

NickHope wrote on 2/27/2011, 3:49 AM
Anyone following this thread should probably go here next.