0

To illustrate my point, lets take this 2d numpy array:

array([[1, 1, 5, 1, 1, 5, 4, 1],
       [1, 5, 6, 1, 5, 4, 1, 1],
       [5, 1, 5, 6, 1, 1, 1, 1]])

I want to replace the value 1 with some other value, let's say 0, but only at the edges. This is the desired result:

array([[0, 0, 5, 1, 1, 5, 4, 0],
       [0, 5, 6, 1, 5, 4, 0, 0],
       [5, 1, 5, 6, 0, 0, 0, 0]])

Note that the 1's surrounded by other values are not changed.

I could implement this by iterating over every row and element, but I feel like that would be very inefficient. Normally I would use the np.where function to replace a specific value, but I don't think you can add positional conditions?

seb
  • 105
  • 1
  • 6
  • Related: https://stackoverflow.com/questions/41200719/how-to-get-all-array-edges , Another one: https://stackoverflow.com/questions/60811307/check-if-a-numpy-array-has-0-on-all-its-borders – Ch3steR Mar 23 '20 at 10:32
  • 3
    @Ch3steR The OP is misleading by calling it edges. The example demonstrates that you start from the corners and propagate until you hit a value not equal to 1. So the thickness of the "edge" may be more than 1 row/column and it can also be that an element in the proper edges is not affected. – Reti43 Mar 23 '20 at 10:49
  • Can you tell us what problem you're trying to solve? There might be a better by representing your data differently. Also, how big is your array? Based on how it's been stated so far, I can't think of a better way than some form of iterative process. Also, is 0 likely to be part of your normal data? – Reti43 Mar 23 '20 at 10:52
  • @Reti43 Sorry if my question was a bit vague, I thought the example would be sufficient. The problem is that I have a lot of images with some kind of padding with a gray value of 168 (as seen in the example with 1's). But these are not just constant borders with a fixed size: they vary per row. I want to set these 'border' values to 0. However, if I set all 168 values in the array to 0, there will also be a lot of pixels inside the image that get changed to 0, which is not something I want. – seb Mar 23 '20 at 11:04

1 Answers1

3
m = row!=1   
w1 = m.argmax()-1
w2 = m.size - m[::-1].argmax()

These three lines will give you the index for the trailling ones. The idea has been taken from trailing zeroes.

Try:

arr = np.array([[1, 1, 5, 1, 1, 5, 4, 1],
       [1, 5, 6, 1, 5, 4, 1, 1],
       [5, 1, 5, 6, 1, 1, 1, 1]])

for row in arr:
    m = row!=1

    w1 = m.argmax()-1
    w2 = m.size - m[::-1].argmax()
#     print(w1, w2)
    row[0:w1+1] = 0
    row[w2:] = 0
#     print(row)

arr:

array([[0, 0, 5, 1, 1, 5, 4, 0],
       [0, 5, 6, 1, 5, 4, 0, 0],
       [5, 1, 5, 6, 0, 0, 0, 0]])
Pygirl
  • 12,969
  • 5
  • 30
  • 43