Analogue captures contain noise. The source of this noise is
mainly due to the cables carrying the signal to your house. One
should use smoothers to get rid of the noise without losing too
much detail. The main difficulty is to find good a trade off
between noise, the level of detail you want to keep in your clip
and the encoding time. The best is to smooth before any resizing,
because you will remove more noise this way.
There are two kind of smoothers:: temporal smoothers and spatial
smoothers. Temporal smoothers work by looking at frames
surrounding the current one and averaging corresponding pixels
together if they look similar enough (and thus likely to be
noise). Spatial smoothers work in a similar way, except they look
at nearby pixels within the same frame. A few filters are a
hybrid of the two, including NoMoSmooth, Convolution3D and
PixieDust. This way you will remove more noise than when using
only a spatial smoother. But remember if you use a temporal
smoother with strong settings, you will see blending between
frames. So, use low settings when using temporal smoothers.
Each approach has its advantages and disadvantages. The great
thing about temporal smoothers is that they do a fantastic job
getting rid of noise when you set them up just right, but they
can also generate some very ugly artifacts, particularly when
dealing with motion. Spatial smoothers, on the other hand, can be
quite destructive to the details in your image, but are great
with high-motion areas because those have few details and are
moving too quickly to notice artifacts anyway. Ideally, one would
like to apply a temporal smoother to relatively static areas and
a spatial smoother to moving ones.
In this test several spatio-temporal smoothers are compared on an
analogue capture. The clip can be downloaded here: [part1, part2] and it contains a
performance of Dido (75 frames, captured with huffyuv). It has
some slow and fast moving scenes, scenes with a uniform
background and scences with some detail. Ivo (i4004) and I used
the codec DivX3 and XviD for smoothing tests.
If this site is too slow, or the images don't load fast enough. They can be downloaded here.
Most of us have read Doom9's famous codec comparisons (aimed at one CD rips with clean DVD sources). But how do the codecs perform on analogue captures which contains a lot of noise. In this subsection we will give some comments on this issue, considering the following codecs: DivX3, DivX5, FFVFW and XviD (no pre and post processing).
DIVX3.avi
size: 436 KB (in this case k = 1024 bytes, therefore the used bitrate is
1200 kpbs / 1.024 = 1172 kbps)
DIVX5.avi size:
392 KB (DivX Pro 5.1.1,
1200 kpbs)
FFVFW.avi
size: 390 KB (FFVFW 09-27-03,
1200 kpbs)
XVID.avi
size: 384 KB (XviD v1.0 beta 3,
1200 kpbs)
The latter three encodings are undersized because of the small number of frames. For XviD and FFVFW this could be improved by highering the overflow settings. But since the desired size (440 KB) still couldn't be reached, we didn't bother doing this.
The codec settings used throughout the tests (unless stated otherwise):
DivX3 [Nandub]
I4-31, P2-9
Internal SCD-100%
1 pass
DivX5 [VdubMod 1.5.10.1]
no pre-processing
no b-frames
Standard Performance
2 passes
FFVFW [VdubMod 1.5.10.1]
I2-31, P2-9
MPEG quantization
no b-frames
[defaults on MotionEstimation tab]
2 passes
XviD [VdubMod 1.5.10.1]
I2-31, P2-9
MPEG quantization
no b-frames
Motion search precision: Ultra High
Trellis quantization
VHQ=4
2 passes
Standard script:
Avisource("D:\Test\huffyuv_raw2.avi")+Avisource("D:\Test\huffyuv_raw.avi")
KernelDeint(order=1, sharp=true)
BicubicResize(640, 480, 0, 0.75)
tweak(0.0, 0.8, 0.0, 1.0)
This script is used to encode using the above mentioned codecs. The results are given below.
There are several important issues where the behaviour of the codecs are different.
Some screenshots from the XviD clip were taken, and a small
slideshow was made to show the effect. Note, that it is much more
clearly visible when watching the clip itself! On the right
handside the tested codecs are compared (deinterlaced, resized,
but no smoothing) with the source clip:
Tearing motion (source: XviD)![]() Stop | Continue |
Raw frame from the tested codecs
(deinterlaced and resized) raw DivX3 DivX5 FFVFW XviD (trellis disabled, VHQ=0) |
Does that mean that DivX5 and XviD shouldn't be used for encoding
analogue captures? Well, yes and no. Yes, because there are good
alternatives like DivX3 [Nandub] and FFVFW which don't have this
undesirable effect. Yes, if you can't or don't want to denoise
much. No, because this effect can be reduced using good
denoisers. We will come back to this in the next subsection.
The following smoothers are considered (between brackets their settings):
| smoother | settings |
| PixieDust | PixieDust(limit=5) |
| Overlay with two different broadcastings | OverLay(clip2a, clip2b, mode="blend", opacity=0.5) |
| PeachSmoother (temporal component) | PeachSmoother(noiselevel=4.286, baseline=3.141, NoiseReduction = 60, Stability = 30, Spatial = 0) |
| TemporalCleaner | TemporalCleaner(6, 12) |
| TemporalSoften | TemporalSoften(3, 5, 5, 10, 2) |
| MipSmoother (spatial component) | MipSmooth(spatial=9, temporal=0, spatial_chroma=10, method="superstrong", downsizer="bilinear", upsizer="bilinear", scalefactor=0.60, weigh=true) |
| VagueDenoiser | VagueDenoiser(threshold=4, method=1, nsteps=6, chroma=true) |
The following scripts are used:
[1] PixieDust:
LoadPlugin("C:\Program Files\AviSynth2_temp\plugins\dustv5.dll")
Avisource("D:\Test\huffyuv_raw2.avi")+Avisource("D:\Test\huffyuv_raw.avi")
KernelDeint(order=1, sharp=true)
PixieDust(limit=5)
BicubicResize(640, 480, 0, 0.75)
Tweak(0.0, 0.8, 0.0, 1.0)
[2] Overlay with two different broadcastings:
clip1a=Avisource("D:\Test\huffyuv_raw2.avi")+Avisource("D:\Test\huffyuv_raw.avi")
clip2a=clip1a.KernelDeint(order=1, sharp=true)
clip1b=AviSource("D:\Captures\dido2.avi").Trim(608,632)+AviSource("D:\Captures\dido2.avi").Trim(1212,1262)
clip2b=clip1b.KernelDeint(order=1, sharp=true)
Overlay(clip2a, clip2b, mode="blend", opacity=0.5)
BicubicResize(640,480)
Tweak(0.0, 0.8, 0.0, 1.0)
[3] Combo's (see appendix for the qmf.avs script). For the low motion scenes PeachSmoother, TemporalCleaner or TemporalSoften are used, and for the medium/high motion scenes Mip or VagueDenoiser are used:
# QUANTIFIED MOTION FILTER v1.4
# EXAMPLE 2 : ADAPTIVE RESIZING FILTER
# LOADING QUANTIFIED MOTION FILTER SCRIPT
Import("D:\Test\Ivo\Wilbert\qmf.avs")
# LOW MOTION FILTER FUNCTION
# -> SHARP RESIZING + TEMPORAL ONLY
function Low_Motion_Filter(clip c)
{
ConvertToYUY2(c)
PeachSmoother(noiselevel=4.286, baseline=3.141, NoiseReduction = 60, Stability = 30, Spatial = 0)
ConvertToYV12()
BicubicResize(640, 480, 0, 0.75)
}
# MEDIUM MOTION FILTER FUNCTION
# -> NEUTRAL BICUBIC RESIZING + TEMPORAL & SPATIAL
function Medium_Motion_Filter(clip c)
{
c.MipSmooth(spatial=9, temporal=0, spatial_chroma=10, method="superstrong", downsizer="bilinear", upsizer="bilinear", scalefactor=0.60, weigh=true)
BicubicResize(640, 480, 0, 0.75)
}
# HIGH MOTION FILTER FUNCTION
# -> SOFT RESIZING + SPATIAL ONLY
function High_Motion_Filter(clip c)
{
c.MipSmooth(spatial=9, temporal=0, spatial_chroma=10, method="superstrong", downsizer="bilinear", upsizer="bilinear", scalefactor=0.60, weigh=true)
BicubicResize(640, 480, 0, 0.75)
}
# OPENING VIDEO SOURCE
Avisource("D:\Test\huffyuv_raw2.avi")+Avisource("D:\Test\huffyuv_raw.avi")
KernelDeint(order=1, sharp=true)
ConvertToYV12()
# APPLYING ADAPTATIVE RESIZING FILTER (USING QMF)
#QMF(debug=true)
QMF()
Tweak(0.0, 0.8, 0.0, 1.0)
The denoisers are compared based on the following
considerations: the amount of detail in the clip, uniformity of
the background (for example, no artefacts in a uniform green
background) and the absence of noise. The denoisers are listed
from best to worst, based on our visual inspection. We will start
by comparing the temporal denoisers: PeachSmoother,
TemporalCleaner and TemporalSoften with Overlay and PixieDust. In
this case only the low motion scenes are considered: The reason
is that the temporal smoothers are applied on the low motion
scenes, and spatial smoothers on medium/high motion scenes, using
the filter Quantified Motion Filter. Which frames are detected as
low motion or medium/high motion can be checked with
QMF(debug=true).
![]() |
|||
|
The listing is as follows:
amount of detail:
1) PeachSmoother, TemporalCleaner, TemporalSoften
2) Overlay, PixieDust
Overlay and PixieDust are blurrier than PeachSmoother,
TemporalCleaner and TemporalSoften.
uniform background:
I (Wilbert) always like that parts of a frame are uniform if they are supposed to be uniform. In this case it means that there are no artefacts in the green areas, and no artefacts on the skin of the girl..
1) Overlay
2) PeachSmoother, PixieDust
3) TemporalCleaner
4) TemporalSoften
Overlay did the best job here, leaving no artefacts at all.
PixieDust follows closely. In the first bunch of frames (say 25)
PeachSmoother has more artefacts than TemporalCleaner and
TemporalSoften in the green areas. But, Peach has a startup time.
Hence, it takes a time before the filter starts to work. After
the first 25 frames, PeachSmoother hardly leaves any artefacts.
That's why it is listed above TemporalCleaner and TemporalSoften.
Besides that, TemporalSoften gives sometimes noticable artefacts
on the skin of the girl (see frame 39, 41, 43, 44, etc.).
absence of noise:
1) Overlay
2) PixieDust
3) PeachSmoother
4) TemporalCleaner, TemporalSoften
The ones with the least amount of detail, contains the least amount of noise. That's no surprise of course. However, PeachSmoother contains less noise than Temporalcleaner and TemporalSoften.
We will continue the comparison with the spatial smoothers:
MipSmoother (note I used temporal=0, but I suspect it means that
only temporal luma filtering is disabled) and VagueDenoiser. They
will be compared to Layer and PixieDust. Only the medium / high
motion scenes are considered.
![]() |
||
|
The listing is as follows:
amount of detail:
1) PixieDust, VagueDenoiser
2) Overlay
3) MipSmoother
PixieDust and VagueDenoiser has the most detail. Overlay is blurrier, and MipSmoother is the blurriest.
uniform background:
1) Overlay
2) PixieDust
3) MipSmoother
4) VagueDenoiser
Overlay did the best job here, leaving no artefacts at all. PixieDust follows closely. MipSmoother and VagueDenoiser have the most artefacts in the green background and on the skin of the girl VagueDenoiser more than MipSmoother. That's why VagueDenoiser is listed as last.
absence of noise:
1) MipSmoother, Overlay
2) PixieDust, VagueDenoiser
The ones with the least amount of detail, contains the least amount of noise. That's no surprise of course. VagueDenoiser has the most noise. PixieDust a bit less, and MipSmoother and Overlay are the cleanest.
We will conclude by making some general remarks about the pro's and cont's of the denoisers.
The overall ratings:
A few words about bitrates and resolutions. The bitrates/resolutions we picked for this test are 512x384 at 800 kbps and 640x480 at 1200 kbps. They seem reasonable. Of course, you can't expect that 640x480 at 1200 kbps (movie) and 640x480 at 1200 kbps (sports, music videos) will look the same. In general, these sources need higher bitrates. With music videos and sports you can't really expect bigger benefits from 2 pass encoding modes, since there are no still scenes where the codec would be able to spare some bits.
Some conclusions and recommendations about the tested filters:
Some conclusions about the encoders:
A small disclaimer, though it is actually more like a contest. It may very well be that you can find a set of filters which produce better quality than the filters we used. The source clips can be downloaded (see introduction), so everyone can take a try. If you have found something better, please contact us :)
The qmf.avs script:
# QUANTIFIED MOTION FILTER (17/08/2003) by HomiE FR,
# a simplified version.
# MOTION ESTIMATION FUNCTION
function ME()
{
# SETTING MOTION LEVEL ACCORDING TO AVERAGE DIFFERENCE
global motion_level = (diff < threshold_lm) ? 0 : motion_level
global motion_level = (diff >= threshold_lm && diff <= threshold_hm) ? 1 : motion_level
global motion_level = (diff > threshold_hm) ? 2 : motion_level
}
# QUANTIFIED MOTION FILTER FUNCTION
function QMF(clip c, float "threshold_lm", float "threshold_hm", bool "debug")
{
# SETTING MOTION LEVELS THRESHOLDS
threshold_lm = default(threshold_lm, 4.5)
threshold_hm = default(threshold_hm, 12.0)
global threshold_lm = threshold_lm
global threshold_hm = threshold_hm
# ENABLING/DISABLING DEBUG INFORMATION
debug = default(debug,false)
global debug = debug
# SETTING PAST/PRESENT/FUTURE CLIPS
global clip = c
# GETTING OUTPUT RESOLUTION
width = Width(Low_Motion_Filter(clip))
height = Height(Low_Motion_Filter(clip))
global clip_resized = PointResize(clip,width,height)
# APPLYING MOTION FILTER ACCORDING TO MOTION LEVEL
c = ConditionalFilter(c,Low_Motion_Filter(clip),clip_resized,"motion_level","=","0")
c = ConditionalFilter(c,Medium_Motion_Filter(clip),c,"motion_level","=","1")
c = ConditionalFilter(c,High_Motion_Filter(clip),c,"motion_level","=","2")
# PRINTING DEBUG INFORMATION
c = (debug == true) ? ScriptClip(c,"Debug()") : c
# GETTING MOTION LEVEL THROUGH MOTION ESTIMATION
c = FrameEvaluate(c,"ME()")
# GETTING DIFFERENCES BETWEEN PAST/PRESENT/FUTURE FRAMES
c = FrameEvaluate(c,"global diff = 0.50*YDifferenceFromPrevious(clip) + 0.25*UDifferenceFromPrevious(clip) + 0.25*VDifferenceFromPrevious(clip)")
return c
}
# DEBUG INFORMATION FUNCTION
function Debug(clip c)
{
# PRINTING VERSION INFORMATION
c = Subtitle(c,"Quantified Motion Filter",x=20,y=30,font="lucida console",size=18,text_color=$FFFFFF)
c = Subtitle(c,"by HomiE FR (homie.fr@wanadoo.fr)",x=20,y=45,font="lucida console",size=14,text_color=$FFFFFF)
# PRINTING MOTION ESTIMATION INFORMATION
c = Subtitle(c,"motion estimation",x=20,y=85,font="lucida console",size=18,text_color=$FFFFFF)
c = Subtitle(c,"diff = "+string(diff),x=20,y=110,font="lucida console",size=16,text_color=$FFCCCC)
# PRINTING QUANTIFIED MOTION FILTER INFORMATION
c = Subtitle(c,"quantified motion filter",x=20,y=135,font="lucida console",size=18,text_color=$FFFFFF)
c = (motion_level == 0) ? Subtitle(c,"scene type = low motion",x=20,y=160,font="lucida console",size=16,text_color=$66FF66) : c
c = (motion_level == 1) ? Subtitle(c,"scene type = medium motion",x=20,y=160,font="lucida console",size=16,text_color=$66FF66) : c
c = (motion_level == 2) ? Subtitle(c,"scene type = high motion",x=20,y=160,font="lucida console",size=16,text_color=$66FF66) : c
return c
}
last edited on: 02/23/2004 | Authors: Wilbert & Ivo