Noise Generators - Avisynth filters for the generation of noise
By Ross Thomas <ross@grinfinity.com>
This distribution contains two filters, UniformNoise and GaussianNoise. As the more alert amongst you will have deduced, one generates uniformly distributed noise and the other generates normally distributed (or Gaussian) noise.
These are essentially wrappers around pseudo-random number generators (PRNGs). Each makes random numbers and uses them to populate a frame or frames of the clip. The exact nature of the random numbers can be fairly finely tuned with the filters' parameters.
The difference between the two filters is best illustrated by example. If you were to generate uniformly distributed random numbers between 0 and 100, each value (0, 1, 2, 3, etc.) would have an equal chance of occurring. That is to say, you're as likely to generate a 5 as you are an 80.
Gaussian random numbers are different in that the chance of each value occurring is not equal. Let's say you generate normally distributed numbers with a mean of 0 and a variance of 1 (for an explanation of these terms see the links at the end of the paragraph). The generator can in theory spit out any number that can fit into a 32-bit floating point, but taken as a whole the numbers will average out to zero (that's what mean=0, er, means). With these parameters about 68% of the values will be between -1 and 1, about 95% between -2 and 2, and about 99% between -3 and 3. The probability of generating numbers that are significantly higher or lower is very small indeed, with the probability getting smaller the further away from zero you get. You'd need to make billions of Gaussian random numbers with mean 0, variance 1 before you saw, for example, the value 9 being generated. You can read more about normal distribution
here and
here.
Uniform noise and Gaussian noise look quite different. Based on the above explanation it should be evident that uniform noise will be, well, uniform, while Gaussian noise will very much tend to concentrate around the specified mean. Gaussian noise is more "natural," since most things in nature (including spring precipitation, calorific intake, and, of course, noise) concentrate around "normal" values, with progressively less frequent occurrences as you get further from that norm.
Which type of noise you should use depends on the application. If applying noise to the entire frame, it might be best to use Gaussian noise as this is most similar to noise occurring in, for example, television signals from an antenna. For specific applications such as adding noise to very dark areas of a frame, uniform noise might be more suitable.
Rationale
Wait a minute! Add noise to a clip? Have I gone insane? Maybe.
These filters started out as an experiment, inspired by
this thread on Doom9's XviD forum, to determine the effect of noise on the so-called "dark blocks" produced by MPEG encoding. These little beasts tend to show up in areas that are predominantly one colour, especially dark areas. They occur less often with higher bitrates, but even DVD bitrates can't get rid of them completely. However, they do totally disappear when sufficient noise is added to the image... Hence these filters.
Yes, adding noise seriously affects compressibility. That's kind of the point. DCT blocks are a direct result of the MPEG encoder compressing too much. I suppose one's definition of "too much" varies, but for me it's when there are visible, distracting artifacts. Adding noise "forces" the encoder to compress less -- that is, make fewer blocks.
I find that adding noise generally produces a more aesthetically pleasing encode, at least when viewed on a TV set. Similar reasoning must have gone on behind ffdshow's "add noise" feature. You can find further discussion on adding noise to video (or "dithering")
here.
As always, your mileage may vary.
Usage
Usage is similar to the built-in BlankClip() filter:
Code:
UniformNoise(clip clip, int ya, int yb, int ua, int ub, int va, int vb, bool temporal, bool fast, int length, int width, int height, float fps, int fps_denominator, int audio_rate, bool stereo, bool sixteen_bit)
The defaults are chosen such that it will produce grayscale noise over the entire CCIR-601 legal TV range (Y=16-235).
Parameter | Meaning | Default |
clip | This optional parameter provides the default width, height, etc. for the generated clip. Whether a clip is specified or not, the defaults can be overridden by specifying the property as a parameter. | None |
ya, yb | Specifies the inclusive range of values to be generated for the luma (Y) component. | ya=16, yb=235 |
ua, ub | As ya and yb except for the chroma (U) component. | ua=128, ub=128 |
va, vb | As ua and ub for the chroma (V) component. | va=128, vb=128 |
temporal | If true causes the generator to produce new noise for each frame it makes. This is "classic" noise. If false the generator will make a frame of noise on startup and will return that frame every time. This makes "static" or "spatial" noise and is much faster than temporal noise, but probably not suitable for many applications. | True |
fast | (Note: The fast algorithm is only suitable for 32-bit IEEE floating point architectures. This means x86 and most *nix boxes, but not VAX.) Selects a much faster algorithm for generating random numbers. The trade-off is that this algorithm has a much lower period. It's still pretty good, though (it's "ranqd1" from Numerical Recipes in C) and is probably more than adequate for most applications. It's false by default only for compatibility. The default algorithm is "ran1" from the aforementioned text. | False |
length | The length of the clip in frames. | 240 |
width | The width of the frame in pixels. | 640 |
height | The height of the frame in pixels. | 480 |
fps | Number of frames per second. | 24 |
fps_denominator | The fps parameter is divided by the fps_denominator to obtain the final FPS of the clip. | 1 |
audio_rate | Number of audio samples per second. | 44100 |
stereo | Whether or not the clip's audio is stereo. | True |
sixteen_bit | Whether or not the clip's audio is sixteen-bit. | True |
The usage of GaussianNoise is very similar:
Code:
GaussianNoise(clip clip, float ym, float yv, float um, float uv, float vm, float vv, bool temporal, bool fast, int length, int width, int height, float fps, int fps_denominator, int audio_rate, bool stereo, bool sixteen_bit)
Defaults are chosen such that it will produce greyscale noise over the entire CCIR-601 legal TV range, predominantly mid-level luminosity (Y=100-150), without too much truncation of the tails.
Parameter | Meaning | Default |
ym, yv | The mean and variance for the luma (Y) component. | ym=125, yv=400 |
um, uv | As ym and yv for the chroma (U) component. | um=128, uv=0 |
vm, vv | As um and uv for the chroma (V) component. | vm=128, vv=0 |
Parameters not listed are the same as for UniformNoise (see above).
Both filters generate silence for the audio part of the clip.
Examples
Generate uniform noise over the entire range for Y, U and V:
Code:
UniformNoise(ua=16, ub=240, va=16, vb=240)
Generate just chroma noise:
Code:
UniformNoise(ya=235, yb=235, ua=16, ub=240, va=16, vb=240)
Generate normally distributed noise and blend it with a clip:
Code:
Layer(movie_clip, GaussianNoise(movie_clip, um=125, uv=400, vm=125, vm=125, vv=400), "add", 40)
Observations
With regard to reducing the occurrance of DCT blocks in MPEG-1 video, I find that adding chroma noise doesn't help much. Luma noise alone seens to be sufficient, and is also (theoretically) three times quicker to generate. With an averagely clean source DVD I find very pleasing results to be achieved with:
Code:
Layer(movie_clip, GaussianNoise(movie_clip), "add", level, use_chroma=false)
where level is between 10 and 15, with 10 being the most compressible (and having the most blocks) and 15 being the least (and having the fewest).
For this purpose UniformNoise does not perform well: it is too "harsh" and drastically increases file size even with very low level settings.
Using fast mode with GaussianNoise gives a slight performance boost (~3-5fps on my system) and doesn't noticibly affect the final product. Based on my tests so far I'd say fast mode is the way to go on 32-bit IEEE systems unless for some reason you need the very high period provided by the default mode.
Known Issues: Could be faster.
To-Do:
- MMX/SSE optimizations (I have to learn x86 assembler first...).
- Better sanity checking of parameters.
- Maybe implement more/different PRNG algorithms. For example, it might be sensible to add a portable algorithm (I have my eye on one in Knuth) that is in-between fast and precise mode as far as performance goes, and make it the default.
History
- 0.2 - Fixed pure virtual call runtime error when temporal=false.
- 0.1 - First release. Alpha code. Danger, Will Robinson!
Download here: SansGrip's Avisynth Filters [DOWNLOADS]