Log in

View Full Version : Local Contrast Enhancement


Pages : 1 [2] 3

poisondeathray
2nd February 2012, 00:46
http://cjoint.com/12fe/BBbwsW6v5pi.htm

I would like to remove the dark lines around the white neckties in this movie. Any suggestion ?

Previously i used internal sharpening from VD


Don't sharpen so much, but you can try dehalo filters e.g. dehalo_alpha

http://avisynth.org/mediawiki/External_filters#Dehaloing

lisztfr9
2nd February 2012, 11:32
Don't sharpen so much, but you can try dehalo filters e.g. dehalo_alpha

http://avisynth.org/mediawiki/External_filters#Dehaloing

Hi,

I agree for reducing the sharpening very often... for example unsharp mask in VD, this creates a lot of artifacts along edges, so i go back to moderated sharpen (internal).

Here is the original :

http://cjoint.com/12fe/BBclwfwaQAR.htm

===============================

I'm trying Dehalo_alpha, it needs the expand function. It is part from mastools, but i have all of them...

Ok, i have them all. This begins to wear my cpu (E8400) :)

At a first glance it's very impressive ! It does something on that nasty artifact, - i would never thought it was possible to reduce them ! Thanks very much for your work guys, and support !

lisztfr9
17th February 2012, 11:46
Now using VirturaldubMod to be able to "play" with the scripts... to fine tune them.

Before i used VD with dmpgdec & Vfapi...

http://www.animemusicvideos.org/guides/avtech/amvappvdubmod.html

http://docs.gimp.org/en/gimp-imaging-photos.html#gimp-using-photography

Equalize does a nice effect.

yup
24th February 2012, 10:13
Hi lisztfr9!
I have got it to work on the video i want to convert.

The colors seems more saturated, but in another way that would be provided by colormil (VD), more neutral, and better imho.

This is a Local contrast enhancement filter, witch is very often my preferred image processing method... it should be used with very large radius, like 50 :

http://gimpguru.org/tutorials/removinghaze/

"Set the Radius parameter to a largish, seemingly unreasonable value somewhere between 50 and 100."
It is can implement with Avisynth

ColorYUV(autogain=true, autowhite=true)
unsharp(varY=15,varC=15,strength=1.0)# tritical variableblur revision

I try with my VHS capture source and see improvements.
yup.

yup
29th February 2012, 06:32
Hi all!
I suggest variance value relative low for this purpose.
I try find relation between radius for Gaussian blur and variance, i find two approaches:
from Gimp
sigma=(radius+1)/sqrt(2*log10(255))
variance=sigma^2=(radius+1)^2/(2*log10(255))
from common knowledge about normal distribution
3*sigma=radius
variance=radius^2/9
Both give higher value variance for local contrast enhancement from 250 to 2000 and for this value I see increase contrast even at strength 0.4.
Please confirm my calculations.
yup.

lisztfr9
16th April 2012, 09:57
(OT)

Hi guys,

I have a video with so many problems (VHS record) :

1) The video jerks vertically. It's unstable vertically
2) There is a echo artifact, in form of a white strip (could be blend out with some alpha blending).
3) There is also some flickering, sometimes : the luminescence quickly changes...

not mention awful chroma noise, etc.

Could the flickering be stabilized with some conditional scripting based on luma ?

Anyway this is OT, i will open new thread for healing this video.

lisztfr9
16th April 2012, 13:19
(OT)

Hi guys,

I have a video with so many problems (VHS record) :

1) The video jerks vertically. It's unstable vertically
2) There is a echo artifact, in form of a white strip (could be blend out with some alpha blending).
3) There is also some flickering, sometimes : the luminescence quickly changes...

not mention awful chroma noise, etc.

Could the flickering be stabilized with some conditional scripting based on luma ?

Anyway this is OT, i will open new thread for healing this video.


Hi all,

I already found some virtualdub filters for healing the flickering and the image shaking, Defliker and deshaker, but remains one nasty artifact, like here :

http://cjoint.com/12av/BDqolUo6ves.htm

How would you handle this ? subtracting a mask from the image, - but any advice would be thankfully taken. Also a good tutorial explaining avisynth scripting...

Maybe building on-the-fly the mask from the black strip donwside...

Thanks, L

lansing
20th April 2012, 04:00
in the HighlightLimiter script in post #28, smode was deleted from the newer version of SmoothLevels

Chainmax
14th May 2012, 16:08
So the current latest version of HighlightLimiter is the one on post 28 and the latest version of ContrastMask is on the OP, right? Also, is ContrastMask supposed to be obsolete with the latest HighlightLimiter?

javlak
16th May 2012, 12:13
Hi everyone,

Unfortunately my time is extremely limited so I don't have too much time to work on these scripts. Please feel free to adjust/develop/change them to fit your needs.

