[Numpy-discussion] color filtering

paul taney paultaney@yahoo....
Wed Sep 17 07:29:18 CDT 2008

```Hi,

I"m just learning numpy and I am not a math.  I just need it.

I need to do a color filter;  I have it working in python
but it runs forever on some of my images.  And I dont know
enuf c or c++ to use weave (or Boost or Pyrex or...)

This looks like the best way, and I have somebody who is
advising me, but he said to put the question to you guys, so

I have an array from a wx.Image, but for testing we can use
something just 5 * 5 * 3.  I want the x,y coords of the blues
pixel(s) per x returned as a line of this sort:

[(x1, y1), (x2, y2)...(xn, yn)]

# In real life we have an image:

import wx
import numpy as np
image = wx.Image(path, wx.BITMAP_TYPE_ANY)
w, h = image.GetWidth(), image.GetHeight()
# Rappin page 362, Smart page 285
a = np.fromstring(image.GetData(), np.uint8)
a.reshape(w, h, 3)

# But while testing we can use:

import numpy as np
a = np.array(
[[[ 64, 237, 108],  #  x  y
[185, 240,  68],  # [0, 1]
[ 17, 116,  55],  # [0, 2]
[107,  11, 185],  # [0, 3] is blue
[154,  30,  52]], # [0, 4]

[[251,  73, 150],  #  x  y
[ 47, 225,  97],  # [1, 1]
[101,  91, 251],  # [1, 2] is blue
[ 61,  23,  79],  # [1, 3]
[161,  22, 165]], # [1, 4]

[[  4, 162, 188],  # [2, 0]
[ 25, 131, 211],  # [2, 1]
[162, 112, 177],  # [2, 2]
[169,  83, 214],  # [2, 3] is blue
[254, 139,  95]],

[[  2,  88, 216],  # [3, 0] is blue
[230,  63, 192],
[ 71,  78, 250],  # [3, 2] is blue
[113, 151, 142],
[104,  65, 127]],

[[  6, 191, 220],  # [4, 0] is blue
[ 38, 141,   4],
[245,  41,  23],
[ 23, 127, 183],  # [4,] is blue
[165,  24,   5]]], np.uint8)

# some of these tests work...
# Proceeding from the concrete to the abstract...

DIM = (5, 5)
def test1(a):

red, grn, blu = a[0,0]
print "r=%r, g=%r, b=%r" % (red, grn, blu)  # prints r=64, g=237, b=108

red, grn, blu = a[4, 4]
print "r=%r, g=%r, b=%r" % (red, grn, blu)  # prints r=165, g=24, b=5

def test2(a):
# this is a threshold filter
rmin, rmax, gmin, gmax, bmin, bmax = 0,178, 0,178, 100,255

very_blue_pixels = []
w = DIM[0]
x = y = 0
# searches rows first (x is turning faster, so...)
for yslice in a:
for xyslice in yslice:
if 0: print "x=%r, y=%r, type(xyslice)= %r" % (x, y, type(xyslice))
if 0: print "a[x=%i, y=%i] = %r" % (x, y, a[x,y])
red, grn, blu = xyslice
if (rmin <= red <= rmax) and \
(gmin <= grn <= gmax) and \
(bmin <= blu <= bmax):
if 1: print "a very blue pixel at x=%i, y=%i, rgb=%r" % (x, y, xyslice)
very_blue_pixels.append((x,y))
y += 1
if y==w: y=0  # ugly
x += 1
print very_blue_pixels

def test3(a, THRESH):
# for my dataset I can optimize the above loop like this
# at the cost of getting less output since the THRESHOLD
# is only one number

very_blue_pixels = []
w = w=DIM[0]
x = y = 0
for yslice in a:
for xyslice in yslice:
red, grn, blu = xyslice
if (red <= THRESH) and (grn <= THRESH) and (THRESH <= blu):
very_blue_pixels.append((x, y))
if 1: print "I see blue a[x=%i, y=%i] pixel = %r" % (x, y, xyslice)
y += 1
if y==w: y=0
x += 1
print very_blue_pixels

# <snip>
# I see blue a[x=3, y=2] pixel = array([ 71,  78, 250], dtype=uint8)
# I see blue a[x=4, y=3] pixel = array([ 23, 127, 183], dtype=uint8)
# [(0, 3), (1, 2), (2, 0), (2, 1), (2, 3), (3, 0), (3, 2), (4, 3)]

def test4(a):
RED, GRN, BLU = 0, 1, 2
rmin, rmax, gmin, gmax, bmin, bmax = 0,178, 0,178, 100,255
line_pix = ((rmin <= a[:, :, RED] <= rmax) &
(gmin <= a[:, :, GRN] <= gmax) &
(bmin <= a[:, :, BLU] <= bmax))
print "test4: line_pix = %r" % (line_pix)
# ValueError: The truth value of an array with more than
# one element is ambiguous. Use a.any() or a.all()

# There is one more test in the attached file who"s
# results mystify me.  It goes like this:

def test5(a, rmax, gmax, bmin):
RED, GRN, BLU = 0, 1, 2
line_pix = ((a[:, :, RED] <= rmax) &
(a[:, :, GRN] <= gmax) &
(a[:, :, BLU] >= bmin))
print "test5: line_pix = %r" % (line_pix)

# returns
# test5: line_pix = array([
#        [False, False, False,  True, False],
#        [False, False,  True, False,  True],
#        [ True,  True,  True,  True, False],
#        [ True, False,  True,  True,  True],
#        [False, False, False,  True, False]], dtype=bool)

All I need is a line like this: [(x,y),(x,y)(x,y)...(x,y)]
preferably 1 y per x at the "best" (cluster) location,
without going into kmeans or anything obscure.

Any suggestions?

This is for a volunteer project vectorizing scanned
stripcharts for http://IEDRO.org