Re: [Numpy-discussion] collecting the bluest pixels

2008-10-07 Thread Stéfan van der Walt
Hi Paul

2008/10/7 paul taney <[EMAIL PROTECTED]>:
> 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
___
Numpy-discussion mailing list
Numpy-discussion@scipy.org
http://projects.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] collecting the bluest pixels

2008-10-07 Thread Anne Archibald
2008/10/7 paul taney <[EMAIL PROTECTED]>:
> 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)
  return np.minimum(A,B)

Now, once you have the bluenesses, you can sort them and pull out the
blueness that gives you the percent you want:

bluenesses = np.sort(blueness(image),axis=None) # axis=None flattens the array
factor = bluenesses[int((1-wanted_fraction)*len(bluenesses))]

If you want a smarter blueness filter, you could look into using HSV:
you could then specify a distance in hue and a distance in saturation,
based on how relatively important you think they are.

Anne
___
Numpy-discussion mailing list
Numpy-discussion@scipy.org
http://projects.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] collecting the bluest pixels

2008-10-07 Thread paul taney
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)
np.divide(image[...,BLU], image[...,GRN], B)
return np.minimum(A, B)

Anne2 = """
Now, once you have the bluenesses, you can sort them and pull out the
blueness that gives you the percent you want:
"""
bluenesses = np.sort(blueness(image), axis=None)  # axis=None flattens the 
array
#factor = bluenesses[int((1-wanted_fraction)*len(bluenesses))]
w, h, bpp = image.shape
factor = bluenesses[int((1-(linedensity*6/float(w*h))) * len(bluenesses))] 

Anne3 = """
If you want a smarter blueness filter, you could look into using HSV:
you could then specify a distance in hue and a distance in saturation,
based on how relatively important you think they are.
Anne
"""
print "blueness returning factor = %r" % (factor)
return factor


___
Numpy-discussion mailing list
Numpy-discussion@scipy.org
http://projects.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] collecting the bluest pixels

2008-10-07 Thread Christopher Barker
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:

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.

-Chris


-- 
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

[EMAIL PROTECTED]
___
Numpy-discussion mailing list
Numpy-discussion@scipy.org
http://projects.scipy.org/mailman/listinfo/numpy-discussion


Re: [Numpy-discussion] collecting the bluest pixels

2008-10-07 Thread Anne Archibald
2008/10/7 Christopher Barker <[EMAIL PROTECTED]>:

> 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
project.

Anne
___
Numpy-discussion mailing list
Numpy-discussion@scipy.org
http://projects.scipy.org/mailman/listinfo/numpy-discussion