0

Is possible to implement this image filtering process in numpy array ? I need to check if the pixel in the previous column and previous row is differente of the current pixel.

width, height = orig_bin.size
pixels = orig_bin.load()

delta = 50
begin = 10
min_w = 30
max_w = 260
min_h = 10
max_h = 40

w_range = range(begin, width - min_w - delta)
h_range = range(begin, height - min_h - delta)

is_changing = False
for x in w_range:
    for y in h_range:
        change_pixel = False
        current_pixel = pixels[x,y]
        if current_pixel != pixels[x, y+1]:
            change_pixel = True

        if current_pixel != pixels[x+1, y]:
            change_pixel = True

        if change_pixel:
            pixels[x,y] = (0,0,0)
        else:
            pixels[x,y] = (255,255,255)

Best regards, Emilio

1
  • Is there a problem with this implementation or are you looking to optimize? What's the question here specifically? Commented Feb 27, 2014 at 19:58

2 Answers 2

2

Here's one approach. Take an example image:

Render of Utah teapot model by Martin Newell

You didn't say where your orig_bin came from, so I've used scipy.misc.imread:

from scipy.misc import imread, imsave
img = imread('input.png')

First, create a mask for pixels that are different from the pixel above (this uses an idea from Bi Rico's answer):

up   = (img[1:,1:] != img[:-1,1:]).any(axis=2)

Note that imread loads images in row-major order, so the first NumPy axis is the vertical axis. See "Multidimensional Array Indexing Order Issues" for an explanation.

Similarly, create a mask for pixels that are different from the pixel to the left:

left = (img[1:,1:] != img[1:,:-1]).any(axis=2)

Combine these to get a mask for pixels that are different to either the pixel above or left:

mask = numpy.zeros(img.shape[:2], dtype=bool)
mask[1:,1:] = left | up

Create a black output image of the right size; then set the mask to white:

output = numpy.zeros(img.shape)
output[mask] = (255, 255, 255)
imsave('output.png', output)

And here's the result:

Output white

or if you want the colours to be the other way round, invert the mask:

output[~mask] = (255, 255, 255)

Output black

Sign up to request clarification or add additional context in comments.

2 Comments

Good spot! Fixed; and I adopted your idea of computing a smaller mask.
Gareth Rees, Is possible to invert the colors ? The mask use (0,0,0) and the color is filled with 255,255,255 ?
1

You want something like:

change = (pixels[1:, 1:] != pixels[1:, :-1]) | (pixels[1:, 1:] != pixels[:-1, 1:])

This will be binary (True, False), you'll need to multiply it by 255 if you want your result to be 0/255. You also might need to run and any on the last dimension if you array is (x, y, 3).

There are other ways you could re-cast this problem, for example a convolution with [1, -1] might get you most of the way there.

2 Comments

I get ValueError: operands could not be broadcast together when I try this.
@GarethRees, the left and right side of | should have the same shape. I've fixed the issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.