You are on page 1of 2

26

down vote
accepted

I wasn't sure how it worked either but came across a couple of really good pages
for understanding it. Basically it goes like this:

What's the opposite of a sharpened image? A blurry one. We know how to blur an
image. Duplicate the original image and perform some Gaussian blurring. This is the
Radius slider on most USM dialogs.
Well, if we subtract away the blurriness, we should be left with the parts that
are high-contrast! Think about it: if you blur a sky, it still looks like a sky.
Subtract the pixels and you get sky - sky = 0. If you blur a Coke logo, you get a
blurry Coke logo. Subtract it and you're left with the edges. So do the difference
Well what makes things look sharper? Contrast. Duplicate the original image
again and increase the contrast. The amount by which you increase the contrast is
the Amount or Intensity slider on most USM dialogs.

Finally put it all together. You have three things at this point:
A high contrast version of your original image
The difference of the blurred image and your original (this layer is mostly
black). This layer is the unsharp mask
The original

The algorithm goes like this: Look at a pixel from the unsharp mask and find
out its luminosity (brightness). If the luminosity is 100%, use the value from the
high-contrast image for this pixel. If it is 0%, use the value from the original
image for this pixel. If it's somewhere in-between, mix the two pixels' values
using some weighting. Optionally, only change the value of the pixel if it changes
by more than a certain amount (this is the Threshold slider on most USM dialogs).

Put it all together and you've got your image!

Here's some pseudocode:

color[][] usm(color[][] original, int radius, int amountPercent, int threshold) {


// copy original for our return value
color[][] retval = copy(original);

// create the blurred copy


color[][] blurred = gaussianBlur(original, radius);

// subtract blurred from original, pixel-by-pixel to make unsharp mask


color[][] unsharpMask = difference(original, blurred);

color[][] highContrast = increaseContrast(original, amountPercent);

// assuming row-major ordering


for(int row = 0; row < original.length; row++) {
for(int col = 0; col < original[row].length; col++) {
color origColor = original[row][col];
color contrastColor = highContrast[row][col];

color difference = contrastColor - origColor;


float percent = luminanceAsPercent(unsharpMask[row][col]);

color delta = difference * percent;


if(abs(delta) > threshold)
retval[row][col] += delta;
}
}

return retval;
}

Note: I'm no graphics expert, but this is what I was able to learn from the pages I
found. Read them yourself and make sure you agree with my findings, but
implementing the above should be simple enough, so give it a shot!

You might also like