Conditional Temporal Median Filter http://kevin.atkinson.dhs.org/temporal_median/ Version 0.93 for AviSynth 2.5 September 27, 2003 Copyright (C) 2003 Kevin Atkinson (kevin.med@atkinson.dhs.org) under the GNU GPL version 2. This filter is designed to remove temporal noise in the form of small dots and streaks found in some videos. A common cause of this is dirty VHS heads but I have also seen small black or white streaks in broadcast material. The filter requires AVISynth 2.5, and My AviSynth C API Plugin version 0.14 or better. The required DLL "avisynth_c.dll" is included. The full version can be found at at http://kevin.atkinson.dhs.org/avisynth_c/. Two versions of my filter are provided a generic version CondTemporalMedian-gen.dll and an Integer SSE optimized version CondTemporalMedian-isse.dll. USAGE After the AviSynth C Plugin is loaded (by putting it in the Plugin directory or using LoadPlugin) the filter needs to be loaded using LoadCPlugin: LoadCPlugin(""). Basic Usage: ConditionalDenoise(clip, ) OR ConditionalMedian(clip, The input MUST be YV12. ConditionalDenoise will attempt to identify noise and eliminate it while ConditionalMedian will simply apply a simple temporal median filter to the non-moving areas of the image. Parms for ConditionalDenoise are any of the following p1 (default 24) p2 (default 12) A pixel needs to be at different from its neighbors by at least 'P1' in order for it to be considered noise. The surrounding pixels must be different by at lease 'P2' in order for the pixel to be considered part of the same speck. pwidth (default 16) pheight (default 5) A speck can be no larger than PWIDTH x PHEIGHT Parms for both ConditionalDenoise and ConditionalMedian are: mthres (default 16) A pixel needs to be different from the previous frame by at least 'MTHRES' in order to be considered moving. This number should be larger than 'P2' in order to prevent noise from being identified by motion. mwidth (default 7) mheight (default 5) mp (default 11) These control the behavior of the the motion map denoising algorithm. interlaced (boolean) Whether to treat the video as interlaced or not. The default depends on id AviSynth thinks the video is Field based (ie interlaced) or Frame based. To instead show a motion map and noise that would of been eliminated use: ConditionalDenoiseMap(clip, , [show_chroma = false]) ConditionalMedian(clip, , [show_chroma = false]) The luma is changed as follows: 255 (White): Noise that will be removed 159: Noise that won't be remove because it might be motion 95: Motion map for the current image 63: Motion map for the next frame To just highlight the noise instead of removing it use ConditionalDenoiseMark(clip, , [mark_v = 255]) Where mark_v is the luma value to highlight the noise with TUNING THE PARMS In order for the filter to work right the various parameters MUST be set correctly. There is no good default values. The first parameter that needs to be set is interlaced, set it to true if your video is interlaced, false otherwise. Than pwidth and pheight need to be set. Set these to be slightly larger than the specks you want to eliminate. If your video is interlaced than height represents the height of an individual field. Thus, it will essentially be doubled. Than p1, p2, and mthres need to be set. In general, p1 > mthres > p2. If these are set too low than you may lose detail as small pixel variations might be mistaken as specks, thus losing detail, and more importantly, real specks might not be recognized as the size of the filter thinks the spec is might be larger than pwidth by pheight. ConditionalDenoiseMark, and ConditionalDenoiseMap might be helpful in setting these parameters. HOW IT WORKS The filter works as follows: 1) Find pixes that are different from its neighbors by at least P1. 1b) Enlarge outliers based on P2. 2) Determine the size of the specks and reject all those larger than PWIDTHxPHEIGHT 3) Find moving areas of an image by simply comparing each pixel to the previous frame and considering all those which are greater than MTHRES. 3b) Remove pixels determined as noise from the motion map. 4) Denoise the motion map by diffusing and then diluting. This is probably the most important step. 5) Only remove the specks in which there was no motion in the current or the next frame. The filter can also be configured to work as follows: 1) Find moving areas of an image by simply comparing each pixel to the previous frame and considering all those which are greater than MTHRES. 2) Denoise the motion map by diffusing and then diluting. This is probably the most important step. 3) Apply a simple temporal median filter on the non-moving areas of the image. NOTES It is integer SSE optimized using either GCC or Intel MMX/SSE builtins. Unfortunately Gcc versions before 3.3 does not use them very well. There for it is recommended that either GCC 3.3+ or Intel's compiler is used. Even GCC 3.0 and Intel's compiler do not generate optimal code when using MMX/SSE builtins, in particular GCC 3.3 interests a few unnecessary movq. Thus hand optimizing some of the code might be beneficial. COMPILING To compile this filter you will need to install Gcc and perhaps GNU Make. I used MinGw (2.0.0-3) with MSYS 1.09, Gcc 3.3.1. All of the required utilities can be found at http://www.mingw.org/download.shtml. Other configurations should work, but you may need to edit the Makefile. Once all the proper tools are installed and in the path, simply type: make from the MSYS shell and that is all that should be required. CHANGES Changed from 0.92 (Sep 27, 2003) Fix another nasty bug. Included non optimized version. Expanded the manual a bit Changes from 0.91 (Sep 10, 2003) Fixed nasty bug.