paul taney | 7 Oct 20:27
Favicon

collecting the bluest pixels

Hi,

I have this silly color filter that Stefan gave me:

def vanderwalt(image, f):
    """colorfilter, thanks to Stefan van der Walt"""
    RED, GRN, BLU = 0, 1, 2
    bluemask = (image[...,BLU] > f*image[...,GRN]) & \
               (image[...,BLU] > f*image[...,RED])

    return bluemask

To collect the right number of the bluest pixels I am calling it from this arduous successive approximation
routine.  It occured to me that someone on this list knows how to do this in a couple of lines...

def successive_approximation(image, density, width, height, bpp):
    """keep calling vanderwalt till line length is within 10% of density target"""
    count = 0
    failsafe = 20  # max iterations
    gimp.progress_init("this is the fun part...")
    init_high = 1.400001
    init_low = 1.399991
    high_guesses = [(init_high, width*height*bpp)]  # we collect recent stats in this list
    low_guesses  = [(init_low, 0)]
    crossed_high = crossed_low = False
    factor = 1.4
    delta_high = .18   # adjust the factor by this much when it is too high
    delta_low = .14    # adjust the factor by this much when it is too low 
                       # if they were the same amount then they"d cancel
    xlength = 0
(Continue reading)

| 7 Oct 21:28
Favicon

Re: collecting the bluest pixels

Hi Paul

2008/10/7 paul taney <paultaney <at> yahoo.com>:
> I have this silly color filter that Stefan gave me:
>
> def vanderwalt(image, f):
>    """colorfilter, thanks to Stefan van der Walt"""
>    RED, GRN, BLU = 0, 1, 2
>    bluemask = (image[...,BLU] > f*image[...,GRN]) & \
>               (image[...,BLU] > f*image[...,RED])
>
>    return bluemask

Here's a heuristic method that may work.  The above statement is equivalent to

image[...,BLU] > f*max(image[...,GRN], image[...,RED])

So I would construct a new array with the maximum of the red and green
values.  Then, divide that new image by the blue image -- this gives
you all the different "f" values above.  Calculate the histogram of
the "f"s, and pick an f with the right percentile.

Regards
Stéfan
Anne Archibald | 7 Oct 21:30

Re: collecting the bluest pixels

2008/10/7 paul taney <paultaney <at> yahoo.com>:
> Hi,
>
> I have this silly color filter that Stefan gave me:
>
>
> def vanderwalt(image, f):
>    """colorfilter, thanks to Stefan van der Walt"""
>    RED, GRN, BLU = 0, 1, 2
>    bluemask = (image[...,BLU] > f*image[...,GRN]) & \
>               (image[...,BLU] > f*image[...,RED])
>
>    return bluemask
>
>
> To collect the right number of the bluest pixels I am calling it from this arduous successive
approximation routine.  It occured to me that someone on this list knows how to do this in a couple of lines...

Well, I can see several approaches. The most direct way to do what
you're asking is to use scipy.optimize.bisect to implement the
successive approximations. That'll be almost as slow as your current
approach, though. Instead, I'd first write a function that measures
the "blueness" of each pixel:

def blueness(image):
      A = np.empty(image.shape[:-1],dtype=np.float32)
      np.divide(image[...,BLU],image[...,RED],A) # use three-argument
divide to reduce the number of float temporaries
      B = np.empty(image.shape[:-1],dtype=np.float32)
      np.divide(image[...,BLU],image[...,GRN],B)
(Continue reading)

paul taney | 7 Oct 22:27
Favicon

Re: collecting the bluest pixels

Thank you Stefan and Anne for such quick replies.

I am writing a gimp plugin, and if anybody is interested in how do that -- there are only about 10-20 examples
that I"ve found -- this plugin is attempting to do raster-to-vector conversion on the bluest pixels.  It
outputs SVG and a python tuple.  Current version is at 

    http://pastebin.com/m2bd8113f

I dunno np.histogram yet, so rather than look that up I tried Anne"s approach.

I get a divide by zero error on 

    np.divide(image[...,BLU], image[...,GRN], B)

...and I dont understand this well enough to diagnose.  Any ideas?

Thanks in advance,
paul

----

Anne1 = """Well, I can see several approaches. The most direct way to do what you're asking is to use
scipy.optimize.bisect to implement the successive approximations. That'll be almost as slow as your
current approach, though. Instead, I'd first write a function that measures the "blueness" of each pixel:"""

def blueness(image, linedensity):
    A = np.empty(image.shape[:-1], dtype=np.float32)
    np.divide(image[...,BLU], image[...,RED], A)  # use three-argument
    # divide to reduce the number of float temporaries
    B = np.empty(image.shape[:-1], dtype=np.float32)
(Continue reading)

Christopher Barker | 7 Oct 22:53
Favicon

Re: collecting the bluest pixels

paul taney wrote:
> Thank you Stefan and Anne for such quick replies.
> 
> I am writing a gimp plugin

cool!

> I get a divide by zero error on 
> 
>     np.divide(image[...,BLU], image[...,GRN], B)
> 
> ...and I dont understand this well enough to diagnose.  Any ideas?

you're dividing the value of Blue by the value of green, so if there is 
zero green, yes, you will get a divide by zero error.

I wonder if the euclidian norm would make sense for this application:

HowFarFromBlue = np.sqrt((255-image[...,BLU])**2 +
                          image[...,GRN]**2 +
                          image[...,RED]**2)

smaller numbers would be bluest -- pure blue would be 0, pure red 360, 
etc...

One thing I like about this is that your "blue" may not exactly be an 
RBG blue -- so you could see how "far" a given pixel was from any given 
color -- in your case, whatever your blue is. Then it would be something 
like:

(Continue reading)

Anne Archibald | 8 Oct 02:10

Re: collecting the bluest pixels

2008/10/7 Christopher Barker <Chris.Barker <at> noaa.gov>:

> I wonder if the euclidian norm would make sense for this application:
>
> HowFarFromBlue = np.sqrt((255-image[...,BLU])**2 +
>                          image[...,GRN]**2 +
>                          image[...,RED]**2)
>
> smaller numbers would be bluest -- pure blue would be 0, pure red 360,
> etc...
>
> One thing I like about this is that your "blue" may not exactly be an
> RBG blue -- so you could see how "far" a given pixel was from any given
> color -- in your case, whatever your blue is. Then it would be something
> like:
>
> r, g, b = ref_color
>
> HowFarFromRefColor = np.sqrt((r - image[...,RED])**2 +
>                              (g - image[...,GRN])**2 +
>                              (b - image[...,BLU])**2
>                              )
>
>
> NOTE: I know nothing of image prcessing -- I"ll be there is are some
> standard ways to determine how "close" two colors are.

It's a tricky problem, but if you're serious about it you can use
Euclidean distance in the CIELUV colour space, or if you're really
serious Euclidean distance in CIELAB. Both probably overkill for this
(Continue reading)


Gmane