[magick-users] adaptive sharpening - the wonders of the 'fx' command
Kornelis Sietsma
korny at sietsma.com
Mon Apr 26 17:35:51 PDT 2004
Hi all - I've been playing with a smart sharpening workflow I found on the
net, and I've managed to get it working with ImageMagick, thanks to the 'fx'
command - I thought I'd share it with you, and see if anyone can give me any
tips for improving the process.
The original technique comes from
http://www.gimpguru.org/Tutorials/SmartSharpening2/ - I wanted to replace this
manual Gimp process with an ImageMagick equivalent, partly because I wanted to
manipulate 48-bit digital camera images, and partly so I could automatically
bulk sharpen a pile of photos at once.
The basic original technique is :
1 - Create an edge mask by running an edge-detect on the image, converting to
greyscale, blurring the results, and spreading the contrast out a bit.
2 - Split the image into HSV channels
3 - Strongly sharpen the V channel using unsharp mask
4 - Merge the sharpened V channel back with the H and S channels, using the
edge mask as a mask.
This means that areas near edges in the original image get sharpened quite
strongly, while areas far from edges get left largely unprocessed.
Due to a lack of HSV channel manipulation in ImageMagick I couldn't do this
quite the same way - there is no way (that I could find) to do step 4 without
resorting to some mathematics. But the rest of the steps were fairly easy:
1. With some fiddling of parameters, I make an edge mask with:
convert orig.png -edge 3 -colorspace GRAY -level 20%,95% -gaussian 10
-level 10%,95% edgemask.png
2. I managed to extract just a brightness image with :
convert orig.png -modulate 100,0 bchannel.png
(This is close enough to the "V" channel for my purposes - I thought of using
"intensity" but that was rather too slow for my liking)
3. Sharpening is simple, though again lots of fiddling of parameters can be
done. Note this is stronger sharpening than you'd want to do normally!
convert bchannel.png -unsharp 0x1+200+0 sharpened.png
4. Merging them back together is where 'fx' comes in:
convert orig.png bchannel.png sharpened.png edgemask.png -fx
"u[0]+(((u[2]+1)/(u[1]+1))-1)*u[0]*u[3]" output.png
just to break that last mess down:
u[0] is the original image
u[1] is the brightness channel
u[2] is the sharpened brightness channel
u[3] is the edge mask
((u[2]+1)/(u[1]+1)) is the ratio of the sharpened brightness to the original -
I had to use "((u[2]+1)/(u[1]+1))" instead of "(u[2]/u[1])" as the latter
would cause divide-by-zero problems on black areas of the original image.
(I'll call this "K" from here on for simplification.)
The rest is to scale the amount of brightness change by the edge mask (u[3]):
when u[3] is 0, the output is "u[0]"
when u[3] is 1, the output is "u[0] + (K-1)*u[0]"
which equals "K * u[0]"
Finally, I string the whole thing together into a single command line:
convert orig.png \( +clone -modulate 100,0 \) \( +clone -unsharp 0x1+200+0 \)
\( -clone 0 -edge 3 -colorspace GRAY -level 20%,95% -gaussian 10 -level
10%,95% \) -colorspace RGB -fx "u[0]+(((u[2]+1)/(u[1]+1))-1)*u[0]*u[3]" output.png
Note I had to put an extra "-colorspace RGB" in there to stop the output being
greyscale.
It's kind of slow on a big image, but it works!
Thoughts, comments, improvements?
- Korny
--
Kornelis Sietsma korny at my_surname.com
More information about the Magick-users
mailing list