PIL_usm is a module for PIL that provides true Gaussian Blurring and Unsharp Mask Sharpening functions to PIL. See the PIL_usm page for details.
NOTE: as of PIL 1.7, PIL_usm and pyCMS functionality is built into the standard distribution of PIL - these stand-alone modules are no longer required or being updated/maintained!
PIL_usm is licensed under the GNU LGPL (Lesser General Public License), making it freely
available in source form to programmers everywhere. Depending on how you use PIL_usm,
it is possible to use it with both closed-source programs, as well as open-source programs.
Although I highly encourage you to release your works under the LGPL or GPL licenses,
the choice is up to you. In either case, please follow the licensing terms provided and
ensure to give credit where credit is due. If you have need of this library under
different licensing terms, please contact us to discuss that possibility.
Click Here to see samples of PILusm vs. Photoshop USM
PIL_usm License (Lesser General Public License)
Full package (vers. 0.6.0) including source code, Python wrapper module, a pre-compiled binary for Windows (compiled with Python
2.2.1, PIL 1.1.3), and sample images (with Photoshop comparison).
Please let me know if you use PIL_usm, how you like it, any bugs/errors you've found, and what
features or improvements you'd like to see. You can email me at:
Using PIL_usm for Gaussian blurring or USM sharpening is very easy, and works very similarly to how it would in any normal painting program (like Photoshop for example).
Here are some examples:
import PIL_usm # don't use the DLL directly, the Python wrapper makes it easier
im = Image.open("c:\\temp\\test.tif")
# first, a blurring example
im2 = PIL_usm.gblur(im, radius = 6.5)
# use a radius value about the same as what you would in Photoshop.
# next, a sharpening example
im3 = PIL_usm.usm(im, radius = 5.25, percent = 150, threshold = 4)
# once again, use a radius value about what you would in other
# paint programs for a similar look.
Documentation and Theory
Gaussian blurring is actually pretty simple. For each pixel in the image, you look at the surrounding pixels and "average" their values
into the value of the current pixel. You control the amount of blur by specifying the "radius" of how many surrounding pixels are taken
into consideration. Pixels that are closer to the current pixel have more effect than further ones, based on a Gaussian distribution, or
To improve speed, PIL_usm does this in two passes which actually result in the EXACT same output. Instead of doing a single pass with a
large, square (2-dimensional) matrix, it does two 1-dimensional transformations. For example, if using a "radius" of 10, instead of doing
a single pass with a 10x10 matrix (100 lookups per pixel), it does a 10x1 transform (rows) followed by a 1x10 transform (columns). This
results in only 20 lookups per pixel instead of 100... a 500% speed improvement.
Unsharp masking is actually quite simple in practice, but can easily confuse you if you don't know what's happening. There are two steps
to USM application: 1) creating a temporary "blurred" image using a Gaussian Blur (as above), and 2) evaluating how much the image was blurred,
and applying the OPPOSITE correction to the final image.
For USM, the "radius" variable determines the radius to use in the Gaussian Blur function (see above). The "threshold" value determines the
minimum amount a pixel value must change before we apply any sharpening to it (i.e. if it changes less than "threshold" values after the
Gaussian Blur, we leave the pixel alone in the output image). The "percent" value is a multiplier for the correction we apply to any pixels
that DID change more than "threshold" values.
The result, when properly applied, is that only "edge features" are sharpened, by effectivly increasing the contrast only in areas where there
was high-contrast to begin with. This may create a "ring" effect, or white/black outline around edges, but it shouldn't be visible unless either
the radius or percent values were too large.
Typical settings for USM for a starting point are:
Of course, this depends on how much sharpening the image needs, and what the final use of the image will be.
- Radius: (dpi of final image) * (0.025 to 0.1) (or so)
- Percent: 125 - 175
- Threshold: 3-6
- Released Jan 29, 2003
- fixed/improved float radius support (oops!)
- now that radius can be a float (properly), changed radius value to
be an actual radius (instead of diameter). So, you should get
similar results from PIL_usm as from other paint programs when
using the SAME values (no doubling of radius required any more).
Be careful, this may "break" software if you had it set for 2x
or 5x the radius as was recommended with earlier versions.
- made PILusm thread-friendly (release GIL before lengthly operations,
and re-acquire it before returning to Python). This makes a huge
difference with multi-threaded applications on dual-processor
or "Hyperthreading"-enabled systems (Pentium4, Xeon, etc.)
- Released Jan 28, 2003
- Added support for float radius values! You can now fine-tune the output much better than before for both gblur and usm functions.
- Released Jan 27, 2003
- Changed method of calculating gaussian curve (again) to try to keep shape constant for varying radii. It's working fairly well now,
but still might change in the future. Note that you should use a radius value of about 2x what you would in Photoshop now... not 5x. This
is because the gaussian curve shape is more similar to Photoshop's, and is more constant throughout the range. PILusm doesn't
actually use the "radius" value as a radius... it's actually the diameter of the gaussian area, hence the 2x correction factor compared
- Released Jan 27, 2003
- Changed method of calculating gaussian curve to try to keep shape constant for varying radii... still a work in progress
- _gblur (and therefor usm too) adds 1 to the user-supplied radius before using it. This fixes the problem of returning a
black image if the user supplies "0", it now returns the original image.
- fixed handling of alpha channel in RGBX and RGBA images (_gblur function of DLL)
- improved speed of gblur by reducing unnecessary checks and assignments
- Released Jan 26, 2003
- Fixed type L mode image support (gray scale), improved C++ code slightly overall (it's still a bit of a mess though, sorry!)
- Released Jan 26, 2003: initial release.
Please help keep shareware software going... make a small donation for us today!