To answer your question Chainmax, ContrastMask has different functionality in the sense that it is purely a contrast mask, while the Highlight/HighlightLimiter functions do things a bit differently. You can see the differences in the posts made by travolter. I guess what I'm trying to say is that if you are looking for a contrast mask to see how it affects your picture, then ContrastMask is what you're looking for. Otherwise you can call it obsolete. These are the versions I have on my PC (and indeed they were written for SmoothLevels 1.x, the smode bit should be removed for SmoothLevels 2.x, but I think the end result might vary a bit so it might need some tweaking in that respect):


function HighlightLimiter(clip v, float "gblur", bool "gradient", int "threshold", bool "twopass", int "amount", bool "softlimit", int "method")
{
gradient = default (gradient,true) #True uses the gaussian blur to such an extent so as to create an effect similar to a gradient mask being applied to every area that exceeds our threshold.
gblur = (gradient==true) ? default (gblur,100) : default (gblur,5.0) #The strength of the gaussian blur to apply.
threshold = default (threshold,150) #The lower the value, the more sensitive the filter will be.
twopass = default (twopass,false) #Two passes means the area in question gets darkened twice.
amount = default (amount,10) #The amount of brightness to be reduced, only applied to method=2
softlimit = default (softlimit,false) #If softlimit is true, then the values around the edges where the pixel value differences occur, will be averaged.
method = default (method, 1) #Method 1 is multiply, the classic HDR-way. Any other method set triggers a brightness/gamma approach.

amount = (amount>0) ? -amount : amount

darken=v.Tweak(sat=0).mt_lut("x "+string(threshold)+" < 0 x ?")
blurred= (gradient==true) ? darken.gaussianblur(gblur).gaussianblur(gblur+100).gaussianblur(gblur+200) : darken.gaussianblur(gblur)
fuzziness_mask=blurred.mt_edge(mode="prewitt", Y=3, U=2, V=2).mt_expand(mode="both", Y=3, U=2, V=2)
multiply = (method==1) ? mt_lut(v,"x x * 255 /") : v.Tweak(bright=amount)
multiply = (method==1) ? eval("""
(twopass==true) ? mt_lutxy(multiply,v,"x y * 255 /") : multiply""") : eval("""
(twopass==true) ? multiply.SmoothLevels(gamma=0.9,smode=2) : multiply""")

merged=mt_merge(v,multiply,blurred)
fuzzy= (softlimit==true) ? mt_merge(merged,mt_lutxy(v,merged,"x y + 2 /"),fuzziness_mask) : merged
return fuzzy
}



function Highlighter(clip v, float "gblur", bool "gradient", int "threshold", bool "twopass", int "amount", bool "softlimit", int "method")
{
gradient = default (gradient,true)
gblur = (gradient==true) ? default (gblur,100) : default (gblur,5.0)
threshold = default (threshold,100) #The lower the value, the more sensitive the filter will be.
twopass = default (twopass,false)
amount = default (amount,10)
softlimit = default (softlimit,false)
method = default (method, 1)

amount = (amount<0) ? abs(amount) : amount

lighten=v.Tweak(sat=0).mt_lut("x "+string(threshold)+" > 0 x ?")
blurred= (gradient==true) ? lighten.gaussianblur(gblur).gaussianblur(gblur+100).gaussianblur(gblur+200) : lighten.gaussianblur(gblur)
fuzziness_mask=blurred.mt_edge(mode="prewitt", Y=3, U=2, V=2).mt_expand(mode="both", Y=3, U=2, V=2)
photoshop_overlay = (method==1) ? mt_lutxy(v,blurred.invert(),"x 127.5 > y 255 x - 127.5 / * x 255 x - - + y x 127.5 / * ? ") : \
(method==2) ? mt_lutxy(v,blurred.invert(),"255 255 x - 255 y - * 255 / -") : v.Tweak(bright=amount)
photoshop_overlay = (twopass==true) ? photoshop_overlay.SmoothLevels(gamma=2.0,smode=2) : photoshop_overlay
merged=mt_merge(v,photoshop_overlay,blurred)
fuzzy= (softlimit==true) ? mt_merge(merged,mt_lutxy(v,merged,"x y + 2 /"),fuzziness_mask) : merged
return fuzzy
}

Gavino
16th May 2012, 12:40
function Highlighter(...)
{
...
(method==2) ? mt_lut(v,mt_polish("255 255 x - 255 y - * 255 / -")) : v.Tweak(bright=amount)
...
}
:confused:

mt_polish expects an infix (ie 'normal'-type) expression as input.

javlak
16th May 2012, 13:11
:confused:

mt_polish expects an infix (ie 'normal'-type) expression as input.

Corrected the 6-month old error there. Thanks for that Gavino!

Chainmax
6th June 2012, 01:10
I am getting an out-of-bounds memory access error related to fftw3.dll, of which the latest version is installed on my system.The current filterchain HighlightLimiter is on is as follows:

