Welcome to Doom9's Forum, THE inplace 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. 
6th March 2010, 09:01  #1  Link 
Registered User
Join Date: Feb 2004
Posts: 1,350

Soft thresholded median sharpening function
Code:
Function MedSharp(Clip C, int "thresh", int "rad", int "mode", bool "lp", bool "hp", bool "nr", float "str", int "kernel") { _Thr = Default(thresh, 256) _Rad = Default(rad, 1) Mode = Default(mode, 1) str = Default(str, 1.5) THR = string(_Thr) RAD = string(_Rad) RAD2 = string(_Rad) lp = Default(lp, false) hp = Default(hp, false) nr = Default(nr, false) kernel = Default(kernel, 1) Lowpass = C Lowpass = lp == true ? _Rad >= 2 ? Lowpass.NLLV(rad=1).NLLH(rad=1) : Lowpass : Lowpass Lowpass = lp == true ? _Rad >= 4 ? Lowpass.NLLV(rad=2).NLLH(rad=2) : Lowpass : Lowpass Lowpass = lp == true ? _Rad == 6 ? Lowpass.NLLV(rad=3).NLLH(rad=3) : Lowpass : Lowpass Lowpass = lp == true ? _Rad >= 8 ? Lowpass.NLLV(rad=4).NLLH(rad=4) : Lowpass : Lowpass Lowpass = lp == true ? _Rad == 10 ? Lowpass.NLLV(rad=4).NLLH(rad=5) : Lowpass : Lowpass Lowpass = lp == true ? _Rad == 12 ? Lowpass.NLLV(rad=4).NLLH(rad=6) : Lowpass : Lowpass Lowpass = lp == true ? _Rad == 14 ? Lowpass.NLLV(rad=4).NLLH(rad=7) : Lowpass : Lowpass Lowpass = lp == true ? _Rad >= 16 ? Lowpass.NLLV(rad=4).NLLH(rad=8) : Lowpass : Lowpass Lowpass = nr == true ? Lowpass.TMed2(rad=_Rad, thresh=thresh, Kernel=Kernel) : Lowpass Diff = Mode==0 ? MT_Luts(C, Lowpass, mode="med", pixels = "0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1)\ : MT_Luts(C, Lowpass, mode="med", pixels = "0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD+" 0 0" ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1) Diff = Kernel > 1 ? MT_Luts(C, Lowpass, mode="med", pixels = ""+RAD2+" "+RAD2+""+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" 0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1) : Diff Diff = Diff.mt_Lut("X 128  "+string(str)+" * 128 +") Diff2 = Diff.NLLV(rad=_Rad).NLLH(rad=_Rad) Diff = hp == true ? Mt_Makediff(diff, diff2) : Diff #Diff = hp == true ? Diff.lanczosresize(c.width*2, c.height*2, 0.25, 0.25, taps=3).NLHH().NLHV().pointresize(c.width, c.height) : Diff #Diff = hp == true ? Diff.NLHH2().NLHV2() : Diff MT_adddiff(C, Diff, u=2, v=2) Return(Last) } Code:
Function TMed2(Clip C, int "thresh", int "rad", int "mode", int "kernel") { _Thr = Default(thresh, 256) _Rad = Default(rad, 1) Mode = Default(mode, 1) THR = string(_Thr) RAD = string(_Rad) RAD2 = string(_Rad) kernel = Default(kernel, 1) Diff = Mode==0 ? MT_Luts(C, C, mode="med", pixels = "0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1)\ : MT_Luts(C, C, mode="med", pixels = "0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD+" 0 0" ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1) Diff = Kernel > 1 ? MT_Luts(C, C, mode="med", pixels = ""+RAD2+" "+RAD2+""+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" 0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1) : Diff MT_Makediff(C, Diff, u=2, v=2) Return(Last) } Function NLHH2(Clip C) { B1 = C.BlurH(1, 0.833) B2 = C.BlurH(2, 0.750) B3 = C.BlurH(3, 0.944) B4= C.BlurH(4, 0.981) B1_D = Mt_Makediff(c, b1, u=1, v=1) B2_D = Mt_MakeDiff(b2, c, u=1, v=1) B3_D = Mt_MakeDiff(c, b3, u=1, v=1) B4_D = Mt_MakeDiff(b4, c, u=1, v=1) B2_DT = Mt_LutXY(B1_D, B2_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 0.75 * X 128  abs  0 > \ Y 128  abs 0.75 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) B3_DT = Mt_LutXY(B2_DT, B3_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 2.25 * X 128  abs  0 > \ Y 128  abs 2.25 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) B4_DT = Mt_LutXY(B3_DT, B4_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 6.75 * X 128  abs  0 > \ Y 128  abs 6.75 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) Mt_AddDiff(B4_DT, C) Return(last) } Function NLHV2(Clip C) { B1 = C.BlurH(1, 0.833) B2 = C.BlurH(2, 0.750) B3 = C.BlurH(3, 0.944) B4= C.BlurH(4, 0.981) B1_D = Mt_Makediff(c, b1, u=1, v=1) B2_D = Mt_MakeDiff(b2, c, u=1, v=1) B3_D = Mt_MakeDiff(c, b3, u=1, v=1) B4_D = Mt_MakeDiff(b4, c, u=1, v=1) B2_DT = Mt_LutXY(B1_D, B2_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 0.75 * X 128  abs  0 > \ Y 128  abs 0.75 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) B3_DT = Mt_LutXY(B2_DT, B3_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 2.25 * X 128  abs  0 > \ Y 128  abs 2.25 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) B4_DT = Mt_LutXY(B3_DT, B4_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 6.75 * X 128  abs  0 > \ Y 128  abs 6.75 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) Mt_AddDiff(B4_DT, C) Return(last) } Function NLLH(Clip C, int "rad") { Rad = Default(Rad, 1) B1 = C.BlurH(1*rad, 0.439) B2 = C.BlurH(3*rad, 0.833) B3 = C.BlurH(5*rad, 0.934) B4= C.BlurH(7*rad, 0.983) B1_D = Mt_Makediff(B1, C, u=1, v=1) B2_D = Mt_MakeDiff(C, B2, u=1, v=1) B3_D = Mt_MakeDiff(B3, C, u=1, v=1) B4_D = Mt_MakeDiff(C, B4, u=1, v=1) B2_DT = Mt_LutXY(B1_D, B2_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 1.915 * X 128  abs  0 > \ Y 128  abs 1.915 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) B3_DT = Mt_LutXY(B2_DT, B3_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 2.025 * X 128  abs  0 > \ Y 128  abs 2.025 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) B4_DT = Mt_LutXY(B3_DT, B4_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 2.077 * X 128  abs  0 > \ Y 128  abs 2.077 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) Mt_AddDiff(B4_DT, C) Return(last) } Function NLLV(Clip C, int "rad") { Rad = Default(Rad, 1) B1 = C.BlurV(1*rad, 0.439) B2 = C.BlurV(3*rad, 0.833) B3 = C.BlurV(5*rad, 0.934) B4= C.BlurV(7*rad, 0.983) B1_D = Mt_Makediff(B1, C, u=1, v=1) B2_D = Mt_MakeDiff(C, B2, u=1, v=1) B3_D = Mt_MakeDiff(B3, C, u=1, v=1) B4_D = Mt_MakeDiff(C, B4, u=1, v=1) B2_DT = Mt_LutXY(B1_D, B2_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 1.915 * X 128  abs  0 > \ Y 128  abs 1.915 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) B3_DT = Mt_LutXY(B2_DT, B3_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 2.025 * X 128  abs  0 > \ Y 128  abs 2.025 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) B4_DT = Mt_LutXY(B3_DT, B4_D, " X 128  Y 128  X 128  abs Y 128  abs * 1 + * X 128  abs Y 128  abs * Y 128  abs 2.077 * X 128  abs  0 > \ Y 128  abs 2.077 * X 128  abs  0 ? X 128  abs 0 > X 128  abs 1 X 128  abs 0 > X 128  1 ? / ^ 1 ? / 1 * + 1 + / + 128 + ", u=1, v=1) Mt_AddDiff(B4_DT, C) Return(last) } Function blurH(clip c, int "rad", Float "CW") { Rad = Default(rad, 1) CW = Default(CW, 0.5) Center = C Left = C.PointResize(C.width, C.height, rad, 0, C.width, C.height) Right = C.PointResize(C.width, C.height, rad, 0, C.width, C.height) Average(Center, CW/2, Left, (1CW)/2, Right, (1CW)/2, Center, CW/2) Return(last) } Function BlurV(clip c, int "rad", Float "CW") { Rad = Default(rad, 1) CW = Default(CW, 0.5) Center = C Down = C.PointResize(C.width, C.height, 0, rad, C.width, C.height) Up = C.PointResize(C.width, C.height, 0, rad, C.width, C.height) Average(Center, CW/2, Down, (1CW)/2, Up, (1CW)/2, Center, CW/2) Return(last) } [edit] forgive the wideness, will fix later [edit] fixed (mostly, still too wide, but I don't want to split the equations) Last edited by *.mp4 guy; 10th March 2010 at 10:05. 
6th March 2010, 12:54  #2  Link 
Registered User
Join Date: Apr 2002
Location: Germany
Posts: 5,394

Hey, that's a nice idea! Alas, the available means in Avisynth are somewhat restricted, you know.
With "thresholded median", I rather understand that the thresholdig (be it soft or hard) is applied to each single neighborhood pixel while doing the median calculation. What we have here is a plain median, where the median's result is furtheron mixcalculated with the original pixel. That's a nontrivial difference. However, the former way can not be done at all with MaskTools, any access "into" the basic operation is not possible. The latter way, as you are doing, is infact the only way that's open from the script level. (I'm only noting, not complaining!) But I wonder a bit about the median neighborhood. E.g. with rad=2, you're using only the following pixels from a 5x5 neighborhood: x x x x x x x x x x x x x x x x x x x x x x x x x With increasing radii, the results get less and less precise. rad=1 is a bit rough, rad=2 is pretty rough, and with rad=3 (or at latest with 4), the result starts to be purely random (too little pixels, from too far away, to produce a meaningful result). Shouldn't there be mt_square used instead, to take all pixels into account? Of course, things will get pretty slow then, especially with larger radii, but that's how median and mt_luts are. A possible addition: make the treshold adaptive to the actual minmax span of the used neighborhood. Idea?
__________________
 We´re at the beginning of the end of mankind´s childhood  My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!) 
7th March 2010, 20:36  #3  Link  
Registered User
Join Date: Feb 2004
Posts: 1,350

Oddly enough, adding in the corners doesn't really help (at least not at small radii).
Also, the median is calculated after the limiting, iirc. From documentation: Quote:
1 calculate difference between center pixel and median neighborhood pixels 2 softlimit each difference 3 find median of differences 4 add median difference to source Also, if the source is blurry at radii X (and needs to be sharpened) then there is correlation at radii X, even excluding the extra pixels, its a bit nonoptimal, but there are other problems with using median sharpening at high radii that this avoids besides the speed problem. 

8th March 2010, 09:47  #4  Link 
Registered User
Join Date: Apr 2002
Location: Germany
Posts: 5,394

Jeeze .... my last post clearly was a case of "unwrap candy, throw candy into dustbin, put paper into mouth."
Thanks for the reminder on the orderofcalculation in mt_luts. It's a more powerful tool than it looks at first glance. Even more funnily, somehow I had stopped reading after "Soft thresholded median..."  thought it was just a kind of softmedian, but didn't see that it's actually a sharpener. [ouch] I'm still a bit puzzeled about "precision"  if only a few random pixels out of a rather big neighborhood are evaluated, it just doesn't seem right. But hey, apart from all theorizing, the empiric test is a strong argument, too. And after simply giving a try on that function, conclusion is: This baby seems to work pretty good. Period.
__________________
 We´re at the beginning of the end of mankind´s childhood  My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!) 
9th March 2010, 12:04  #5  Link  
Registered User
Join Date: Apr 2002
Location: Germany
Posts: 5,394

To compensate for my silliness above, here are two suggestions. (Hopefully, more constructive this time.)
Firstly, just about boring syntax: Quote:
(Took the freedom to also delete leadingblanks, endblanks, and doubleblanks from the strings.) Code:
_Thr = Default(thresh, 256) _Rad = Default(rad, 1) Mode = Default(mode, 1) THR = string(_Thr) RAD = string(_Rad) Diff = Mode==0 ? MT_Luts(C, C, mode="med", pixels = "0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1)\ : MT_Luts(C, C, mode="med", pixels = "0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD+" 0 0" ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1) Ah, boring, isn't it. More interestingly, a technical change. I found that using only 4 pixels from the neighborhood can indeed cause a drawback: if there is any strictlyhorizontal or strictlyvertical detail, then most of it will not get any sharpening. (On a straight line, 3 of the 5 samples are on the line, so the median won't bite.) Surely that's by intention, but it could be interpreted as a shortcoming. The issue can be pretty much avoided by extending the kernel to 8 neighbors, using 4 additional pixels from the diagonals: (Now the strings get awfully long again....) Code:
_Thr = Default(thresh, 256) _Rad = Default(rad, 1) Mode = Default(mode, 1) THR = string(_Thr) RAD = string(_Rad) RAD2 = string( round(_Rad/1.4142) ) Diff = Mode == 0 ? MT_Luts(C, C, mode="med", pixels = ""+RAD2+" "+RAD2+""+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" 0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1)\ : MT_Luts(C, C, mode="med", pixels = ""+RAD2+" "+RAD2+""+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" 0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD+" 0 0" ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1) MT_adddiff(C, Diff, u=2, v=2)
__________________
 We´re at the beginning of the end of mankind´s childhood  My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!) 

