From Avisynth wiki
Jump to: navigation, search
Author frustum & Theodor Anschütz & StainlessS
Version v0.12Beta3
Category Adjustment Filters
License GPLv2
Discussion Doom9 Thread (original) /// Doom9 Thread (update)


[edit] Description

Sometimes a video source will need to be adjusted because it is too dark, or too bright, or the contrast is too high or low, or the gamma value is wrong. By looking at the histogram of the video stream, it is often evident that the range of luma values of a video source is poorly distributed among the possible range of luma.

The AviSynth built-in filter called Levels() can be used to remap the luma value of all pixels to a more desirable distribution (or to intentionally to a "bad" one to achieve some effect). It is documented here: Levels

A continuous range of values is montonically mapped to a different range. levels() does it using this equation:

   output = [(input - input_low) / (input_high - input_low)] ^ (1/gamma)
          * (output_high - output_low) + output_low

In English, luma values less than or equal to input_low get mapped to 0.0 and values greater or equal to input_high get mapped to 1.0, and everything between is linearly interpolated. This intermediate value is raised to a power; note that 0.0 remains and 0.0 and 1.0 remains at 1.0, only values in between are changed. The pixel luma values then get mapped into the range of output_low to output_high.

One shortcoming of levels() is that the mapping parameters must be manually specified, which can be especially difficult as the input range often shifts during a video due to varying lighting conditions.

The ColorYUV() filter has an "autogain=true" option which measures the luma frame by frame and does a kind of levels() adjustment. A disadvantage of this approach is it can produce video that has sudden and unpleasant shifts in the brightness.

The autolevels() filter averages luma statistics from the frames in the vicinity of the current frame and uses that to decide how to set the appropriate input_low, input_high, and optionally gamma. It also offers a number of optional parameters for controlling how this averaging is performed

[edit] Requirements

*** vcredist_x86.exe is required for Autolevels-x86
*** vcredist_x64.exe is required for Autolevels-x64

[edit] Syntax and Parameters

Autolevels() syntax (don't be alarmed; the default is great for most of
them); some groups of parameters that operate together have been set off by
spaces to make the grouping obvious:

               int filterRadius,        default: 5 frames on either side
               int sceneChgThresh,      default: 20
               string frameOverrides,   default: ""

               float gamma,             default: 1.0
               bool autogamma,          default: false
               float midpoint,          default: 0.5

               bool autolevel,          default: true

               int input_low,           default: measured by statistics
               int input_high,          default: measured by statistics
               int output_low,          default:  16 for yuv,   0 for rgb
               int output_high,         default: 235 for yuv, 255 for rgb

               bool coring,             default: false

               float ignore,            default: 1.0/256.0
               float ignore_low,        default: 1.0/256.0
               float ignore_high,       default: 1.0/256.0

               int border,              default: 0
               int border_l,            default: 0
               int border_r,            default: 0
               int border_t,            default: 0
               int border_b,            default: 0

               bool debug)              default: false

All parameters are optional.  The filter has a second interface:

              ... same as before ...

The only difference is that autogamma() has the parameter autogamma true by
default and autolevel false by default.


* filterRadius specifies how many frames before and after the current frame
  are used to average the amount of gain.  The default is 5.  The higher
  the frame right the larger this number should be.

* sceneChgThresh is the detection threshold for scene changes. This parameter
  takes values between 0 and 255; the default is 20.  When the min or max
  luma of consecutive frames changes by more than this amount, it is assumed
  to be caused by a scene change.  This information is used to prevent the
  rolling average to cross a scene boundary.  A smaller number makes the
  trigger more sensitive, at the cost of false positives.

* frameOverrides is a string parameter that allows special handling of certain
  frames.  It is a comma-separated list; each list entry is one of the letters
  {S, N, E}, followed by a frame number or frame range. A range is two frame
  numbers separated by a dash. Depending on the preceding letter code, the
  frame / frame range is treated as follows:

  S<frame>: Assume a scene start at <frame>
            (overrides scene change auto detection)

  N<frame> or N<start-end>:
    Assume there is no scene start at <frame> or frames <start> to <end>,
    resp. (overrides scene change auto detection)

  E<frame> or E<start-end>:
    Leave <frame> or frames <start> to <end> unchanged, resp.

* gamma is used to manually specify a gamma adjustment, and has the same
  meaning as the gamma parameter of the levels() filter.  Although the gamma
  correction is done at the time as the autolevels histogram stretching,
  logically it is as if the gamma is done after the histogram has been
  stretched.  The default value of gamma is 1.0, which means it has no effect.
  This parameter is ignored if the autogamma option is true.

* autogamma is a boolean flag; setting it to true causes the filter to
  estimate a gamma correction parameter, which is then applied after the
  any autolevel histogram adjustment.  This is done by computing the mean
  luma of the frame and then computing a gamma which will move the mean
  to the midpoint luma value.

  The midpoint is 0.5 by default, but can overridden by specifying a midpoint
  parameter value.  The value is normalized to 0.0 being minimum intensity and
  1.0 being the maximum intensity.  I find a value of 0.4 to typically be
  more pleasing than 0.5 in many cases.  This parameter is ignored unless
  autogamma is true.

