The Math Behind Photoshop's Unsharp Mask and Gaussian Blur
 fmw42
 Posts: 26383
 Joined: 20070702T17:14:5107:00
 Authentication code: 1152
 Location: Sunnyvale, California, USA
Re: The Math Behind Photoshop's Unsharp Mask and Gaussian Blur
Yes, I have the order correct for subtraction. If you do multiple composites, each gets its own clamping. That is why I though of doing the 3 adds in one operation and not two. My guess is that there is different clamping in IM as separate operations than is what is done in the unsharp command. Or perhaps PS only clamps one side, say negatives, but does not clamp for values over 255? I really do not know.

 Posts: 13034
 Joined: 20100123T23:01:3307:00
 Authentication code: 1151
 Location: England, UK
Re: The Math Behind Photoshop's Unsharp Mask and Gaussian Blur
If we want the longwinded form of "unsharp", then:
The difference is:
The second convert needs HDRI.
Note that everything is clamped except the minus operation.
Code: Select all
set SRC=lena3.png
%IM%convert %SRC% unsharp 0x3+1+0 u0.png
rem out = O + (OGB)
%IMDEV%convert ^
define compose:clamp=off ^
%SRC% ^
( clone 0 gaussianblur 0x3 clamp ) ^
( clone 01 compose MinusSrc composite ) ^
delete 1 ^
compose Plus composite ^
clamp ^
u1.png
%IM%compare metric RMSE u0.png u1.png NULL:
Code: Select all
37.9088 (0.000578452)
Note that everything is clamped except the minus operation.
snibgo's IM pages: im.snibgo.com

 Posts: 13034
 Joined: 20100123T23:01:3307:00
 Authentication code: 1151
 Location: England, UK
Re: The Math Behind Photoshop's Unsharp Mask and Gaussian Blur
We can avoid the need for HDRI by using "compose Mathematics":
Code: Select all
%IM%convert ^
%SRC% ^
( clone 0 gaussianblur 0x3 ) ^
compose Mathematics define compose:args=0,1,2,0 composite ^
+depth ^
u2.tiff
snibgo's IM pages: im.snibgo.com
 fmw42
 Posts: 26383
 Joined: 20070702T17:14:5107:00
 Authentication code: 1152
 Location: Sunnyvale, California, USA
Re: The Math Behind Photoshop's Unsharp Mask and Gaussian Blur
Snibgo, in your compose mathematics, you are processing O + (O  GB) as 2*OGB with no clamping. Strange that works. But the claim was that PS is using O+(OGB)inv(O+inv(GB)). My guess is that the third term is getting parts missed by clamping OGB. Nevertheless, when I computed O+(OGB) in my script above using clamp=off in HDRI, it did not work. You seems to imply that it is the gaussian blur that needs clamping. But a gaussian has no negative values and should not exceed values in the original, unless the computation has not properly normalized it.

 Posts: 13034
 Joined: 20100123T23:01:3307:00
 Authentication code: 1151
 Location: England, UK
Re: The Math Behind Photoshop's Unsharp Mask and Gaussian Blur
I think clamping after the blur makes no difference. The important part is that (OGB) may be negative, so that mustn't be clamped. "compose Mathematics" works pixelbypixel, with each calculation in floating point, though each result here is then written to Q16 integer.
The formula USM='O+(OGB)inv(O+inv(GB))' seems to have come from Gimp, which I think records pixel values as 0..255 only. So, when O<GB, (OGB) is clamped to zero. To compensate, we need to subtract something, and that's what "inv(O+inv(GB))" is for.
For example, suppose O=33 and GB=44.
USM = 33 + (3344)  inv(33+inv(44))
Negative values are clamped to zero, and inv(X) = 255X, so
USM = 33 + (0)  (255 (33+(25544)))
= 33  (255  (33 + (211)))
= 33  (255  244)
= 33  11
= 22.
We get the same result from USM = 2*OGB = 2*3344 = 6644 = 22.
Internally, the IM USM takes a longer route because it uses (OGB) for the threshold:
USM = O + (OGB) = 33 + (3344) = 33 + (11) = 22.
Internally, (OGB) is stored as a floating point.
Yes.fmw42 wrote:My guess is that the third term is getting parts missed by clamping OGB.
The formula USM='O+(OGB)inv(O+inv(GB))' seems to have come from Gimp, which I think records pixel values as 0..255 only. So, when O<GB, (OGB) is clamped to zero. To compensate, we need to subtract something, and that's what "inv(O+inv(GB))" is for.
For example, suppose O=33 and GB=44.
USM = 33 + (3344)  inv(33+inv(44))
Negative values are clamped to zero, and inv(X) = 255X, so
USM = 33 + (0)  (255 (33+(25544)))
= 33  (255  (33 + (211)))
= 33  (255  244)
= 33  11
= 22.
We get the same result from USM = 2*OGB = 2*3344 = 6644 = 22.
Internally, the IM USM takes a longer route because it uses (OGB) for the threshold:
USM = O + (OGB) = 33 + (3344) = 33 + (11) = 22.
Internally, (OGB) is stored as a floating point.
I'm unsure which of your scripts you mean. When you use "evaluatesequence add" to add O and GB and the third term, all three terms are always positive, so you need to subtract the third term.fmw42 wrote:Nevertheless, when I computed O+(OGB) in my script above using clamp=off in HDRI, it did not work.
snibgo's IM pages: im.snibgo.com
 fmw42
 Posts: 26383
 Joined: 20070702T17:14:5107:00
 Authentication code: 1152
 Location: Sunnyvale, California, USA
Re: The Math Behind Photoshop's Unsharp Mask and Gaussian Blur
I had one computation earlier on where I added define clamp=off but had added the third term. But I now see that I had added a small threshold term. So the comparison with unsharp is not appropriate for both reasons.I'm unsure which of your scripts you mean. When you use "evaluatesequence add" to add O and GB and the third term, all three terms are always positive, so you need to subtract the third term.
I also computed O + (OGB), but in that computation I had clamping on. So my comparison for that would not be appropriate either.
Thanks for doing the comparison properly.