9th March 2010, 13:42  #6  Link 
Registered User
Join Date: Feb 2004
Posts: 1,350

Well, the problem with the diagonals, and with large medians in general, is that all the pixels have the same "weight", when they really shouldn't. Anyway, If you want to force sharpening all the time, that is what mode 0 is for, by excluding the center value, you get sharpening no matter what (though its not exactly a median anymore, it works fine).
Expanding on the pixel positioning problem, the basic situation is that you want all of the pixels in your median calculation to have the same frequency relation to the center pixel, furthermore, you want them to all be of the highest correlation with the center pixel (for any given radius X) the correct way to solve this problem is to use all of the pixels needed to accurately represent a given radius, and then weight them to the correct proportions, but this is slow and causes implementation problems in avisynth. However, I'll see what adding in the diagonals looks like, also, new version in first post, with some experimental features (I know things are really unoptimized, that will be addressed when I know what works and what doesn't) 
9th March 2010, 14:04  #7  Link  
Registered User
Join Date: Apr 2002
Location: Germany
Posts: 5,394

Quote:
If the "pixel situation" is like this ... Code:
o o o o o o o o o o o o o o x x x x x x x o o o o o o o o o o o o o o Quote:
Quote:
__________________
 We´re at the beginning of the end of mankind´s childhood  My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!) Last edited by Didée; 9th March 2010 at 14:06. 

