问题
I'd like to locate all the nonzero values within a 2D numpy array and move them so that the image is centered. I do not want to pad the array because I need to keep it the same shape. For example:
my_array = np.array([[1, 1, 0, 0], [0, 0, 2, 4], [0, 0, 0, 0], [0, 0, 0, 0]])
# center...
>>> [[0 0 0 0]
[0 1 1 0]
[0 2 4 0]
[0 0 0 0]]
But in reality the arrays I need to center are much larger (like 200x200, 403x403, etc, and they are all square). I think np.nonzero
and np.roll
might come in handy, but am not sure of the best way to use these for my large arrays.
回答1:
The combination of nonzero
and roll
can be used for this purpose. For example, if k=0
in the loop shown below, then np.any
will identify the rows that are not identically zero. The first and last such rows are noted, and the shift along the axis is computed so that after the shift, (first+last)/2
will move to the middle row of the array. Then the same is done for columns.
import numpy as np
my_array = np.array([[1, 1, 0, 0], [2, 4, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]])
print(my_array) # before
for k in range(2):
nonempty = np.nonzero(np.any(my_array, axis=1-k))[0]
first, last = nonempty.min(), nonempty.max()
shift = (my_array.shape[k] - first - last)//2
my_array = np.roll(my_array, shift, axis=k)
print(my_array) # after
Before:
[[1 1 0 0]
[2 4 0 0]
[0 0 0 0]
[0 0 0 0]]
After:
[[0 0 0 0]
[0 1 1 0]
[0 2 4 0]
[0 0 0 0]]
Alternative: np.count_nonzeros
can be used in place of np.any
, which allows to potentially set some threshold for the number of nonzero pixels that are deemed "enough" to qualify a row as a part of the image.
来源:https://stackoverflow.com/questions/51716954/how-to-center-the-nonzero-values-within-2d-numpy-array