SetMemoryMax(900)

SetMTMode(5,4)

*plugin loading calls*

MPEG2Source("x:\wherever\somesource.d2v")

SetMTMode(2)

QTGMC(Preset="Very Slow", SubPel=4, Blocksize=8, Overlap=4, NNsize=3, NNeurons=4, EdiQual=2, EdiThreads=4)

vinverse()

Levels(10,1,253,16,235)

HighlightLimiter(70,true,80,false,100)

RemoveGrain(mode=5)

Stab()
Crop(2,2,718,574,align=true)
Spline36Resize(720,576)

source=last
preNR=source.RemoveGrain(mode=5)
preNR_super=preNR.MSuper(pel=2, sharp=1)
source_super=source.MSuper(pel=2, sharp=1)
backward_vec3 = MAnalyse(preNR_super,isb = true, delta = 3, overlap=4)
backward_vec2 = MAnalyse(preNR_super,isb = true, delta = 2, overlap=4)
backward_vec1 = MAnalyse(preNR_super,isb = true, delta = 1, overlap=4)
forward_vec1 = MAnalyse(preNR_super,isb = false, delta = 1, overlap=4)
forward_vec2 = MAnalyse(preNR_super,isb = false, delta = 2, overlap=4)
forward_vec3 = MAnalyse(preNR_super,isb = false, delta = 3, overlap=4)
source.MDegrain3(source_super,backward_vec1,forward_vec1,backward_vec2,forward_vec2,backward_vec3,forward_vec3,thSAD=375)

Spline36Resize(800,600)

GradFunkMirror(3.02)

dull=last
sharp=dull.LimitedSharpenFaster(Smode=4,Strength=250)
Soothe(sharp,dull,25)

Tweak(sat=1.4)

AddGrain(5,0.6,0.6)

AddGrain(3,0.2,0.2)

Distributor()

yup
6th June 2012, 06:14
Chainmax!
Try
EdiThreads=1 at QTGMC call.
yup.

Chainmax
6th June 2012, 14:05
Thanks for the suggestion yup, but as expected that didn't work, as the problem is when it uses the fftw3 DLL, likely on the HighlightLimiter call (it never did with DFTTest) and was the reason I upgraded to its latest version.

yup
6th June 2012, 16:10
Chainmax!
I am also update to last version libfftw3f-3.dll and dfttest work without problem.
yup.

Chainmax
9th June 2012, 14:23
Thanks yup, but like I said in the first post I already have the lates version of that DLL.

Chainmax
19th June 2012, 01:21
Anyone else?

matfra
19th June 2012, 14:10
Hello everyone.
This is the kind of script that I was looking for ! im a master of Photoshop and I used this technique a lot.
Can someone post the lastest version of those script please.
There is so mutch update in every pages. Im not sure what is the current version for those script.
Thank !!!

function Highlighter
function HighlightLimiter
function NonlinUSM
function LCE
function ContrastMask

travolter
23rd March 2013, 21:29
I did a mod of the original highlight limiter.
I wonder if its possible fix this highlight limiter version to use less CPU or maybe the effect can be archived easier


v=last
threshold=123
darken=v.Tweak(sat=0).mt_lut("x "+string(threshold)+" < 0 x ?")
rad=64
blurred=darken.bicubicresize(round(v.width()/rad/4)*4,round(v.height()/rad/4)*4).bicubicresize(v.width(),v.height(),1,0)
multiply=mt_lut(v,"x x * 265 /")
mt_merge(v,multiply,blurred)


(For more black .. increase the "265" value)

Blur code comes from Didée... original script posted in this thread

Chainmax
28th April 2013, 18:54
Since HighlightLimiter and dfttest use different FFTW3 versions, is there a way to use both filters in the same script?

javlak
29th April 2013, 11:56
Since HighlightLimiter and dfttest use different FFTW3 versions, is there a way to use both filters in the same script?

Hi,

I use both dfttest and HighlightLimiter in a lot of my scripts without problems. Even though I am not sure of the version of fftw3 I have, do you want me to upload it?

Chainmax
12th May 2013, 15:24
Thanks, but there's no need for that. This is more of a curiosity thing than anything else.

javlak
13th May 2013, 13:47
Well in that case I guess you could write a script that does the HighlightLimiter stuff, then mount it using pismo and avfs and then write another script that uses dfttest to denoise the mounted script as .avi. Never tried that one, but I think it should work.

Mixxen Mach
28th January 2016, 03:58
[QUOTE=javlak;1514814]

[snip]
photoshop_overlay=mt_lutxy(v,v2,"x 127.5 > y 255 x - 127.5 / * x 255 x - - + y x 127.5 / * ? ")
merged=overlay(v,photoshop_overlay,opacity=enhance)
[snip]