9th March 2010, 14:17  #8  Link 
Registered User
Join Date: Feb 2004
Posts: 1,350

What happens with 4 values is that the median two values are found and then averaged, which still works pretty well, though by all rights it shouldn't.
As to the differences when using the corners, well, it definitely is stronger, but in the one test I did, I couldn't call it better. it amplified the median artifacts, and skewed the sharpening to a lower frequency level, which reduced overall high frequency sharpening, which is the opposite of what I want. [edit] Did another test, it looked alright this time, it might be faster for really strong sharpening, don't think it will look better though. [edit2] The larger kernel is stronger and more regular, while the smaller kernel can get more "sharpness" into the high frequencies, so there is a trade off of sorts. I might have to cobble together a weighted median filter now, since larger kernels do have some clear advantages, meh. Last edited by *.mp4 guy; 9th March 2010 at 16:43. 
11th August 2010, 07:02  #10  Link 
Registered User
Join Date: Feb 2004
Posts: 1,350

Hopefully this doesn't count as necro posting, but I had forgotten about this thread. When I was working on doing things correctly, I did a test run which took an incredible amount of time to accomplish essentially nothing. Then a bit later I had an idea on how to cheat to get something similar with a still large, but now manageable speed hit, its definitely not "correct" but it works.
Code:
Function MedSharp2(Clip C, int "thresh", int "rad", int "mode", bool "lp", bool "hp", bool "nr", float "str", int "kernel") { _Thr = Default(thresh, 256) _Rad = Default(rad, 1) Mode = Default(mode, 1) str = Default(str, 1) THR = string(_Thr) RAD = string(_Rad) RAD2 = string(_Rad) lp = Default(lp, false) hp = Default(hp, false) nr = Default(nr, false) kernel = Default(kernel, 2) inputclipproperties = c blank = BlankClip(length=inputclipproperties.framecount, width=inputclipproperties.width,\ height=inputclipproperties.height, pixel_type="rgb32", fps=inputclipproperties.framerate,\ fps_denominator=1, audio_rate=inputclipproperties.Audiorate, stereo=true, sixteen_bit=true,\ color=$828282).converttoyv12() Lowpass1 = C.NLLV(rad=1).NLLH(rad=1) Lowpass_Return = lp == true ? _Rad >= 2 ? Lowpass1 : C : C Lowpass_NR_1 = Lowpass_Return.TMed2(rad=_Rad, thresh=_Thr, Kernel=1) Lowpass_NR_2 = Lowpass_Return.TMed2(rad=_Rad, thresh=_Thr/4, Kernel=2) Diff1 = MT_Luts(C, Lowpass_NR_1, mode="med", pixels = "0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD+" 0 0" ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 1 >= "+THR+" 0.5 ^ "+THR+" ? + /  128 +", u=1,v=1) Diff2 = MT_Luts(C, Lowpass_NR_2, mode="med", pixels = ""+RAD2+" "+RAD2+""+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" "+RAD2+" 0 "+RAD+" "+RAD+" 0 "+RAD+" 0 0 "+RAD ,\ expr = "X Y  X Y  X Y  abs 1 + * X Y  abs 1 + "+THR+" 2 * 1 >= "+THR+" 2 * 0.5 ^ "+THR+" 2 * ? + /  128 +", u=1,v=1) mask1 = Mt_Lut(Diff1, " X 128  255 * ", u=1, v=1)#.NLLV().NLLH() #mask2 = Mt_Lut(Diff2, " X 128  255 * ", u=1, v=1)#.NLLV().NLLH() s1 = mt_merge(Diff2, blank, mask1).mt_Lut("X 128  "+string(str)+" 2 / * 128 +") s1b = s1.NLLV().NLLH() s1s = mt_makediff(s1, s1b) s2 = Diff1.mt_Lut("X 128  "+string(str)+" * 128 +") s2b = s1.NLLV().NLLH() s2s = mt_makediff(s2, s2b) out = MT_adddiff(C, s1s, u=2, v=2) out = MT_adddiff(out, s2s, u=2, v=2) out Return(Last) } The last version I posted also had the following features, but I don't think I explained them. A lowpass is applied to the neighbor pixels when using radius 2 because it reduces noise amplification, while otherwise performing about the same. I didn't code for radii larger then 2, because they never looked acceptable to me, the medians start to do weird things and distort the image. Also, neighborhood pixels are themselves put through a median smoothing operation before being used for sharpening, it reduces noise and does not significantly effect sharpening strength. There is additionally some fiddling with the frequency components of the sharpening before applying them to the picture. [edit] also it is too wide again, and some of the arguments don't do anything anymore. Last edited by *.mp4 guy; 12th August 2010 at 03:18. 
Thread Tools  Search this Thread 
Display Modes  

