Adding column to higher dimension - python

let's assume that i have array called A
A = np.zeros((4, 3, 2))
array([[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]]])
and another array called B
B = np.arange(4)
array([0, 1, 2, 3])
and i want to do something like concatenation in the third dimension to got this result:
array([[[0., 0., 0.0],
[0., 0., 0.0],
[0., 0., 0.0]],
[[0., 0., 1.0],
[0., 0., 1.0],
[0., 0., 1.0]],
[[0., 0., 2.0],
[0., 0., 2.0],
[0., 0., 2.0]],
[[0., 0., 3.0],
[0., 0., 3.0],
[0., 0., 3.0]]])
i tried serval ways to do that but i didn't succeed.
who i can do that in good way not loops?

To add the extra dimension you can use np.append. You just have to get the shape correct. You can use np.repeat() to make the repeating elements:
A = np.zeros((4, 3, 2))
h, w, d = A.shape
B = np.repeat(np.arange(h), w).reshape([h, w, 1])
np.append(A, B, axis=2)
Output:
array([[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 1.],
[0., 0., 1.],
[0., 0., 1.]],
[[0., 0., 2.],
[0., 0., 2.],
[0., 0., 2.]],
[[0., 0., 3.],
[0., 0., 3.],
[0., 0., 3.]]])

We could broadcast B to the corresponding shape and use advanced indexing here and assign B broadcasted across the corresponding axes:
np.concatenate([A, np.broadcast_to(B[:,None,None], A[...,-1:].shape)], -1)
print(A)
array([[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 1.],
[0., 0., 1.],
[0., 0., 1.]],
[[0., 0., 2.],
[0., 0., 2.],
[0., 0., 2.]],
[[0., 0., 3.],
[0., 0., 3.],
[0., 0., 3.]]])

Related

Numpy concatenate behaviour. How to concatenate example correctly

I have following multi-dimensional array:
windows = array([[[[[[0., 0.],
[1., 0.]],
[[0., 0.],
[1., 0.]],
[[0., 0.],
[1., 0.]]],
[[[0., 1.],
[0., 0.]],
[[0., 1.],
[0., 0.]],
[[1., 0.],
[0., 0.]]],
[[[1., 0.],
[0., 0.]],
[[0., 1.],
[0., 0.]],
[[0., 1.],
[0., 0.]]]]]])
print(windows.shape)
(1, 1, 3, 3, 2, 2) # (n, d, a, b, c, c) w = a * (c*c), h = b * (c*c)
I want to get next resulting array:
mask = array([[
[[0., 0., 0., 0., 0., 0.],
[1., 0., 1., 0., 1., 0.],
[0., 1., 0., 1., 1., 0.],
[0., 0., 0., 0., 0., 0.],
[1., 0., 0., 1., 0., 1.],
[0., 0., 0., 0., 0., 0.]]
]], dtype=np.float32)
print(mask.shape)
(1, 1, 6, 6) # (n, d, w, h)
Basically, I want to squeeze last 4 dimensions into 2-d matrix so the final shape become (n, d, w, h), in this case (1, 1, 6, 6).
I tried np.concatenate(windows, axis = 2), but it didnt concatenate along 2nd dimension and reduced for some reason first(although I set axis = 2) 'n' dimension.
Additional information:
windows is a result of following code snippet
windows = np.lib.stride_tricks.sliding_window_view(arr, (c, c), axis (-2,-1), writeable = True) # arr.shape == mask.shape
windows = windows[:, :, ::c, ::c] # these are non-overlapping windows of arr with size (c,c)
windows = ... # some modifications of windows
Now I want to build from these windows array with shape of arr.shape, this array called mask in example above. Simple reshape doesn't work because it returns elements in wrong order.
IIUC, you want to merge dimensions 2+4 and 3+5, an easy way would be to swapaxes 4 and 5 (or -3 and -2), and reshape to (1,1,6,6):
windows.swapaxes(-2,-3).reshape(1,1,6,6)
output:
array([[[[0., 0., 0., 0., 0., 0.],
[1., 0., 1., 0., 1., 0.],
[0., 1., 0., 1., 1., 0.],
[0., 0., 0., 0., 0., 0.],
[1., 0., 0., 1., 0., 1.],
[0., 0., 0., 0., 0., 0.]]]])

