Red Skies at Night

April 6, 2005

Sharpening using Image Magick

Filed under: articles, linux, tools, workflow — Eric Jeschke @ 10:00 am

Summary: an explanation of Image Magick’s unsharp masking parameters, and how the filter compares to the unsharp mask filters in Photoshop and the GIMP.

Introduction

Image Magick is a set of software tools for processing digital images. The package is open-source, freely-available and may be freely distributed. It is a particularly powerful and flexible package for building custom image processing scripts because the command-line tools can be called from a script, or as library routines from special scripting versions of Perl, Python, and other high level programming languages. Many people, myself included, have scratched our collective heads trying to figure out Image Magick’s unsharp mask operator. The command has extremely sparsely documented parameters and (possibly) poor choices for default values, leading to a lot of frustration and confusion on the part of users of the package. This page is an attempt to shed some light on the parameters and operation of Image Magick’s unsharp mask and to compare it to a couple of other well-used unsharp mask filters in Photoshop and The GIMP.

If you need an introduction to the general concept of unsharp masking, you should look elsewhere for additional tutorials on the subject; I only briefly review the concepts in here. This tutorial is mostly for those who already understand the basics of unsharp masking and want to understand how to manipulate and interpret the parameters of the operator in Image Magick. I.M. does a very nice job with unsharp masking once you understand the parameters and how to use them effectively.

Invoking the unsharp mask

Most users will use the unsharp mask filter in the convert command. The option to invoke an unsharp mask looks like this

-unsharp <radius>{x<sigma>}{+<amount>}{+<threshold>}

