Log in

View Full Version : DetailSharpen -> Sharpening, now with less edges!


Bloax
23rd December 2011, 20:09
A quick (and perhaps pretty fast) filter that I cooked up some time ago.

Now I decided to make a function out of it, and voila.

Example:

Before (http://img189.imageshack.us/img189/8098/without0.png)/After (http://img823.imageshack.us/img823/2112/with0.png) (Str=6)

function DetailSharpen(clip orig,int "str",int "thr") {

# Another filter by, oh you guessed it, Bloax.
# Requirements: RedAverage, RemoveGrain and ASharp.

# A sharpening filter, that unlike usually, doesn't sharpen edges.
# Instead it sharpens the details, and thus it avoids the classic haloing.
# Not my idea of course, but anyways, enjoy.

# "str" Is the sharpening strength.
# "thr" Is the threshold for detecting edges. The higher, the more "edges" are caught, and less details are sharpened.
# 5 Is the best value, because 4 starts sharpening edges, and 6 sharpens way too little.

str = Default(str, 5)
thr = Default(thr, 5)
Threshold = Pow(2,thr)

clp = orig.IsYV12() ? orig.ConvertToYV12() : orig

msk=RAverageW(clp,Threshold,clp.RemoveGrain(19,-1),Threshold*-1,u=0,v=0,sse=8,bias=128).RemoveGrain(2,-1).Mt_Inpand(mode="both").Mt_Deflate()
RMerge(clp,clp.ASharp(str,-1),msk)
}

Didée
23rd December 2011, 20:42
With all due respect for your enthusiasm for RedAverage.

But if you would use mt_edge for edge masking, you'd have better chances of your masking actually making sense.

Bloax
24th December 2011, 10:26
Well, maybe it's all because of my limited stuff to test it on.
But I can't find a case where Mt_Edge detects more edges that this, unless it's prewitt, which is way overkill.

Not that they're useless, it's just that I'd like to have as many edges as possible, with the least non-edge coverage.
Laplace is useless, Sobel is really thick and Roberts detects too many details before it's in the same league.

But yeah, it's pretty much nonsense, but it works. I should probably add a bias control too.

Didée
24th December 2011, 14:40
Maybe I've a different view or something, dunno ...

You want to sharpen much where edges are little, and sharpen little where edges are much?

Here's a frame:
http://thumbnails58.imagebam.com/16615/334d11166143593.jpg (http://www.imagebam.com/image/334d11166143593)

Here's the mask from your script:
http://thumbnails25.imagebam.com/16615/d35bb0166143603.jpg (http://www.imagebam.com/image/d35bb0166143603)

Black= do nothing, white= do sharpen, gray= sharpen somewhat.
The edges are excluded. But there are vast areas of non-edges that are black too, and don't get any sharpening though they should. And there's almost no "white", the majority is a 50% mask.
There are some white spots getting full sharpening, but those spots are, well, random.


Prewitt edge mask:
http://thumbnails55.imagebam.com/16615/605e1b166143611.jpg (http://www.imagebam.com/image/605e1b166143611)

This is an edge mask that maskes edges.


Wanna some sharpening that causes no haloing, without any edge masking?

mt_lutxy(o,o.removegrain(20),"x x y - abs 4 / 1 4 / ^ 4 * 1.51 * x y - x y - abs 1.001 + / * +",U=2,V=2) # 1.51 = "strength" multi


Merry Christmas.

Bloax
24th December 2011, 15:26
That's certainly a nice lutxy function, too bad I have no idea what's the actual math. ("abs 4 / 1 4 / ^ 4 * str" is machine code to me.)
But anyways, I added a RemoveGrain(2,-1) to the mask, just to reduce the amount of random black dots. (Those are nasty.)

Sapo84
24th December 2011, 16:18
That's certainly a nice lutxy function, too bad I have no idea what's the actual math. ("abs 4 / 1 4 / ^ 4 * str" is machine code to me.)
If I'm not completely inept at reading reverse polish notation, it should be "x + (((abs(x-y) / 4)^0.25) * 4 * 1.51) * ( (x - y) / (abs (x - y) + 1.001))"

Bloax
24th December 2011, 17:00
Is this where I ask what use reverse polish notation would have?
I guess it is.

Didée
24th December 2011, 17:19
Reverse polish notation is a form of notation that's easier to be machine-evaluated. Look at what Sapo84 posted above: can you immediately see the structure, which open/close brackets actually belong together, etc? Yeah, it's not that easy to read either....

The math behind is exactly the same, no matter if rev.polish or regular expression. If you speak math, you can use either form of expression. If you don't speak math, then regular expression is the same chinese as rev.polish. ;)


The above expression is a "gamma-style reduction term", a simplified version of what is used in SeeSaw (http://forum.doom9.org/showthread.php?t=104701). The idea simply is to amplify small differences stronger, amplify big differences not so strong. (Oversharpening usually occurs in areas where the blur operator causes rather "big" changes, which is always in the spots where local contrast is big to start with.)

http://thumbnails55.imagebam.com/16617/9ed04d166162780.jpg (http://www.imagebam.com/image/9ed04d166162780)

red: "linear sharpening"
blue: "nonlinear sharpening" - small differences amplified more, big differences amplified less.

Gavino
24th December 2011, 17:58
red: "linear sharpening"
blue: "nonlinear sharpening" - small differences amplified more, big differences amplified less.
What is the difference between the two blue curves? (They seem to have a different shape at the origin.)

What is the purpose of the 1.001 - why not 1.0?

LaTo
24th December 2011, 19:26
Some graphs of non linear sharpening here (used in LSFmod) (http://forum.doom9.org/showthread.php?p=1212516#post1212516).
And you can use "edgemode=2" in LSFmod to sharpen only details and not edges.

PS: Merry Christmas everyone ;)

gyth
24th December 2011, 20:05
If I'm not completely inept at reading reverse polish notation, it should be "x + (((abs(x-y) / 4)^0.25) * 4 * 1.51) * ( (x - y) / (abs (x - y) + 1.001))"
I guess it depends what you are used to.
I can see that this is equivalent to "x + (((abs(x-y) * 64)^0.25) * 1.51) * ( (x - y) / (abs (x - y) + 1.001))" using infix, but I can barely use r.polish when there is a stack of numbers, algebraic simplification would fry my brain.
Luckily there is an infix->r.polish function in the masktools library.

Didée
24th December 2011, 22:39
What is the difference between the two blue curves? (They seem to have a different shape at the origin.)
That's the effect of the "lodamp" term. (The graph shows the quadratic-falloff term used in SeeSaw, the shorter lut posted in this thread uses only linear [1.001].) The purpose is to reduce the overdrive for *very* small blurdifferences. In areas of weaker textures, one might want to have the equivalent of 200%, 300% sharpening strength, but very small diff's like 1 or 2 shouldn't be boosted that much.

What is the purpose of the 1.001 - why not 1.0?
An artifact. The value might be 0.001, or 1.51, or 0.12345.
When set at 1.001, the next time I want to use 0.001, I need to edit only one char instead of the whole number. :p

Jenyok
3rd October 2012, 11:29
Bloax
.
Do you have any new version of function ?

Bloax
3rd October 2012, 12:22
Why would you need that? ;o

Jenyok
3rd October 2012, 16:46
Didee
Bloax
.

mt_lutxy(o,o.removegrain(20),"x x y - abs 4 / 1 4 / ^ 4 * 1.51 * x y - x y - abs 1.001 + / * +",U=2,V=2) # 1.51 = "strength" multi

.
Where could I put this string, see upper, to function DetailSharpen(...) ?
.
Bloax
.
Questions to you.
What is Min, Max value of "Str" parameter in function DetailSharpen(...) ?
What is Min, Max value of "Thr" parameter in function DetailSharpen(...) ?

Bloax
3rd October 2012, 19:06
The first is a separate function, as for the second question - Str goes 0 for disabled and is only practical up to about 6, or until you start to see some nasty haloed banding. (And you will.)

Thr is probably around 4-6 it seems, less if you can take the extra haloing, more is kind of pointless.

Jenyok
5th October 2012, 05:11
Bloax
.
I need that more small details in video would be sharpened.
Is parameter "THR = 2" ok for this reason in function DetailSharpen(...) ?

Jenyok
5th October 2012, 05:16
Some changes for function SharpenDetail(clip orig, int "str", int "thr") .
.

#
# http://forum.doom9.org/showthread.php?t=163598
#
# Function name DetailSharpen() is replaced by SharpenDetail() name function ...
#
function SharpenDetail(clip orig, int "str", int "thr")
{
#
# Another filter by, oh you guessed it, Bloax.
# Requirements: RedAverage, RemoveGrain and ASharp.
#
# A sharpening filter, that unlike usually, doesn't sharpen edges.
# Instead it sharpens the details, and thus it avoids the classic haloing.
# Not my idea of course, but anyways, enjoy.
#
# "str" Is the sharpening strength.
# "thr" Is the threshold for detecting edges. The higher, the more "edges" are caught, and less details are sharpened.
# Value 5 Is the best value, because 4 starts sharpening edges, and 6 sharpens way too little.
#

str = Default(str, 5)
thr = Default(thr, 5)
Threshold = Pow(2, thr)
sse0 = 0 # change this constant for limits the processor capabilities.
# -1 = use all (bitwise... 16, 8, 4 = SSE4.1, SSSE3, SSE2),
# 0 = no asm, which is veeeeryyyy sloooow.

clp = orig.IsYV12() ? orig.ConvertToYV12() : orig
msk = RAverageW(clp, Threshold, clp.RemoveGrain(19, -1), (-1) * Threshold, u=0, v=0, sse=sse0, bias=128). \
RemoveGrain(2, -1).Mt_Inpand(mode="both").Mt_Deflate()

return (RMerge(clp, clp.ASharp(str, -1), msk, sse=sse0))

#
# for debugging only
#
# return (msk)
# return (clp)
}