Plugin for Avisynth 2.5
Version 0.8.2
Copyright (C)2004-2006 Alexander G. Balakhnin (aka Fizick).
http://avisynth.org.ru
DeGrainMedian plugin is mainly for film grain removal, but may
be used for general denoising.
It uses some spatio-temporal limited median method.
DeGrainMedian
(clip, int
"limitY", int "limitUV", int "mode", bool "interlaced", bool "norow" )
first parameter as always is input clip or default last,
limitY (0 to 255, default=4) -limit of pixel luma correction,
limitUV (0 to 255, default=6) - limit of pixel chroma correction,
mode (0 to 5, default=1) - operation mode (the more, the weaker)
interlaced (true or false, default=false) - process clip as interlaced
norow (true or false, default=false) - do not use same row in spatial filter
Load plugin, adjust parameters value for your clip.
Set limitY to typical value about 2-8 (compromise between denoising and bluring).
It seems, that bigger values of limitUV for chroma (4-15) are often quite safe.
Set mode parameter to bigger value if you found picture as oversmoothed (try!).
The more mode number, the bigger limit values is safe.
It seems, that mode=1 or 2 is good compromise, but it is dependent from source.
With mode=5 the result changes are invisible, but some of "hot" pixels are removed.
Option norow=true is useful on video with horizontal noise stripes , such as analog TV or VHS captures.
Avisource("dvd-input.avi") loadplugin("DeGrainMedian.dll") DeGrainMedian(limitY=5,limitUV=5,mode=3)
Avisource("input.avi") loadplugin("DeGrainMedian.dll") DeGrainMedian(limitY=2,limitUV=3,mode=1) DeGrainMedian(limitY=2,limitUV=3,mode=1)
Avisource("analog-input.avi") loadplugin("DeGrainMedian.dll") DeGrainMedian(limitY=5,limitUV=7,mode=0)
Avisource("analog-input.avi") loadplugin("DeGrainMedian.dll") DeGrainMedian(limitY=5,limitUV=7,mode=1, norow=true)
The plugin is mostly based on two ideas, used at two stages of processing.
The first idea is from STMedianFilter
plugin by Tom Barry
I also use part of its great optimized code and put some part of its
nice doc (edited a little) here:
"STMedianFilter is a (slightly motion
compensated) spatial/temporal median filter. It fairly very fine
grained, using only adjacent pixels in space and
time, so it looks at the adjacent 26 locations to filter each location.
It filters both luma and chroma....
...A simple median filter is
just a clipping step where a value is set to not extend past the high
and low of its neighbors.
(probably
more strictly: median is middle member of ranked (ordered by value)
series - Fizick).
For instance, if you had 3 pixels in a
row that had the values <5,8,7> you could clip the center
one to not be outside the low of 5 or the high of
7, so you would set it to 7.
Now imagine you had a small 3x3 video
screen, like one surface of a Rubiks cube. Imagine the previous frame
was the bottom layer of the cube, the current frame was the middle
layer, and the next frame was the top.
Then the current center pixel would be
right in the center of the Rubics cube and there would be 13 ways you
could draw a line through it and a pair of two nearest neighbors.
What I (and
I - Fizick) did was to compare
each of those pairs of neighbors to see which pair was most agreeing on
value. I (and I - Fizick)
used that pair to
clip the value of the center pixel." (The end of Tom
Barry citation).
Very interesting RemoveGrain
plugin
by Kassandro in mode=9 works similar to STMedianFilter
at this stage, but in spatial plane only (not in temporal). It than
changes pixel to this value of neighbors (by minimax). But it can not
remove middle sized grain from my bad film source.
RemoveGrain
is considered by Kassandro as
prefilter for RemoveDirt
, he says in doc:
"If grain is too crude, RemoveGrain can only partially remove it or
cannot remove it at all."
( The end of Kassandro citation)
It seems, that it is mostly due to lack of temporal information from
neighbor frames.
Since version 0.2, I add to DeGrainMedian also some other more
safe operation
modes 1-4(later 5) (code borrowed from RemoveGrain).
We consider the same 3x3x3 cube.
New pixel candidate value (newp) is clipped by values of neighbor
pixels
from pair (bound1 and bound2).
But mode1-mode5 use more safe criterion (weight) of optimal pixel pair,
We take into account also the difference of new value from central
pixel old value (oldp) .
Mode=0
of DeGrainMedian (similar to mode=9 of RemoveGrain) uses weight=|bound1
-bound2|, it is strongest.
Mode=1
of DeGrainMedian (more strong than mode=8 of RemoveGrain) uses weight=|oldp -
newp|+4* |bound1 - bound2|
Mode=2
of DeGrainMedian (similar to mode=8 of RemoveGrain) uses weight=|oldp -
newp|+2* |bound1 - bound2|
Mode=3
of DeGrainMedian (similar to mode=7 of RemoveGrain) uses weight=|oldp -
newp|+ |bound1 - bound2|
Mode=4
of DeGrainMedian (similar to mode=6 of RemoveGrain) uses weight=2*|oldp
- newp|+ |bound1 - bound2|
Mode=5
of DeGrainMedian (similar to mode=5 of RemoveGrain) uses weight=|oldp -
newp|, it is weakest.
norow option excludes horizontal pixels pair of same frame, so filter considers 12 pairs only.
STMedianFilter
at second stage don't filter pixel if it would change it more than some
threshold.
(More correctly, it firstly makes temporal detecting and thresholding,
with following spatial detecting and thresholding)
The most denoisers also do not filter pixels with big noise
(big luma differences).
But both such single pixels are very visible on flat smoothed regions,
and group of them forms very annoying edge artifacts.
Moreover, pure temporal denoisers often produce ghosting even for not very big thresholds.
DeGrainMedian at this second stage uses other (different) method of pixel processing.
Here I use second idea, borrowed from Dust
plugin by Steady. See part of Dust
doc here:
"Limit=5
Sets the strength of the temporal filtering. (How much it can change
the
original pixel)." (The end of Steady citation).
So, if filtered pixel would be changed
more than some threshold (limit),
it will NOT be restored to original in DeGrainMedian,
but will be changed by LIMITED value.
DeGrainMedian
plugin
filters ALL pixels, but with limited strength.
Therefore, all grain and strikes are (fully or partially) smoothed.
Filter almost don't produce edge artifacts.
Ghosting is also minimal, since it is automatically switched to spatial
smoothing as more nearest pair by values.
You may select one of 6 modes of operation, from strong (but smoothed) to
weak (but sharp).
So, DeGrainMedian have a speed of STMedianFilter (true) and
strength of Dust (true by limit value :-)!
It is almost not joke :-).
It can greatly increase the compession degree.
What is bad, really?1. Some blurring (you want denoising without it ? :-) .
2. It can not produce flat fully smooth picture, some noise always
remains
(you like oversmoothed and blocked clips ?).
3. Motion compensation is limited to 1 pixel value (of course, it is
NOT as
Dust
, but what about external motion compensation ?).
Seriously,
it is not super filter and still experimental, but for my noisy grainy
films, it makes quite good results.
Firstly I developed it as prefilter (to Vaguedenoiser etc), but it
seems now, that sometimes it can be used alone...
Probably, it can help somebody else. That is why I release it.
Some note. With limitY=255,
DeGrainMedian must have the same (or similar) output
as STMedianFilter with thresholds=255 (and with the same artifacts),
but it is not true now,
probably due to some bug or bugs :-(
Edit: It is true now - it was a bug in STMedianFilter
,
I fixed it in v 1.0.3.
It must be applied before other denoising filters.
Sometimes I use two DeGrainMidian filters in script with lower limits for better noise removal.
The better results for films restoration within Avisynth can be
achieved with my global motion compensation plugin DePan
.
See doom9 forum special thread: http://forum.doom9.org/showthread.php?s=&threadid=80834
I use free MS VC++ Toolkit 2003 with MS Platform SDK.
Use make file "makefile" with command:
nmake
(note: copy lost nmake.exe and cvtres.exe from Platform SDK directory Bin\win64 to Bin ).
This program is free software; you can redistribute it and/or
modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
If you like my plugins, please consider to make some donation.