That is, a radius is expected (or a leading “x” if omitted), followed by optional parameters sigma, amount and threshold. [Note that there is also a -sharpen option to convert. This is not an alias for -unsharp, and (I'm pretty sure) employs a different sharpening routine internally.]

A typical call to convert might look something like the following:

$ convert ... -unsharp 1.5x1.2+1.0+0.10 <input file> <output file>

The “-unsharp” option should usually come last (after other options), since in Image Magick operations are carried out in the order that they appear on the command line, and sharpening is usually the last step that you want to take before image output. Missing parameters to the unsharp mask will take on default values, which may not be the ones you want. I strongly recommend that you always specify all four parameters to prevent ambiguity.

Notes on parameters and operation

The radius parameter

The radius parameter specifies (official documentation)

“the radius of the Gaussian, in pixels, not counting the center pixel”

Unsharp masking, like many other image-processing filters, is a convolution kernel operation. The filter processes the image pixel by pixel. For each pixel it examines a block of pixels surrounding it (the kernel) and does some calculations on them to render the output pixel value. The radius parameter determines which pixels surrounding the center pixel will be considered in the convolution kernel: (think of a circle) the larger the radius, the more pixels that will need to be processed for each individual pixel.

Image Magick’s radius is similar to the same parameter in Photoshop, GIMP and other image editors. In practical terms, it affects the size of the “halos” created to increase contrast along the edges in the image, increasing acutance and thus apparent sharpness.

How do you know how big of a radius to use? It depends on your output target resolution, for one thing. It also depends on your personal preferences, as well as the specific needs of the image at hand. As far as the resolution issue goes, the GIMP User Manual recommends that unsharp mask radius be set as follows:

    radius = (output ppi / 30) * 0.2

Which is very similar to another commonly found rule of thumb:

    radius = output ppi / 150

So for a monitor with 72 PPI resolution, you’d use a radius of approximately 0.5; if your targeting a printer at 300 PPI you’d use a value of 2.0. Use these as a starting point; different images have different sharpening requirements, and individual preference is also a consideration. [Aside: there are a few postings around the net (including some referenced in this article) that suggest that Image Magick accepts, but does not honor, fractional radii; that is, if you specify a radius of 0.5 or 1.2 it is rounded, or defaults to an integer, or is silently ignored, etc. This is not true, at least as of version 5.4.7, which is the one that I am using as I write this article. You can easily see for yourself by doing something like the following:

$ convert -unsharp 1.2x1.2+5+0 test.tif testo1.tif
$ convert -unsharp 1.4x1.4+5+0 test.tif testo2.tif
$ composite -compose difference test01.tif testo2.tif diff.tif
$ display diff.tif

you can also load them into the GIMP or Photoshop into different layers and change the blend mode to "Difference"; the resulting image is not black (you may need to look closely for a 0.2 difference in radius). No, this mistaken impression likely comes from the fact that there is a relationship between the radius and sigma parameters, and if you do not specify sigma properly in relation to the radius, the radius may indeed be changed, or at least not work as expected. Read on for more on this.]

Please note that the default radius (if you do not specify anything) is 0, a special value which tells the unsharp mask algorithm to “select an appropriate value for the radius”!.

The sigma parameter

The sigma parameter specifies (official documentation)

“the standard deviation of the Gaussian, in pixels”

This is the most confusing parameter of the four, probably because it is “invisible” in other implementations of unsharp masking, and it is most sparsely documented. The best explanation I have found for it came from a google search that unearthed an archived mailing list thread which had the following snippet:

>Comparing the results of
>
>    convert -unsharp 1.2x1+4+0 test test1.2x1+4+0
>
>and
>
>    convert -unsharp 30x1+4+0 test test30x1+4+0
>
>results in no significant differences but the latter takes approx. 50 times
>longer to complete.

That is not surprising.  A radius of 30 involves on the order of 61x61
input pixels in the convolution of each output pixel.  A radius of 1.2
involves 3x3 or 5x5 pixels.

>Please can anybody give me any hints, what 'sigma' means?

It describes the relative weight of pixels as a function of their distance
from the center of the convolution kernel.  For small sigma, the outer
pixels have little weight.

Another important clue comes from the documentation for the -unsharp option to convert (emphasis mine):

The -unsharp option sharpens an image. We convolve the image with a Gaussian operator of the given radius and standard deviation (sigma). For reasonable results, radius should be larger than sigma. Use a radius of 0 to have the method select a suitable radius.

Combining the two clues provides some good insight: sigma is a parameter that gives you some control over how the strength (given by the amount parameter) of the sharpening is “graduated” or lessened as you radiate away from a given pixel at the center of the convolution matrix to the limit defined by the radius. My testing confirms this inferred conclusion, namely that a bigger sigma causes more pronounced sharpening for a given radius. That is why the poster in the mailing list question (above) did not see any significant difference in the sharpening even though he was using an amount of 400% (!!) and a threshold of 0%; with a sigma of only 1.0, the strength of the filter falls off too rapidly to be noticed despite the large difference in radius between the two invocations. This is also why the man page says “for reasonable results, radius should be larger than sigma”; if it is not, then the sigma parameter does not have a graduated effect, as designed, to “soften” the halos toward their edges; instead it simply applies the amount evenly to the edge of the radius (which may be what you want in some circumstances). A general rule of thumb for choosing sigma might be:

if radius < 1, then sigma = radius
else sigma = sqrt(radius)

Summary: choose your radius first, then choose a sigma smaller than or equal to that. Experimentation will yield the best results. Please note that the default sigma (if you do not specify anything) is 1.0. This is the main culprit for why most people don’t see as much effect with Image Magick’s unsharp mask operator as they do with other implementations of unsharp mask if they are using a larger radius: unless you bump up this parameter you are not getting the full benefit of the larger radius!

[Aside: you might be wondering what happens if sigma is specifed larger than the radius. The answer, as the documentation states, is that the result may not be "reasonable". In my testing, the usual result is that the sharpening is extended at the specified amount to the edge of the specified radius, and larger values of sigma have little if any effect. In some cases (e.g. for radius < 0) specifying a larger sigma increased the effective radius (e.g. to 1); this may be the result of a "sanity check" on the parameters in the code. In any case, keep in mind that the algorithm is designed for sigma to be less than or equal to the radius, and results may be unexpected if used otherwise.]

The amount parameter

The amount parameter specifies (official documentation)

“the percentage of the difference between the original and the blur image that is added back into the original”

The amount parameter can be thought of as the “strength” of the sharpening: higher values increase contrast in the halos more than lower ones. Very large values may cause highlights on halos to blow out or shadows on them to block up. If this happens, consider using a lower amount with a higher radius instead.

amount should be specified as a decimal value indicating the percentage. So, for example, if in Photoshop you would use an amount of 170 (170%), in Image Magick you would use 1.7.

Please note that the default amount (if you do not specify anything) is 1.0 (i.e. 100%).

The threshold parameter

The threshold parameter specifies (official documentation)

“as a fraction of MaxRGB, needed to apply the difference amount”

The threshold specifies a minimum amount of difference between the center pixel vs. sourrounding pixels in the convolution kernel necessary to apply the local contrast enhancement. Increasing this value causes the algorithm to become less sensitive to differences that may define edges. Specifying a positive threshold is often used to avoid sharpening smooth areas that may contain noise (e.g. an area of blue sky). If you have a noisy image, strongly consider raising the threshold, or using some kind of smart sharpening technique instead.

The threshold parameter should be specified as a decimal value indicating this percentage. This is different than GIMP or Photoshop, which both specify the threshold in actual pixel levels between 0 and the maximum (for 8-bit images, 255).

Please note that the default threshold (if you do not specify anything) is 0.05 (i.e. 5%; this corresponds to a threshold of .05 * 255 = 12-13 in Photoshop). Photoshop uses a default threshold of 0 (i.e. no threshold) and the unsharp masking is applied evenly throughout the image. If that is what you want you will need to specify a 0.0 value for Image Magick’s threshold. This is undoubtedly another source of confusion regarding Image Magick’s sharpening algorithm.

Summary of differences in various unsharp mask filters

Program Radius Sigma Amount Threshold Notes

Examples

Program Radius Sigma Amount Threshold Notes

References

12 Comments »

  1. Thanks a lot for providing this information. Until now I had been using Imagemagick with completely wrong parameters. Because I didn’t know what they actually meant (you’re right, the documentation on this is not clear), and with the evidently wrong parameters I got something of usable results. Until I upgraded to a newer version of IM, and suddenly the pictures remained muddy and fuzzy. When changing some of the (still evidently) wrong parameters, I was able again to get usuable results, but small deviations would either do nothing or ruin the picture. Thanks to your explanation I now have a good starting point again and I am able to enhance the pictures in a controlled way applying as much or as little sharpening as required.
    jlinkels

    Comment by jlinkels — December 16, 2007 @ 5:42 am

  2. quit good information. I can not distinguish the parameters of USM between ImageMagick and Photoshop untill read this article.

    Comment by Jun — January 19, 2008 @ 7:29 am

  3. thanks a lot! That was just what I was looking for.

    Comment by Johannes Hofmann — February 26, 2008 @ 12:37 pm

  4. I will be using imagemagick and this article is really useful.

    Comment by P. Borges — March 14, 2008 @ 12:42 am

  5. Hello! an THANK YOU REALLY MUCH! :-D

    I had such hard time triying to understand this, and so good article are You made.

    I found it looking for info about using Digikam and Kipi batch plugin filter settings and found this, so I almost sure that there are the same settings for the unsharp mask option of such plugin because I believe that is also based on ImageMagick code.

    I wonder now if the simple sharp plugin that have ONLY TWO options that are radius and deviation use the same definition for their options ( I suppose this because some info in this link: http://urchin.earth.li/~twic/The_ImageMagick_Sharpen_Operation.html
    I hope that thsi could not bother too much but I would like to copy the info since may save this because in the web sometimes the info is lost.

    PLEASE, PLEASE excuse me if the the following bother and in this case please edit my messagu so it could be accepted for your page.

    Thanks again and best regards from Costa Rica!

    Comment by Javier Segura — March 23, 2008 @ 3:18 pm

  6. I came across this article while trying to figure out how to automate my (8-bit) by-hand Gimp workflow uisng (16-bit) ImageMagick. After a lot of tests, it seems to me that your analysis is a good explanation of the ideas behind the ImageMagick unsharp operator, but some of your comparisons with Gimp and Photoshop are misleading.

    In particular, the radius in ImageMagick does not behave like the radius in Gimp or Photoshop. In ImageMagick, radius simply seems to provide an outer bound for the operator’s calculations, whereas in Gimp or Photoshop it determines the visual effect of the filter.

    In ImageMagick, as long as the radius is sufficiently large (larger than sigma), there is no visible difference in output for different radius values. Compare “convert -unsharp 2×1.5+1.5+0.0″ with “convert -unsharp 200×1.5+1.5+0.0″. Now go to Gimp and compare radius=2;amount=1.5;threshold=0 with radius=200;amount=1.5;threshold=0. Very different results.

    A empirical comparison of the behaviors of ImageMagick and Gimp shows that ImageMagick’s sigma is the real equivalent to Gimp’s radius. The actual relationship is imSigma == gimpRadius + 1.0.

    Based on my tests, the following shell script will closely reproduce Gimp’s results in ImageMagick:

    #!/bin/sh
    # Usage: unsharp.sh
    convert “$1″ -unsharp 0x$(dc -e “4k 1 $2 +p”)+$3+$(dc -e “4k $4 255.0 /p”) “$5″

    I.e. Gimp’s unsharp at radius=2;amount=1.5;threshold=5 would result in
    convert infile.tif -unsharp 0×3+1.5+0.0196 outfile.tif

    Note that I let ImageMagick decide on radius here. To match Gimp’s results perfectly, one would have to read the source code of both programs to figure out a better value for radius.

    Comment by Alex Beels — September 16, 2008 @ 8:30 pm

  7. Thanks for this awesome technical note! Very well researched, experimented and compiled! Hope the IM homepage does the same for its tools :)

    Comment by Sendhil — February 3, 2009 @ 10:45 pm

  8. A great article, thanks.

    I also found a page on the ImageMagick website, http://www.imagemagick.org/Usage/convolve/#sharpen. The radius and sigma values are explained in the Blurring section, with some good examples.

    Basically, they suggest always setting radius to 0, so IM picks the best value based on sigma. So to match other tools just choose a sigma of maybe half the intended radius, or as you suggest, sqrt.

    Comment by MrGreedy — March 25, 2009 @ 4:00 am

  9. Thanks for this excellent Image Magick topic. This is the best explaination of how these parameters work that I’ve seen. Excellent work!

    Comment by Tom — April 9, 2009 @ 8:41 pm

  10. [...] Unsharpening with ImageMagick [...]

    Pingback by Urban Influence — June 12, 2009 @ 11:16 am

  11. Great article. I’ve been looking for such detailed informations about sigma for a while.
    Thank you.

    Comment by Olivier — July 30, 2009 @ 8:09 pm

  12. [...] ImageMagick to unsharpen each of our photos. If you want a more detailed explanation, please see this great blog post about fine-tuning this command. As is shown here, this command is performing an unsharp mask of a [...]

    Pingback by Automated image sharpening- Nate Miller — October 10, 2009 @ 9:45 am


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.