Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
|
18th February 2021, 15:33 | #1 | Link |
Registered User
Join Date: Feb 2021
Posts: 121
|
Brightness - restore dark and bright zones
This script will be useful for restoring dark and bright zones of a video or for smoothly changing luma.
Thanks to Didée for his Ylevels. This inspired me to create other functions. Code:
# Brightness v1.2 # # v1.0 - First release. # v1.1 - Adapted for use in all versions of AviSynth. # v1.2 - Changed the function for CurveL. # Now if 'light' > 0 bright areas will be brighter. # Changed the default value of 'light' to -20. /* Needed plugins: MaskTools2 v2.2.16 or greater. https://github.com/pinterf/masktools/releases http://avisynth.nl/index.php/MaskTools2/mt_lut Brightness(mode, dark, light, bit, chroma, DarkLightZonesOnly, SaveMinMaxLuma) mode: ----- "Line" - linear brightness variation. "Cos" - changes brightness by Cosine function. "Cube" - changes brightness by a cubic power function. Default: "Cube" dark: ----- The strength of changing dark zones. The recommended range is -30 ... 30. The range is not limited, in theory. Default: 20 light: ------ The strength of changing light zones. The recommended range is -30...30. Default: -20 bit: ---- Bit depth per channel in input clip. -1 - for autoscale in MaskTools2 (slower). 0 - for autodetection (faster). 8, 10, 12, 14, 16. Default: 0 chroma: ------- true - it means "process"; set u = v = 3 in mt_lut() MaskTools2. false - it means "copy" or "copy first"; set u = v = 2. Default: false DarkLightZonesOnly: ------------------- Changes only dark and light zones. true or false. If true, then "SaveMinMaxLuma" is ignored. Default: false SaveMinMaxLuma: --------------- Smooth brightness change for dark and bright zones. Keep minimum (0) and maximum (255) value of luma range. true or false. Default: true Usage Default: Brightness(mode="Cube", dark=20, light=-20, bit=0, chroma=false, DarkLightZonesOnly=false, SaveMinMaxLuma=true) or Brightness("Cube", 20, -20, 0, false, false, true) */ function Brightness(clip input, string "mode", float "dark", float "light", int "bit", bool "chroma", bool "DarkLightZonesOnly", bool "SaveMinMaxLuma") { mode = Default(mode, "Cube") dark = Default(dark, 20) light = Default(light, -20) bit = Default(bit, 0) chroma = Default(chroma, false) DLZO = Default(DarkLightZonesOnly, false) SMML = Default(SaveMinMaxLuma, true) Assert(mode == "Line" || mode == "Cos" || mode == "Cube", "Brightness: Mode must be: Line, Cos, Cube") Assert(bit == -1 || bit == 0 || bit == 8 || bit == 10 || bit == 12 || bit == 14 || bit == 16, \ "Brightness: Bit depth per channel must be only: 8, 10, 12, 14, 16 or -1, 0 for autodetection") Try { bpc = bit == 0 || bit == -1 ? input.BitsPerComponent : bit } Catch (msg) { bpc=8 } #BitsPerComponent only in AVS+ scale_inputs = bit >= 0 ? "none" : bpc == 8 ? "none" : "allf" #"all" range in 8 bits Y=16...235; "allf" range in 8 bits Y=0...255 use_expr = bit >= 0 ? 0 : bpc == 8 ? 0 : 2 chrom = chroma ? "process" : "copy" LUMA = bit >= 0 ? Pow(2.0, bpc) - 1 : 255.0 maxY = String(LUMA) midY = String(LUMA/2.0) stD = bit >= 0 ? String(dark * Pow(2.0, bpc - 8)) : String(dark) stL = bit >= 0 ? String(light * Pow(2.0, bpc - 8)) : String(light) k = String(mode == "Line" || mode == "Cube" ? 0 : 1) n = String(mode == "Cube" ? 3 : 1) # odd numbers only j = String(30) # even numbers only l = string(21) # odd numbers only m = String(SMML == true ? 1 : 0) f = String(mode == "Line" ? 1.25 : mode == "Cos" ? 1.15 : 1.05) curveD = dark == 0 ? "x" : !DLZO ? "x "+stD+" "+k+" 1 + 1 x "+midY+" / - "+n+" ^ * pi x * "+maxY+" / cos "+k+" * - * 1 1 x "+midY+" / - "+j+" ^ "+m+" * - * +" \ : "x "+stD+" 1 x "+midY+" / - "+l+" ^ pi x * "+maxY+" / cos "+l+" ^ - * "+f+" * -" curveL = light == 0 ? "x" : !DLZO ? "x "+stL+" "+k+" 1 + 1 x "+midY+" / - "+n+" ^ * pi x * "+maxY+" / cos "+k+" * - * 1 1 x "+midY+" / - "+j+" ^ "+m+" * - * -" \ : "x "+stL+" 1 x "+midY+" / - "+l+" ^ pi x * "+maxY+" / cos "+l+" ^ - * "+f+" * +" # function 1: x + 'st'*((1+'k')*(1 - x/127.5)^'n' - 'k'*cos(x*pi/255))*(1 - 'm'*(1 - x/127.5)^'j') # function 2: x - 'f'*'st'*((1 - x/127.5)^'l' - cos(x*pi/255)^'l') out = "x "+midY+" > "+curveL+" "+curveD+" ?" mt_lut(input, expr=out, Y=3, chroma=chrom, scale_inputs=scale_inputs, use_expr=use_expr) # mt_lut(input, expr=out, Y=3, chroma=chrom) # for MaskTools v2.0a48 } 1. Basic functions for smoothly changing luma: Backup copy formulas 1 graphs 1 2. Functions for changes only dark and light zones: Backup copy formulas 2 graphs 2 Examples: Brightness(mode="Cube", dark=20, light=0, bit=0, chroma=false, DarkLightZonesOnly=true, SaveMinMaxLuma=true) Backup copy Source frame Restored frame Comparison of original and restored clip Last edited by Arx1meD; 16th February 2023 at 16:56. Reason: Changed image hosting. In mt_lut changed yexpr to expr, use_expr to 2 |
16th February 2023, 09:25 | #6 | Link |
Registered User
Join Date: Apr 2019
Posts: 217
|
When I brighten something, I would add a certain value, and subtract a certain value when less bright, i.e. darker.
However in your script when I brighten bright zones by adding a certain value, it becomes darker, subtract a certain value and it becomes brighter. This makes no sense. Looking at the code I changed one thing, in red. Code:
curveL = light == 0 ? "x" : !DLZO ? "x "+stL+" "+k+" 1 + 1 x "+midY+" / - "+n+" ^ * pi x * "+maxY+" / cos "+k+" * - * 1 1 x "+midY+" / - "+j+" ^ "+m+" * - * +" \ : "x "+stL+" 1 x "+midY+" / - "+l+" ^ pi x * "+maxY+" / cos "+l+" ^ - * "+f+" * +" |
16th February 2023, 13:44 | #8 | Link | |
Registered User
Join Date: Apr 2019
Posts: 217
|
Quote:
dark + v = brighter light + v = brighter dark - v = less brighter (darker) light - v = less brighter (darker) logical with all existing software dealing with brightness. |
|
16th February 2023, 13:21 | #9 | Link |
Registered User
Join Date: Dec 2020
Posts: 84
|
CLAHE is also a very good filter for this: https://github.com/dnjulek/VapourSynth-EqualizeHist
(no AVS ver) |
16th February 2023, 14:43 | #10 | Link |
Registered User
Join Date: Feb 2021
Posts: 121
|
coolgit, I think you are right.
Formulas do not need to be changed. They are right. Need to invert part of the luma curve 127.5-255. Change only: Code:
light = Default(light, 20)*(-1.0) Code:
curveL = light == 0 ? "x" : !DLZO ? "x "+stL+" "+k+" 1 + 1 x "+midY+" / - "+n+" ^ * pi x * "+maxY+" / cos "+k+" * - * 1 1 x "+midY+" / - "+j+" ^ "+m+" * - * -" \ : "x "+stL+" 1 x "+midY+" / - "+l+" ^ pi x * "+maxY+" / cos "+l+" ^ - * "+f+" * +" out = "x "+midY+" > "+curveL+" "+curveD+" ?" Last edited by Arx1meD; 16th February 2023 at 15:09. |
17th November 2023, 12:29 | #15 | Link | |
Registered User
Join Date: Jun 2020
Posts: 303
|
Quote:
The save luma line variant would requires dark=-light in order to have continuity on contrast at x=0.5. it's possible to use lower values of n (ex n=2 or n=4 as in the plot linked below): f(x, k) = x + k*(1-2*x)(1-(1-2*x)^n) with n even, >0 and k in [-0.12, 0.12] https://raw.githubusercontent.com/bu...deContrast.png
__________________
bShaders: realtime Effects/filters for video players |
|
15th November 2023, 05:02 | #16 | Link |
Registered User
Join Date: Oct 2001
Location: Germany
Posts: 7,259
|
btw. if anyone got the time and motivation, a Vapoursynth port of this would be nice.
Also shouldn't there be some adjustemnts depending whether the source if 'limited' or 'full' luma? (to use 16-235 instead of 0-255) Last edited by Selur; 15th November 2023 at 05:05. |
17th November 2023, 17:55 | #17 | Link | |
Registered User
Join Date: Feb 2021
Posts: 121
|
Quote:
ColorYUV(levels="TV->PC") Brightness(...) ColorYUV(levels="PC->TV") |
|
Tags |
bright, dark, restore, zones |
Thread Tools | Search this Thread |
Display Modes | |
|
|