[Image-SIG] Removing specific range of colors from scanned image

Scott David Daniels Scott.Daniels at Acm.Org
Tue Apr 28 20:58:00 CEST 2009


Fredrik Lundh wrote:
> On Tue, Apr 28, 2009 at 4:13 PM, Eduardo Ismael <eismb at hotmail.com> wrote:
>> Thanks, John - I'll have a look at numpy and vips (and CIELAB) right away.
>>
>> I'm having trouble thinking out of the "for pixel in image" loop. Is it
>> possible to calculate with images and not pixels with PIL?
> 
> Sure - the trick is to figure out how to express your problem in terms
> of the basic operations provided by the Image object itself, by the
> ImageChops or ImageOps modules (which should be merged some day), etc.
> 
> And in 1.1.6 and later, there's also the ImageMath module.
> 
>     http://effbot.org/imagingbook/imagemath.htm
> 
> To do a distance calculation, you could do something like:
> 
>     target = (red, green, blue)
>     distance = 10
> 
>     # calculate a distance mask
>     R, G, B = target
>     r, g, b = im.split()
>     distance3 = distance ** 3
> 
>     mask = ImageMath.eval(
>         "convert(((abs(r - R)*abs(g - G)*abs(b - B)) < distance3)*255, 'L')",
>         **locals())
> 
>     # paste in some nice color on pixels that are "close" to the target color
>     im.paste("white", mask)

Warning: this distance function is the product of the three elements,
so an exact match on red, green, or blue will look like a match on all.

Try something like this:
      distance2 = 3 * distance ** 2
      mask = ImageMath.eval("convert((((r-R)**2 + (g-G)**2 + (b-B)**2) "
                                       " < distance2) * 255, 'L')",
                            **locals())
--Scott David Daniels
Scott.Daniels at Acm.Org



More information about the Image-SIG mailing list