[Image-SIG] Unsharp Masking?
Kevin@Cazabon.com
kevin@cazabon.com
Sun, 17 Mar 2002 21:24:45 -0700
This is a multi-part message in MIME format.
------=_NextPart_000_0062_01C1CDFA.2929D510
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
I've cleaned it up a bit, and added documentation so you people other =
than me understand what's going on in the code a little more.
I've tried to move all the calculations upstream as much as possible, =
but it's still only about 7% faster than the original... there's a LONG =
way to go. On a dual 1.2ghz box, it's taking 30 seconds to sharpen a =
400x600 pixel image!
Iterating over each channel of each pixel in Python is just too slow... =
would trying to implement this type of thing in a C extension (like the =
core _imaging.pyd file) help a lot? Unfortunately, I'm not much of a C =
programmer. FRED!!! HELP!!! q:]
I could do the calculations on a gray-scale version of the file and only =
sharpen based on gray-contrast, but I'd rather not limit it that way... =
(max 3x speed improvement, minus time to create grayscale version of =
image)
The updated version, if anyone can give me a hand is available at: =
http://www.cazabon.com/python/unsharpMask/UnsharpMaskingModule.py
(and it now can be used for gaussian blurring too, as an added bonus).
Thanks,
Kevin.
----- Original Message -----=20
From: Moodie, Craig CA=20
To: 'Kevin@Cazabon.com'=20
Sent: Sunday, March 17, 2002 7:05 PM
Subject: RE: [Image-SIG] Unsharp Masking?
Kevin,
On first inspection I would suggest that you remove as much as is =
physically possible from the inner loop. Put as much as you can into a =
lookup table-----avoid calculations.You should be able to at least get a =
speed increase of 2.
For example
pixNumber =3D ((column + (row * =
image.size[0])) * channels) + c + (xr * channels) + (yr * image.size[0] =
* channels)
=20
if pixNumber < 0:
pixNumber =3D column * channels
elif pixNumber > len(imArray) - 1:
pixNumber =3D (column + (row * =
image.size[0])) * channels
=20
pixValue =3D imArray[pixNumber]
=20
pixWeight =3D pow(weight, (abs(xr) + =
abs(yr)))----------------------->LUT
totalValue =3D totalValue + ((origPixel - =
pixValue) * pixWeight)
the underlined could all be calculated outside the xr,yr loops.
Cheers
Craig
-----Original Message-----
From: Kevin@Cazabon.com [mailto:kevin@cazabon.com]
Sent: Monday, March 18, 2002 10:18 AM
To: image-sig@python.org
Subject: [Image-SIG] Unsharp Masking?
Does anyone have a FAST unsharp-masking method for use with PIL?
I wrote a brute-force module for this in Python today (attached, if =
it gets through the newsgroup filters) that works just fine, but it's =
mighty slow... anyone have something faster? The built in =
ImageEnhance.Sharpness filter is OK for very basic stuff, but the best =
way to sharpen is through an unsharp-mask type algorithm... it's much =
more powerful and controllable.
For those that don't know how unsharp masking works, here's the =
basics:
1) a copy of the image is blurred using a gaussian-type blurring =
algorighm (this is the 'unsharp' part), with a user-defined radius for =
the blur.
2) the blurred image is then compared (pixel by pixel if necessary) =
to the original image
3) the amount of difference between the blurred pixel and original =
pixel determines if it is an edge or not. If the difference is greater =
than the user-specified "threshold", sharpening is performed in step 4)
4) the pixel is changed by the OPPOSITE amount of the difference =
between the original and blurred pixels, multiplied by the user-defined =
"percentage"
Any help is appreciated in speeding this up!
Kevin Cazabon.
EOM=20
NOTICE - This message and any attached files may contain information =
that is confidential and/or subject of legal privilege intended only for =
use by the intended recipient. If you are not the intended recipient or =
the person responsible for delivering the message to the intended =
recipient, be advised that you have received this message in error and =
that any dissemination, copying or use of this message or attachment is =
strictly forbidden, as is the disclosure of the information therein. If =
you have received this message in error please notify the sender =
immediately and delete the message.
------=_NextPart_000_0062_01C1CDFA.2929D510
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 5.50.4913.1100" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DArial size=3D2>I've cleaned it up a bit, and added =
documentation=20
so you people other than me understand what's going on in the =
code a=20
little more.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>I've tried to move all the calculations =
upstream as=20
much as possible, but it's still only about 7% faster than the =
original...=20
there's a LONG way to go. On a dual 1.2ghz box, it's taking 30 =
seconds to=20
sharpen a 400x600 pixel image!</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Iterating over each channel of each =
pixel in Python=20
is just too slow... would trying to implement this type of thing in a C=20
extension (like the core _imaging.pyd file) help a lot? =
Unfortunately, I'm=20
not much of a C programmer. FRED!!! HELP!!! q:]</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>I could do the calculations on a =
gray-scale version=20
of the file and only sharpen based on gray-contrast, but I'd rather not =
limit it=20
that way... (max 3x speed improvement, minus time to create grayscale =
version of=20
image)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>The updated version, if anyone can =
give me a=20
hand is available at: <A=20
href=3D"http://www.cazabon.com/python/unsharpMask/UnsharpMaskingModule.py=
">http://www.cazabon.com/python/unsharpMask/UnsharpMaskingModule.py</A></=
FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>(and it now can be used for gaussian =
blurring too,=20
as an added bonus).</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Thanks,</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Kevin.</FONT></DIV>
<BLOCKQUOTE dir=3Dltr=20
style=3D"PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; =
BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">
<DIV style=3D"FONT: 10pt arial">----- Original Message ----- </DIV>
<DIV=20
style=3D"BACKGROUND: #e4e4e4; FONT: 10pt arial; font-color: =
black"><B>From:</B>=20
<A title=3DCraig.Moodie@bhpsteel.com=20
href=3D"mailto:Craig.Moodie@bhpsteel.com">Moodie, Craig CA</A> </DIV>
<DIV style=3D"FONT: 10pt arial"><B>To:</B> <A =
title=3Dkevin@cazabon.com=20
href=3D"mailto:'Kevin@Cazabon.com'">'Kevin@Cazabon.com'</A> </DIV>
<DIV style=3D"FONT: 10pt arial"><B>Sent:</B> Sunday, March 17, 2002 =
7:05=20
PM</DIV>
<DIV style=3D"FONT: 10pt arial"><B>Subject:</B> RE: [Image-SIG] =
Unsharp=20
Masking?</DIV>
<DIV><BR></DIV>
<DIV><SPAN class=3D055105401-18032002><FONT face=3DArial =
color=3D#0000ff=20
size=3D2>Kevin,</FONT></SPAN></DIV>
<DIV><SPAN class=3D055105401-18032002> <FONT =
face=3DArial=20
color=3D#0000ff size=3D2>On first inspection I would suggest that you =
remove as=20
much as is physically possible from the inner loop. Put as much as you =
can=20
into a lookup table-----avoid calculations.You should be able to at =
least get=20
a speed increase of 2.</FONT></SPAN></DIV>
<DIV><SPAN class=3D055105401-18032002><FONT face=3DArial =
color=3D#0000ff size=3D2>For=20
example</FONT></SPAN></DIV>
<DIV><SPAN class=3D055105401-18032002><FONT face=3DArial =
color=3D#0000ff=20
=
size=3D2> &nbs=
p;  =
;=20
pixNumber =3D (<STRONG>(column + (row * image.size[0])) * channels) + =
c</STRONG>=20
+ (xr * channels) + (yr * image.size[0] *=20
=
channels)<BR> =
&=
nbsp;=20
=
<BR> &nb=
sp; =20
if pixNumber <=20
=
0:<BR> &=
nbsp; &n=
bsp; =20
pixNumber =3D <STRONG>column *=20
=
channels</STRONG><BR> &nbs=
p;  =
; =20
elif pixNumber > <STRONG>len(imArray) -=20
=
1</STRONG>:<BR> &nbs=
p;  =
; =20
pixNumber <STRONG>=3D (column + (row * image.size[0])) *=20
=
channels<BR></STRONG> &nbs=
p;  =
; =20
=
<BR> &nb=
sp; =20
pixValue =3D=20
=
imArray[pixNumber]<BR> &nb=
sp; &nbs=
p; =20
=
<BR> &nb=
sp; =20
<STRONG>pixWeight =3D pow(weight, (abs(xr) +=20
=
abs(yr)))----------------------->LUT<BR></STRONG> &nb=
sp; &nbs=
p; =20
totalValue =3D totalValue + ((origPixel - pixValue) * =
pixWeight)<BR>the=20
underlined could all be calculated outside the xr,yr=20
loops.</FONT></SPAN></DIV>
<DIV><SPAN class=3D055105401-18032002> <FONT =
face=3DArial=20
color=3D#0000ff size=3D2>Cheers</FONT></SPAN></DIV>
<DIV><SPAN =
class=3D055105401-18032002> =20
<FONT face=3DArial color=3D#0000ff size=3D2>Craig</FONT></SPAN></DIV>
<BLOCKQUOTE dir=3Dltr style=3D"MARGIN-RIGHT: 0px">
<DIV class=3DOutlookMessageHeader dir=3Dltr align=3Dleft><FONT =
face=3DTahoma=20
size=3D2>-----Original Message-----<BR><B>From:</B> =
Kevin@Cazabon.com=20
[mailto:kevin@cazabon.com]<BR><B>Sent:</B> Monday, March 18, 2002 =
10:18=20
AM<BR><B>To:</B> image-sig@python.org<BR><B>Subject:</B> [Image-SIG] =
Unsharp=20
Masking?<BR><BR></FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Does anyone have a FAST =
unsharp-masking method=20
for use with PIL?</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>I wrote a brute-force module for =
this in Python=20
today (attached, if it gets through the newsgroup =
filters) that=20
works just fine, but it's mighty slow... anyone have something =
faster? =20
The built in ImageEnhance.Sharpness filter is OK for very basic =
stuff, but=20
the best way to sharpen is through an unsharp-mask type algorithm... =
it's=20
much more powerful and controllable.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>For those that don't know how =
unsharp masking=20
works, here's the basics:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>1) a copy of the image is =
blurred using a=20
gaussian-type blurring algorighm (this is the 'unsharp' part), with =
a=20
user-defined radius for the blur.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>2) the blurred image is then =
compared=20
(pixel by pixel if necessary) to the original image</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>3) the amount of difference =
between the=20
blurred pixel and original pixel determines if it is an edge or =
not. =20
If the difference is greater than the user-specified "threshold", =
sharpening=20
is performed in step 4)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>4) the pixel is changed by =
the OPPOSITE=20
amount of the difference between the original and blurred pixels, =
multiplied=20
by the user-defined "percentage"</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Any help is appreciated in speeding =
this=20
up!</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Kevin =
Cazabon.</FONT></DIV></BLOCKQUOTE><BR>
<P><FONT face=3DArial size=3D2>EOM </FONT></P><BR>
<P><FONT face=3DArial size=3D2>NOTICE - This message and any attached =
files may=20
contain information that is confidential and/or subject of legal =
privilege=20
intended only for use by the intended recipient. If you are not the =
intended=20
recipient or the person responsible for delivering the message to the =
intended=20
recipient, be advised that you have received this message in error and =
that=20
any dissemination, copying or use of this message or attachment is =
strictly=20
forbidden, as is the disclosure of the information therein. If you =
have=20
received this message in error please notify the sender immediately =
and delete=20
the message.</FONT></P></BLOCKQUOTE></BODY></HTML>
------=_NextPart_000_0062_01C1CDFA.2929D510--