* autolevel specifies whether the luma histogram stretching is to be performed
  or not.  This is parameter is useful if you want to use autogamma only
  without the preceding autolevel adjustment.

* input_low specifies the point in the luma range which corresponds to the
  blackest pixel; any pixels with a lower luma also map to black.
  autolevels() normally determines this value itself, but if this value is
  specified, it takes priority over the frame statistics.
* input_high specifies the point in the luma range which corresponds to the
  brightest pixel; any pixels with a greater luma map to the same color.
  autolevels() normally determines this value itself, but if this value is
  specified, it takes priority over the frame statistics.

* output_low specifies what the blackest pixel value is in the post-adjusted
  image.  It defaults to 16 for yuv images and 0 for rgb images.

* output_high specifies what the brightest pixel value is in the post-adjusted
  image.  It defaults to 235 for yuv images and 255 for rgb images.

* coring is another feature implemented to allow autolevels() to be a
  superset of the built-in filter levels().  Note, though, that coring
  defaults to true for levels(), while it defaults to false for autolevels(),
  to match the behavior of older versions of autolevels().

  This parameter is ignored for rgb video sources.

  Like levels(), if coring is true, input/output low/high parameters are
  applied after the 16..235 luma range has been mapped to 0..255 and before
  it has been mapped back.

  If input_low and input_high are not manually specified and are
  automatically determined by the autolevels algorithm, the front end
  remapping of the luma range for "coring" is ignored and the low cutoff of
  the histogram is mapped to 0.0 and the high cutoff is mapped to 1.0.

* ignore, ignore_low, and ignore_high are used to control how much of the
  low and high tails of the luma histogram are to be ignored when computing
  the image statistics.  In versions 0.4 and earlier, this was hardwired to
  be 1.0/256.0, or about 0.4%, of all pixels.  This remains the default for
  backwards compatibility.

  If "ignore" is set, it applies to both the high and low tails of the
  histogram; "ignore_low" can be used to set the fraction of pixels ignored
  on the low (dark) tail of the distribution, while "ignore_high" does the
  same for the high (bright) tail.  Values up to 0.45 are allowed, but
  anything above a few percent leads to very bad range clipping.

* By default, statistics are gathered over the entire image, and these
  statistics drive the autolevel and autogamma behavior.  The border
  parameters can be used to specify that a band of pixels on one or more sides
  of the image should not be included in the statistics.  Whether a border is
  specified or not, the entire image is always processed.  Specifying
  "border=N" indicates that the N pixels from the left, right, top, and bottom
  edges are to be ignored.  "border_l" specifies the zone on the left edge to
  ignore; "border_r" does the same for the right edge, "border_t" for the top
  edge, and "border_b" for the bottom edge.  If both "border" and a specified
  border, say "border_t" are specified, the larger value is used.

  This feature is useful if the edges of the frame contain defects or
  brightness rolloff that aren't representative of the image in whole and
  might adversely affect the algorithm.

* debug reports some statistics about the frame, and reports when a scene
  change has been detected.

[edit] Examples

    autolevels(filterRadius=8, sceneChgThresh=10, frameOverrides="E8400-8405,S62908,S63315,N8527-8540")
    autolevels(sceneChgThresh=255)  [ effectively disables scene change logic ]
    autolevels(autolevel=false, autogamma=true)  [ autogamma only ]
    autolevels(ignore=1.0/500.0, gamma=1.5)

[edit] Changelog

// 01-09-2010   Ver. 0.6     + added support for the "coring" flag
// Jim Battle                + revised/improved the readme document
// StainlessS                
// 31/05/2019   Ver  0.7     + Convert for avs v2.6/+ x86 and x64. revised a bit.
// 06/05/2019   Ver  0.9     + Switch off debugging in v0.8, oops.
// 11/06/2019   Ver  0.10    + Oops, limited gamma max in adjust to 1.0 instead of 10.0 (so only ever reduced gamma, never increased).
//							   Mods to debug output, shows output Y frame average.
// 08/07/2019   Ver  0.11Beta1    + Basic scene change detect also now takes into account diffLumaMean((n,n-1))>=(sceneChgThresh*0.5), as well as min and max luma diff.
//							  + Added sc2Th=8, and sc2Perc=33.33, a check and possible override to sceneChgThresh detected scene change.
//							  + Changed default filterRadius from 5 to 7.
// 08/07/2019 Ver  0.11Beta2  + Added GamMax, GamMain.
// 09/07/2019 Ver  0.12       + Change Ignore default to 1.0/512 from 1.0/256. GamMax default 1.5 where AutoLevels(AutoGamma=true), else 10.0 where AutoGamma().
// 10/07/2019 Ver  0.12Beta_2 + GamMax default 1.5 where AutoGamma=true, else 10.0.
//						      + sc2Th default 12. Added minRng arg Default 100.
// 11/07/2019 Ver  0.12Beta_3 + Changes to debug metrics.

[edit] Archived Downloads

Version Download Mirror
v0.12Beta3 AutoLevels_25&
v0.10 AutoLevels_25&

[edit] External Links - v0.6 Homapage

Back to External Filters

Personal tools