Can't create ragged array if there is a matching dimension (python/numpy)

I'm doing like this:
>>> import numpy as np
>>> A = np.zeros((12,2))
>>> B = np.zeros((12,))
>>> A
array([[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.]])
>>> B
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
>>> C = np.array([A, B], dtype=object)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: could not broadcast input array from shape (12,2) into shape (12)
It get an error. But when I do like this:
>>> A = np.zeros((20,2))
>>> B = np.zeros((12,))
>>> C = np.array([A, B], dtype=object)
>>> C
array([array([[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.],
[0., 0.]]),
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])],
dtype=object)
It doesn't complain.
Why? How do I store two arrays when they have dimensions like (12,2) and (12,)?

Making a 3D diagonal matrix in Python

I would like to create 3D diagonal matrices. I already succeded to create one with numpy routine numpy.fill_diagonal(numpy.zeros((N, N, N)), n), however it does not allow to choose the diagonal to fill.
In other words, I would like to find the 3D generalization of this numpy routine : https://numpy.org/doc/stable/reference/generated/numpy.diag.html. Thank you.
Well instead of using np.diag to fill a semi diagonal you can do it manually like this:
N = 4
arr = np.zeros((N, N))
i = np.arange(N-1)
arr[i,i+1] = 1
array([[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.],
[0., 0., 0., 0.]])
And it has the advantage to generalize to 3d arrays.
arr = np.zeros((N, N, N))
i = np.arange(N-1)
arr[i,i,i+1] = 1
array([[[0., 1., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 1.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])

Numpy - set first max value over multiple axes

I have a multidimensional array with the last two dimensions corresponding a "window". For each "window" in the array my goal is to set the first max value in the window to 1 and the rest of the values to 0. For example, for one window, we have this assignment:
[[0., 0., 0.], [[0., 0., 0.],
[0., 1., 1.], -> [0., 1., 0.],
[0., 1., 1.]], [0., 0., 0.]]
Now, i want to do this for all windows, where each window is on the last two dimensions, i.e. axis=(-1,-2). This is what I have tried so far:
# windows
x = np.array([[[[[[0., 0., 0.],
[0., 1., 1.],
[0., 1., 1.]],
[[0., 0., 0.],
[1., 1., 0.],
[1., 1., 0.]]],
[[[0., 1., 1.],
[0., 1., 1.],
[0., 1., 1.]],
[[1., 1., 0.],
[1., 1., 0.],
[1., 1., 0.]]],
[[[0., 1., 1.],
[0., 1., 1.],
[0., 1., 0.]],
[[1., 1., 0.],
[1., 1., 0.],
[1., 0., 1.]]]]]])
max_indices = np.argwhere(x == x.max()) # all indicies of max values in x
mask = np.zeros_like(x) # start of with everything set to 0
# I can set the first window by doing the following
mask[tuple(max_indices[0])] = 1.0
How can i do the same for all other windows? Preferably without looping.
My idea was to find unique values in max_indices where the last two dimensions are not taken into account, but i am not sure how to go about this.
EDIT
I have a case where x in the scenario above is taken from another
array using np.lib.stride_tricks.as_strided, which means that the strides will differ.
Here is the case:
# The image or whatever i want to modify
x = np.array([[[[0., 0., 0., 0.],
[0., 1., 1., 0.],
[0., 1., 1., 0.],
[0., 1., 1., 0.],
[0., 1., 0., 1.]]]])
# the windows of that image
x = np.lib.stride_tricks.as_strided(x, shape=(1, 1, 3, 2, 3, 3), strides=(160, 160, 32, 8, 32, 8))
Using the solution given by Felipe:
y = x[0][0] # Just unnesting it a bit
yr = y.reshape(-1, 9)
idx = yr.argmax(1)
y0 = np.zeros_like(yr)
np.put_along_axis(y0, idx[:, None], 1, axis=1)
y = y0.reshape(y.shape)
# plug it back
x[0][0] = y
x
array([[[[[[0., 0., 0.],
[0., 1., 0.],
[0., 1., 0.]],
[[0., 0., 0.],
[1., 0., 0.],
[1., 0., 0.]]],
[[[0., 1., 0.],
[0., 1., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[1., 0., 0.],
[0., 0., 0.]]],
[[[0., 1., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]]]]])
The shape is the same but with different strides in x and y it seems as if "plugging it back" causes x and y to not be identical, which I would expect.
Here's one way using np.put_along_axis (though this is really just a somewhat faster loop).
y = x[0][0] # Just unnesting it a bit
yr = y.reshape(-1, 9)
idx = yr.argmax(1)
y0 = np.zeros_like(yr)
np.put_along_axis(y0, idx[:, None], 1, axis=1)
y = y0.reshape(y.shape)
Output:
array([[[[0., 0., 0.],
[0., 1., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[1., 0., 0.],
[0., 0., 0.]]],
[[[0., 1., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]],
[[[0., 1., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]]])
EDIT
Not the brightest idea but what I meant is you could reassign it first to a copy of it and then get your strided view again, something like:
x0 = x.copy() # Get a normal view
# [ Run the previous snippet ]
x0[0][0] = y # Assign the modified version
# Then if you really want another strided view you can recreate it
x0 = x0.reshape(saved_x.shape) # Reshape it to the original version pre-stride
x = np.lib.stride_tricks.as_strided(x0, shape=(1, 1, 3, 2, 3, 3), strides=(160, 160, 32, 8, 32, 8))

How to get the dictionary output from a generator, which outputs an array with a dictionary for custom keras image generator

I have a custom made generator to output multiple values to predict against. I'm trying to get the values to correspond to a given image, without success. Here is my output:
e(array([[[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
...,
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]],
[[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
...,
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
...,
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]]], dtype=float16),
{'HourTime': array([0.3848, 0.2375], dtype=float16),
'MinTime': array([0.633, 0.862], dtype=float16),
'SecTime': array([0.967, 0.717], dtype=float16)})
My output comes from my generator here:
input_Size = 128
x,y,xrange,yrange = [136,150,47,47]
def ImGenA(directory, files_Loc, Hour, Min, Sec, batch_size):
while True:
batch_paths = imgId = np.random.choice(a = files_Loc.index, size=batch_size)
batch_input = []
batch_Hr = []
batch_Min = []
batch_Sec = []
for i in batch_paths:
img1 = cv2.imread(os.path.join(directory,files_Loc[i]))
img1 = ndimage.rotate(img1, 210)
img1 = cv2.resize (img1, (input_Size,input_Size))
batch_input+=[img1/255]
batch_Hr += [Hour[i]]
batch_Min += [Min[i]]
batch_Sec += [Sec[i]]
batch_x = np.array(batch_input, dtype='float16')
batch_y1 = np.array(batch_Hr, dtype='float16')
batch_y2 = np.array(batch_Min, dtype='float16')
batch_y3 = np.array(batch_Sec, dtype='float16')
yield( batch_x, {'HourTime' : batch_y1, 'MinTime': batch_y2, 'SecTime': batch_y3})
genA = ImGenA(directory=folder, files_Loc= train['ImageLoc'], Hour = train['HrPer'], Min = train['MinPer'], Sec = train['SecPer'],batch_size=2)
b=next(genA)
b[0][0] #provides image at position 0, but how do I find the Y output 'HourTime' at the same position?
I'm having difficulty extracting 'HourTime' from the saved output from a generator run. Sorry, I would assume it has been asked before, but I'm not sure how I can't find the answer.
It is simple, once you get it to work.
b[1]['HourTime'][0]
Provides the 'HourTime' from the dictionary for position 0.
IE. 0.3848

Categories

Resources