1

I am reading an image like so:

img = np.array(Image.open(test_dir + image_name))

What I want to do is find a region in the array where the value is high (250 or more) and reduce it by 10:

rows = img.shape[0]
cols = img.shape[1]
pixel = []
for x in range(0,rows):
    for y in range(0, cols):
        if x >= 122 and x <= 160 and y >= 34  and y <= 71:
            if img[x,y]>= 250:
                img[x,y] = img[x,y] -10
                pixel.append(img[x,y])

So the region I am looking at according the the unaltered image should be a box from (122, 34) to (160,71), and it should have some pixels over 250, but somehow when I run this code I end up with nothing in the pixel list

4 Answers 4

1

Is img a 3 dimensional array? If so, then your test img[x, y] >= 250 is testing if an array of 3 elements is greater than 250. This will result in an error and cause your script to terminate at that point. You did not say if this is happening.

If it is a 3 dimensional array and you want to check if all channels have value greater than 250 at position x, y, then you have to check for np.all(img[x, y] >= 250) instead of img[x, y] >= 250.

In general you want to avoid loops and use vectorized operations to speed things up.

min_row = 122
max_row = 161
min_col = 34
max_col = 72
threshold = 250

row_slice = slice(min_row, max_row)
col_slice = slice(min_col, max_col)
roi = img[row_slice, col_slice] >= threshold
img[row_slice, col_slice][roi] -= 10

or more succinctly but less readable,

roi = img[min_row:max_row, min_col:max_col] >= threshold
img[min_row:max_row, min_col:max_col][roi] -= 10
Sign up to request clarification or add additional context in comments.

Comments

1

The simplest way is one line:

im[im>250]-=10

Demonstration

Start with this 8x8 gradient image:

enter image description here

Here it is enlarged:

enter image description here

Then use IPython like this:

# Load image as L (greyscale)
im = np.array(Image.open('image.png').convert('L'))

# View contents
im
Out[16]: 
array([[255, 255, 255, 255, 255, 255, 255, 255],
       [219, 219, 219, 219, 219, 219, 219, 219],
       [182, 182, 182, 182, 182, 182, 182, 182],
       [146, 146, 146, 146, 146, 146, 146, 146],
       [109, 109, 109, 109, 109, 109, 109, 109],
       [ 73,  73,  73,  73,  73,  73,  73,  73],
       [ 36,  36,  36,  36,  36,  36,  36,  36],
       [  0,   0,   0,   0,   0,   0,   0,   0]], dtype=uint8)

# Do required processing
im[im>250]-=10

# Review contents
In [18]: im
Out[18]: 
array([[245, 245, 245, 245, 245, 245, 245, 245],
       [219, 219, 219, 219, 219, 219, 219, 219],
       [182, 182, 182, 182, 182, 182, 182, 182],
       [146, 146, 146, 146, 146, 146, 146, 146],
       [109, 109, 109, 109, 109, 109, 109, 109],
       [ 73,  73,  73,  73,  73,  73,  73,  73],
       [ 36,  36,  36,  36,  36,  36,  36,  36],
       [  0,   0,   0,   0,   0,   0,   0,   0]], dtype=uint8)

Let's try decreasing even more pixels, just for fun:

In [19]: im[im>100]-=10

In [20]: im
Out[20]: 
array([[235, 235, 235, 235, 235, 235, 235, 235],
       [209, 209, 209, 209, 209, 209, 209, 209],
       [172, 172, 172, 172, 172, 172, 172, 172],
       [136, 136, 136, 136, 136, 136, 136, 136],
       [ 99,  99,  99,  99,  99,  99,  99,  99],
       [ 73,  73,  73,  73,  73,  73,  73,  73],
       [ 36,  36,  36,  36,  36,  36,  36,  36],
       [  0,   0,   0,   0,   0,   0,   0,   0]], dtype=uint8)

Comments

0

Provided your image is grayscale this will do it.

inds = np.where(img>=250)
inds = inds[(inds.T[0]>=122)&(inds.T[0]<=160)&(inds.T[1]>=34)&(inds.T[1]<=71)]
img[inds]-=10

Comments

0

For a more compact solution you can try

roi = img[122:161, 34:72]
pixel = roi[roi >= 250]
roi[roi >= 250] -= 10

5 Comments

Neither roi or pixel are used in the final line... Please review.
@Benjamin Actually, I just looked at this more carefully and, you are correct, the first 2 lines are not needed, but... the final line works on its own as it is the same as my answer which I demonstrated to work in my answer.
@Benjamin You are right about roi, I've fixed that, thanks. As for, the second line, it isn't explicitly asked but the code in the original question also extracts the values of the pixels in the variable pixel
@MarkSetchell The first line is actually needed since the OP just wants to search within a certain area.
There has been an edit here that makes my comment ambiguous... and pixel is still not being used.

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.