1

I have a numpy array of shape(1080,960)

[[0 0 255 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 255 0 0]
 ...
 [0 0 0 ... 0 0 0]
 [0 0 0 ... 0 0 0]
 [0 255 255 ... 0 0 0]]

I want to output a numpy array that replaces the repeated values of both 0 and 255 with a single 0 and a single 255

The numpy array is a representation of a binary image that has pixels in the form BBBWWWWWWWBBBBWWW where B is black and W is white. I want to convert it into BWBW.

Example:

input:

[[0,0,0,255,255,255,0,0,0,0],
 [255,255,255,0,0,0,255,255,255],
 [0,0,255,0,0,255,0,0,255]]

output:

[[0,255,0],
 [255,0,255]
 [0,255,0,255,0,255]]
5
  • What have you tried so far? Commented Aug 3, 2018 at 9:31
  • I have tried itertools´ groupby function, various numpy transformations, etc Commented Aug 3, 2018 at 9:49
  • The numpy array is a representation of a binary image that has pixels in the form BBBWWWWWWWBBBBWWW where B is black and W is white. I want to convert it into BWBW Commented Aug 3, 2018 at 9:50
  • What happens when different rows contain different number of combinations? Like assume the output of first row is BWBW, then second is BWB, third is B, fourth is BWBWB? This will not be a numpy array anymore? Do you just want the individual entries or want to do anything else from it? Commented Aug 3, 2018 at 10:22
  • I am aware that the length of the rows would be uneven, but I would like to append each row with zeroes, to create a 2D numpy array Commented Aug 6, 2018 at 9:21

2 Answers 2

1

You cannot output a 2D numpy array because output rows may have different lengths. I would settle for a list of numpy arrays. So 1st let's generate some data:

img = np.random.choice([0,255], size=(1080, 960))

Then iterate over each row:

out=[]
for row in img:
    idx=np.ediff1d(row, to_begin=1).nonzero()[0]
    out.append(row[idx])

By taking the difference we are simply detecting where changes take place, and then using those indices idx to select the starting element in a consecutive streak. This solution is a bit simpler and faster than the the one by @DavidWinder (30 ms vs. 150 ms).

A fully vectorized solution can be a bit faster, but the code would be a bit complex. It would involve flattening arrays, raveling and unraveling indices... and applying np.split at the end, which is not a very fast operation because it involves creating a list. So I think this answer is good enough compromise between speed/code simplicity.

Edit #1

If the preferred output is an array padded with 0s at the end, it is better to create a zeros array and fill it with values of out list. First find out which row has more elements, and create array:

max_elms = np.max([len(x) for x in out])
arr = np.zeros((1080, max_elms), dtype=np.int32)

And then iterate over out list and arr, filling values of arr with the ones in out list:

for row, data in zip(arr, out):
    row[:len(data)] = data
Sign up to request clarification or add additional context in comments.

4 Comments

Yes, that is the problem. I would like to output a 2D numpy array and append each row with zeroes at the end to make them all the same length.
Could you suggest something for that?
In the final output numpy array, arr, if I want to compare the consecutive values in each row, how do I access these values?
To acces specific elements in a row, for example row 0 element i: arr[0, i]
1

You can iterate over the rows and group the element by build new array while checking last elements and append only if difference.

Function as follow:

def groupRow(row):
    newRow = [row[0]]
    for elem in row:
            if elem != newRow[-1]:
                    newRow.append(elem)
    return newRow

Iterate and replace every row in the shape with the newRow from that function

2 Comments

The ´row´ that should be passed here -- is it a list?
Row is np array as: A = np.array([0,0,0,1,1,1,1,0,0,1]). The same algorithm can be modify to list if that suite you better

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.