Re: [Numpy-discussion] collecting the bluest pixels
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/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
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
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/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