Hi
I came in through the wrong door and I'm finding very useful-looking information here which I still need to fully learn how to apply.
I don't understand the Photoshop reference here--do I need to have Photoshop (I have GIMP) and do I need to create anything with PS here?
I need to be pointed to the introductory articles explaining how to use this information.

(I'm using this script in AvsPmod)

Thanks
MM

`Orum
29th January 2016, 20:40
I don't understand the Photoshop reference here--do I need to have Photoshop (I have GIMP) and do I need to create anything with PS here?

No. This is simply the name given to the variable and has nothing to do with Adobe Photoshop beyond what is in the filter's description.

Mixxen Mach
31st January 2016, 03:28
No. This is simply the name given to the variable and has nothing to do with Adobe Photoshop beyond what is in the filter's description.

Thanks!

LigH
18th August 2017, 10:48
:thanks:

Using ContrastMask to enhance a nightshot of a surveillance camera, trying to identify a number plate thief... Not much time to tune parameters, but defaults already help recognizing the body traits.

fenomeno83
7th October 2017, 13:08
@ travolter

Well, it's tricky. The best way to "not overdo" the effect is .... to not overdo the effect. :)

It could help to use some "parallel-path denoising", see here (http://forum.doom9.org/showthread.php?t=153170). Though, it depends on the temporal characteristic of those unwanted spots. If they are fluctuating, good. If they are persistent/static, bad luck.

It would also help to use stronger low-damping (not parametrized, it's the "0.001 +" term in the lut that would need to be increased). However, while this will reduce emphasizing of unwanted spots, it necessarily will also reduce the emphasizing of spots where the effect is actually welcome. Old story: there is a small pixel variation. Is it noise? Is it detail? Simple algorithms can't tell -- it's just that: a small pixel variation.


@ lisztfr9

function NonlinUSM(clip o, float "z", float "pow", float "str", float "rad", float "ldmp")
{
z = default(z, 6.0) # zero point
pow = default(pow, 1.6) # power
str = default(str, 1.0) # strength
rad = default(rad, 9.0) # radius for "gauss"
ldmp= default(ldmp, 0.001) # damping for verysmall differences

g = o.bicubicresize(round(o.width()/rad/4)*4,round(o.height()/rad/4)*4).bicubicresize(o.width(),o.height(),1,0)

mt_lutxy(o,g,"x x y - abs "+string(z)+" / 1 "+string(pow)+" / ^ "+string(z)+" * "+string(str)+
\ " * x y - 2 ^ x y - 2 ^ "+string(ldmp)+" + / * x y - x y - abs 0.001 + / * +",U=2,V=2)

#interleave(o,last) # just for visualisation, you don't want the function to do this

return(last)
}

Note that I renamed the function to "NonlinUSM" (for "non-linear Unsharp Masking"). The name in itself doesn't matter, you could as well name it MickeyMouse() or BlueElephant() if you wanted. But since the function "sharpen2" is already used in SeeSaw, it seems better to use any other name, in order to avoid possible conflicts.

Hi.
I'm using this sharpener and seems works very good.
I use it in photos
My problem is that is heavily dependent by photo resolution.
So the same parameters works too hard for lower resolution photos and good for high resolution photos and vice versa..
is there something to adaptable to photo resolution?

My purpouse is:
if in a a photo with for example resolution 4000x3000 works fine some settings, If I for example scale the same image to 2000x1500 what settings generates a comparable results?
some algorithm/setting indipendent by photo resolution... thanks

StainlessS
7th October 2017, 15:43
No idea, but perhaps below will assist someone else figure it out,


z = default(z, 6.0) # zero point
pow = default(pow, 1.6) # power
str = default(str, 1.0) # strength
ldmp= default(ldmp, 0.001) # damping for verysmall differences


rpn="x x y - abs "+string(z)+" / 1 "+string(pow)+" / ^ "+string(z)+" * "+string(str)+" * x y - 2 ^ x y - 2 ^ "+string(ldmp)+" + / * x y - x y - abs 0.001 + / * +"


rpn="x x y - abs z / 1 pow / ^ z * str * x y - 2 ^ x y - 2 ^ ldmp + / * x y - x y - abs 0.001 + / * +"

Infix="(
x+(
[ ((((abs(x-y)/z)^(1/pow))*z)*str) * (((x-y)^2) / (((x-y)^2)+ldmp)) ] * [(x-y)/(abs((x-y)) + 0.001)]
)
)"


The 0.001 in Magenta is the Didee mentioned "low-damping (not parametrized, it's the "0.001 +" term"
The red bracketed [] chunk will result, 1.0 + 0.001 if x-y is +ve and -1.0 + 0.001 if -ve.

fenomeno83
7th October 2017, 16:25
Thanks!
these parameters (thanks to raffriff42) works very fine with 15Mpx photos
NonlinUSM(z=3, str=0.5, rad=9, pow=1)...
they apply a little sharpening that removes the little blur effect...
but if I use the same parameters on 5/8MP photos, the effect is stronger...

It would be nice have something normalized, so if I apply a set of parameters because I want I specific power of the filter, they shoud produce the same/similar results independently of photo resolution

StainlessS
7th October 2017, 16:58
OK, where did RaffRiff post those numbers ?

With 5/8MP, maybe try z=1.5 or z=2.0, might also try str=0.25 or str=0.3 or str=0.4.
pow=1.0, switches off that effect [EDIT: z effect].

fenomeno83
7th October 2017, 17:17
I asked him by pm about a good sharpener..but values are just "starting point" (but i like them in 15Mp photos)
They are also here
http://avisynth.nl/index.php/NonlinUSM

Thanks for your suggestion..i'll try.
Should be usefull have a function that starting from parameters/resolution and desidered resolution return new parameters.
Something like parameters1:resolution1=parameters2:resolution2

StainlessS
7th October 2017, 17:30
Thanx for pointing that out on wiki, also nice link pointing here;- https://forum.doom9.org/showthread.php?t=171050&highlight=nonlinusm
for Usage Examples, explains whats happening a bit more (I'm beginning to understand it a lil bit now).

EDIT: Usage examples from above link below

NonlinUSM(pow=4) ## enhance: for low bitrate sources
NonlinUSM(z=3, pow=4.0, str=1, rad=6) ## enhance less
NonlinUSM(z=3, str=0.5, rad=9, pow=1) ## enhance less

NonlinUSM(z=6, str=1.5, rad=0.6).Sharpen(0.3) ## sharpen: for hi-q sources
NonlinUSM(z=3, str=2.5, rad=0.6) ## sharpen: less noise
NonlinUSM(z=6, pow=1.0, str=1, rad=6) ## unsharp

NonlinUSM(pow=1.0, rad=2, str=0.7) ## "smoothen" for noisy sources
NonlinUSM(pow=1.0, rad=18, str=0.5) ## smear: soft glow

NonlinUSM(z=6, pow=4.0, str=1, rad=36) ## local contrast
NonlinUSM(z=6, pow=1.0, str=1, rad=36) ## local contrast
NonlinUSM(z=16, pow=4.0, str=18, rad=6) ## B+W psychedelic
NonlinUSM(z=16, pow=2.0, str=2, rad=36) ## solarized
NonlinUSM(z=16, pow=4.0, str=3, rad=6) ## sepia/artistic

fenomeno83
7th October 2017, 18:12
Thanks! Should be useful create the same function but indipendent by resolution..some coefficient to multiply to different params, based on resolution

StainlessS
7th October 2017, 19:16
Small point, but methinks that rad (ie radius) is actually a diameter, and should perhaps always be odd (integer, 3 or more), maybe wrong, any thoughts ?

EDIT: Not strictly necessary, but rad=9 is sort of diameter = 9, rad = (9-1) / 2.0 == rad 4.0 outside of current pixel.
rad=6 is sort of diameter = 6, rad = (6-1) / 2.0 == rad 2.5 outside of current pixel.

EDIT: I would like some comment from anybody on this.

raffriff42
7th October 2017, 21:18
These are my notes (made a long time ago) on NonlinUSM's arguments ## @ z - default 6 (3 = subtle; 16 = massive)
## @ pow - default 1.6 (1.0 = oversharp; 4.0 = mild)
## @ str - default 1.0 (3 = strong; 18 = massive)
## @ rad - default 9 (0.6 = sharpen; 18 = soft)
## @ ldmp - default 0.001 (block overlap? 0.01 = a little smoother?)
##
function NonlinUSM(clip o, float "z", float "pow",
\ float "str", float "rad", float "ldmp")
...
The arguments are a mystery to me, really.

StainlessS
7th October 2017, 21:37
The arguments are a mystery to me, really.

Me too, but I'm trying (hard) to understand.

If you downsize by eg 3, then upsize (to same size) again, I think that you are using a diameter of 3 and a radius of 1 (outside of current pixel), do that seem at all correct to you ?

EDIT: This is screwing with my head. (It seems easy, then I get into a mode where it gets way complicookered)

raffriff42
7th October 2017, 23:38
The code here (https://forum.doom9.org/showthread.php?p=1555234#post1555234)...g = o.bicubicresize(round(o.width()/rad/4)*4,round(o.height()/rad/4)*4)
\ .bicubicresize(o.width(),o.height(),1,0)
...is a "quick and dirty" version of a proper Gaussian blur. Good enough for purpose, but "rad" does not exactly track (for example) Photoshop's Gaussian blur with the same radius.

"Radius" is used inconsistently by different software. It does not have to be even or even integral. Gaussian blur with radius=0.3 is perfectly usable.

https://dsp.stackexchange.com/questions/10057/gaussian-blur-standard-deviation-radius-and-kernel-size
Blur radius explained :rolleyes:

fenomeno83
8th October 2017, 09:55
Small point, but methinks that rad (ie radius) is actually a diameter, and should perhaps always be odd (integer, 3 or more), maybe wrong, any thoughts ?

EDIT: Not strictly necessary, but rad=9 is sort of diameter = 9, rad = (9-1) / 2.0 == rad 4.0 outside of current pixel.
rad=6 is sort of diameter = 6, rad = (6-1) / 2.0 == rad 2.5 outside of current pixel.

EDIT: I would like some comment from anybody on this.

so, in your opinion I could adapt just "rad" params based on resolution, and keep the others params the same, to get a similar result?

for example:
in 15Mp I use
NonlinUSM(z=3, str=0.5, rad=9, pow=1)
for a smaller resolution I could use
NonlinUSM(z=3, str=0.5, rad=4, pow=1)
??

StainlessS
8th October 2017, 10:29
so, in your opinion ...
Not sure that I have an opinion any more :)

Having looked at Raffs link, have decided to throw all maths out of the window, and choose my own model of what its doing.
In the downsize, it is getting the average local luminance, where each out pixel is average of rad*rad input.
On upsize, is merely tweening the downsized pixels, where result is approx local luminance average.
EDIT: In the downsize, rad is actually a Diameter, which is converted to a radius via the upsize 2D tweening.

If pow=1.0, then I think that z makes no difference


Infix="(
x+(
[ ((((abs(x-y)/z)^(1/pow))*z)*str) * (((x-y)^2) / (((x-y)^2)+ldmp)) ] * [(x-y)/(abs((x-y)) + 0.001)]
)
)"

You're just dividing by z, raising to the power of 1.0 (ie do nothing) and then multiplying by z to bring it back to original value.

I dont know what is best 'normalizer' based on image size, but gut feeling is on rad.
Guess that you just have to do a lot of playing with the numbers to see what seems best to you.
EDIT: I dont have a load of images to test ( and dont want any, thanx :) ).

StainlessS
8th October 2017, 11:39
Is this any kind of improvement (added limiter)

Function Sub(clip c,string Tit,Bool "ShowFrameNo",int "first_frame", int "last_frame",string "font",float "size",int "text_color",
\ int "halo_color",int "align",int "spc",float "font_width",float "font_angle",Int "BackColor") {
/*
Stack Overhead Subtitle Text, with optional FrameNumber shown
http://forum.doom9.org/showthread.php?p=1813402#post1813402
Title bar is Round(size+2) pixels hi (default 20).
Dont use align=4,5,6, better use 1,2,3,7,8,or 9.
*/
ShowFrameNo=Default(ShowFrameNo,False) first_frame=Default(first_frame,0) last_frame=Default(last_frame,c.FrameCount-1)
font=default(font,"Ariel") size=Default(size,18.0) text_color=Default(text_color,$00FFFF00)
halo_color=Default(halo_color,$00000000) align=default(align,7) spc=Default(spc,0)
font_width=Default(font_width,0) font_angle=Default(font_angle,0.0) BackColor=Default(BackColor,$00000000)
c.BlankClip(height=round(size+2.0),Color=BackColor)
(ShowFrameNo)
\ ? ScriptClip("""Subtitle(String(current_frame,"%.0f] ")+"""+Chr(34)+Tit+Chr(34)+String(first_frame,",first_frame=%.0f")+
\ String(last_frame,",last_frame=%.0f,font=")+Chr(34)+font+Chr(34)+String(size,",size=%.3f")+String(text_color,",text_color=%.0f")+
\ String(halo_color,",halo_color=%.0f")+String(align,",align=%.0f")+String(spc,",spc=%.0f")+String(font_width,",font_width=%.3f")+
\ String(font_angle,",font_angle=%.3f)"))
\ : Subtitle(Tit,first_frame=first_frame,last_frame=last_frame,font=font,size=size,text_color=text_color,halo_color=halo_color,align=align,
\ spc=spc,font_width=font_width,font_angle=font_angle)
Return StackVertical(c).AudioDubEx(c)
}


Function NonlinUSM(clip o, float "z", float "pow", float "str", float "rad", float "ldmp") {
z = default(z, 6.0) # zero point
pow = default(pow, 1.6) # power
str = default(str, 1.0) # strength
rad = default(rad, 9.0) # radius for "gauss"
ldmp= default(ldmp, 0.001) # damping for verysmall differences

g = o.bicubicresize(round(o.width()/rad/4)*4,round(o.height()/rad/4)*4).bicubicresize(o.width(),o.height(),1,0)

rpn="x x y - abs "+string(z)+" / 1 "+string(pow)+" / ^ "+string(z)+" * "+string(str)+" * x y - 2 ^ x y - 2 ^ "+string(ldmp)+" + / * x y - x y - abs 0.001 + / * +"
mt_lutxy(o,g,rpn,U=2,V=2)

#interleave(o,last) # just for visualisation, you don't want the function to do this

return(last)
}

Z=6.0 POW=1.6 STR=1.0 RAD=9.0 LDMP=0.001

Imagesource("1.jpg",end=0).ConvertToYV12
O=Last
NonlinUSM(z=Z,pow=POW,rad=RAD)
A=Last
Limiter()
S=String(Z," : Z=%.3f") + String(POW," : POW=%.3f") + String(STR," : STR=%.3f") + String(RAD," : RAD=%.3f") + String(LDMP," : LDMP=%.3f")
StackVertical(A.Histogram(mode="levels").Sub("No Limiter"+S),Last.Histogram(mode="levels").Sub("Limiter"+S))

https://s20.postimg.cc/d5grilc71/karate.jpg (https://postimages.cc/)

EDIT: I guess that it would be no improvement converting to RGB from TV levels, although I'm not sure how YUV->RGB limits
where result is illegal RGB.

EDIT: Original (probably not the best image to try it out on)
https://s20.postimg.cc/n43z6eltp/img_0001.jpg (https://postimages.cc/)

StainlessS
8th October 2017, 12:40
# Generate clip with varying args to NonlinUSM().


# Generate clip with varying args to NonlinUSM().

FN="1.jpg"

Imagesource(FN,end=0)
Crop(0,0,Width/4*4,Height/4*4)
MAT="Rec709"
#MAT="PC.709"
ConvertToYV12(Matrix=MAT)

Global ORG=Last
### CONFIG ###
Global Z_START = 3.0 Global Z_STEP = 0.25
Global POW_START= 1.1 Global POW_STEP = 0.1
Global STR_START= 0.5 Global STR_STEP = 0.05
Global RAD_START= 5.0 Global RAD_STEP = 0.5
Global STEPS = 10
Global STACK = True # Stack Vertical (if true)
Global STKLIM = True # STACK LIMITER rather that ORG clip (if also STACK)
### END OF CONFIG ###
FRAMES=Round(Pow(STEPS,4))
HIT = (Height+20)*(STACK?2:1) # Subtitles add 20 to height
DUMMY=Last.BlankClip(Length=FRAMES,Height=HIT,Width=Width+256) # Histogram adds 256 to width
Global ORG=ORG.Loop(FRAMES) # Make it work with Sub(ShowFrameNo=True)

GScript("""
Function Func(clip c) {
c
n = current_frame
#### Can mod for fastest changing variables by changing line order, Below first one(by default Z) is fastest changing (RAD by default slowest).
q = n % STEPS Z = Z_START + q * Z_STEP n = n / STEPS
q = n % STEPS POW = POW_START + q * POW_STEP n = n / STEPS
q = n % STEPS STR = STR_START + q * STR_STEP n = n / STEPS
q = n % STEPS RAD = RAD_START + q * RAD_STEP n = n / STEPS
####
S=RT_String(" : Z=%.3f : POW=%.3f : STR=%.3f : RAD=%.3f",Z,POW,STR,RAD)
A=ORG.NonlinUSM(z=Z,pow=POW,str=STR,rad=RAD)
B=(STACK) ? (STKLIM ?A.Limiter.Histogram(mode="levels").Sub("Limiter"+S):ORG.Histogram(mode="levels").Sub("Original")) : 0
C1 = A.Histogram(mode="levels").Sub(RT_String("No Limiter %s",S),true)
(STACK) ? StackVertical(C1,B) : C1
}
""")

Return DUMMY.ScriptClip("Func()")


Function Sub(clip c,string Tit,Bool "ShowFrameNo",int "first_frame", int "last_frame",string "font",float "size",int "text_color",
\ int "halo_color",int "align",int "spc",float "font_width",float "font_angle",Int "BackColor") {
/*
Stack Overhead Subtitle Text, with optional FrameNumber shown
http://forum.doom9.org/showthread.php?p=1813402#post1813402
Title bar is Round(size+2) pixels hi (default 20).
Dont use align=4,5,6, better use 1,2,3,7,8,or 9.
*/
ShowFrameNo=Default(ShowFrameNo,False) first_frame=Default(first_frame,0) last_frame=Default(last_frame,c.FrameCount-1)
font=default(font,"Ariel") size=Default(size,18.0) text_color=Default(text_color,$00FFFF00)
halo_color=Default(halo_color,$00000000) align=default(align,7) spc=Default(spc,0)
font_width=Default(font_width,0) font_angle=Default(font_angle,0.0) BackColor=Default(BackColor,$00000000)
c.BlankClip(height=round(size+2.0),Color=BackColor)
(ShowFrameNo)
\ ? ScriptClip("""Subtitle(String(current_frame,"%.0f] ")+"""+Chr(34)+Tit+Chr(34)+String(first_frame,",first_frame=%.0f")+
\ String(last_frame,",last_frame=%.0f,font=")+Chr(34)+font+Chr(34)+String(size,",size=%.3f")+String(text_color,",text_color=%.0f")+
\ String(halo_color,",halo_color=%.0f")+String(align,",align=%.0f")+String(spc,",spc=%.0f")+String(font_width,",font_width=%.3f")+
\ String(font_angle,",font_angle=%.3f)"))
\ : Subtitle(Tit,first_frame=first_frame,last_frame=last_frame,font=font,size=size,text_color=text_color,halo_color=halo_color,align=align,
\ spc=spc,font_width=font_width,font_angle=font_angle)
Return StackVertical(c).AudioDubEx(c)
}


Function NonlinUSM(clip o, float "z", float "pow", float "str", float "rad", float "ldmp") {
z = default(z, 6.0) # zero point
pow = default(pow, 1.6) # power
str = default(str, 1.0) # strength
rad = default(rad, 9.0) # radius for "gauss"
ldmp= default(ldmp, 0.001) # damping for verysmall differences

g = o.bicubicresize(round(o.width()/rad/4)*4,round(o.height()/rad/4)*4).bicubicresize(o.width(),o.height(),1,0)

rpn="x x y - abs "+string(z)+" / 1 "+string(pow)+" / ^ "+string(z)+" * "+string(str)+" * x y - 2 ^ x y - 2 ^ "+string(ldmp)+
\ " + / * x y - x y - abs 0.001 + / * +"
mt_lutxy(o,g,rpn,U=2,V=2)

#interleave(o,last) # just for visualisation, you don't want the function to do this

return(last)
}


EDIT: Optional show Stacked Original or Limited (or neither).

raffriff42
8th October 2017, 13:59
Fooling around with random arguments! That's the ticket, when nothing makes any sense!
Hey, remember when we did that with a Bloom filter (https://forum.doom9.org/showthread.php?p=1642591#post1642591)?

StainlessS
8th October 2017, 15:22
Yep, random is my go-to strategy,

while (bump into wall) { spin around to a random direction, forward };

Works every time, hardly ever get stuck in a loop, for long.

Arh, the Bloom Filter, those woz the daze :)

raffriff42
8th October 2017, 16:21
Brilliant strats. EDIT better than mine:while (wall && skull) { bump into wall; }

StainlessS
9th October 2017, 00:01
Just repaired a broken musvid, just for the hell of it put it through NonlinUSM(z=3, pow=1.1, str=0.33, rad=9), and results quite good (lowish qual source),
Verified that pow=1 and z = 3 or z=12 gave identical results.
Raff, multiple examples of usage show pow=1.0, which switches off z effect, so that part of result depends only upon str.

EDIT: Done another short musvid, source 534x360@25, using my pretty much standard encode script (does as below with used settings).
RoboCrop
AutoContrast
MCDegrainSharp(frames=1)
NNedi3_Rpow2(2)
Spline36Resize(720,576)
ReSampleAudio(44100)
Normalize(0.98)
NonlinUSM(z=3, pow=1.1, str=0.33, rad=9) # additional to standard script
Encode(3:2)

Nice improvement, think I'll stick to roughly those NonlinUSM settings, and add to my standard script (default switched OFF).

EDIT: I dont think you will like pow less than 1.0.

fenomeno83
9th October 2017, 17:00
thanks..my approach will be:
NonlinUSM(z=3, pow=1.1, str=0.33, rad=X), where X depends from resolution..
I'll test for example NonlinUSM(z=3, pow=1.1, str=0.33, rad=startingRadius) in 15Mp photos, and check the rad that generates a similar output when I scale for example the same photo to 5Mp
I'll make several scaling (for example 15Mp--> 13,11,9,5,5,3,1 Mp) and assign to each resolution the rad value that generates a photos similar to the 15MP with startiingRadius photo.
So, I can build a function curve that shows relations between resolution and radius

Than I can repeat test using others startingRadius and others photos and understand if previous function curve is applicable

StainlessS
11th October 2017, 03:04
Added a line to previous posted text ie

Having looked at Raffs link, have decided to throw all maths out of the window, and choose my own model of what its doing.
In the downsize, it is getting the average local luminance, where each out pixel is average of rad*rad input.
On upsize, is merely tweening the downsized pixels, where result is approx local luminance average.
EDIT: In the downsize, rad is actually a Diameter, which is converted to a radius via the upsize 2D tweening.



EDIT: Also note, on the downsize uses BiCubicResize with defaults b=1.0/3,c=1.0/3,
and on the upsize, BiCubicResize with b=1.0,c=0.0, ie max blur, min ringing.

g = o.bicubicresize(round(o.width()/rad/4)*4,round(o.height()/rad/4)*4).bicubicresize(o.width(),o.height(),1,0)

minusthebear
3rd May 2022, 03:08
Hey guys, I can't seem to get ContrastMask to work.

This is the error I get:

"There is no function named gaussianblur"

I've installed mvtool2.dll but still no success.