How to use numpy to concatenate arrays in the following manner? - python

I have a numpy array of dimension:
(1, 1, 188, 621, 32) corresponding to the (batch, depth, height, width, features) dimensions
And I want to convert this array to have the shape (1, 48, 188, 621, 32), i.e., have a depth of 48, where the rest of the arrays in the depth dimension will be the array that's (height, width + x), for x = 1 to x = 47, distance away from the current one?
In case of overflow, the array can be full of zeros.

If you have 48 arrays of shape (1, 1, 188, 621, 32) then just
bigarr = np.concatenate([arr1, arr2, ... , arr48], axis=1)
will produce the (1,48, 188, 621, 32). The concatenation part is trivial.
Now you just need to figure out how to generate the 47 added arrays from the first (at least that seems to be what you are trying to do).

Related

Subtract 2D array from each pixel of a 3D image and get a 4D array

I have a 2D array of shape (10, 3) and an image represented as a 3D array of shape (480, 640, 3). I'd like to perform a difference between each pixel and each element of the 2D array, to get a final result of shape (10, 480, 640, 3).
For now, my code looks like this:
arr_2d = np.random.rand(10, 3)
arr_3d = np.random.rand(480, 640, 3)
res = np.ones_like(arr_3d)
res = np.tile(res, (10, 1, 1, 1))
for i in range(10):
res[i] = arr_3d - arr_2d[i]
My question is if there's a way to do this without the for loop, only using numpy operations.
You can try broadcasting with np.array like this
arr_2d = arr_2d.reshape(-1,1,1,3)
arr_3d = arr_3d.reshape((-1,*arr_3d.shape))
res = arr_3d - arr_2d
This should give the same result as your original code

combining multi numpy arrays (images) in one array (image) in python

I have some numpy arrays which its elements are pixels of 28*28 images like this:
25 of these arrays are in one array in shape of (25,28,28) or (5,5,28,28). Is there any efficient way to stack them to have one image: 5*5 of 28*28 images.
I tried np.reshape to (140,140) array and plt.imgshow. But the output was a messed image.
"I tried np.reshape to (140,140)..." That will work if you first transpose the input appropriately.
Suppose the input x has shape (5, 5, 28, 28). To get the array y with shape (140, 140) that contains the images arranged the way you want, you can do:
xshp = x.shp
y = x.transpose((0, 2, 1, 3)).reshape((xshp[0]*xshp[2], xshp[1]*xshp[3]))
If x always has shape (5, 5, 28, 28), you can hardcode the constant 140:
y = x.transpose((0, 2, 1, 3)).reshape((140, 140))
For example, here I create x with shape (5, 5, 28, 28) where each 28x28 image is a constant. The constants are chosen randomly. The tranposed, reshaped array y is plotted, and you can see that all the constant blocks are arranged correctly.
In [148]: rng = np.random.default_rng()
In [149]: x = np.repeat(rng.integers(0, 256, size=(5, 5)), 28*28, axis=-1).reshape((5, 5, 28, 28))
In [150]: y = x.transpose((0, 2, 1, 3)).reshape((140, 140))
In [151]: imshow(y)

Stacking numpy arrays with padding

I have a list of 32 numpy arrays, each of which has shape (n, 108, 108, 2), where n is different in each array. I want to stack all of them to create a numpy array of shape (32, m, 108, 108, 2), where m is the maximum among the ns, and the shorter arrays are padded with zeros.
How do I do this?
I asked something similar yesterday, but the answers there seem to break when using deep arrays like in my case.
Concretely, I went with this solution in the end, which produced the cleanest code:
data = np.column_stack(zip_longest(*data, fillvalue=0))
But now it is throwing this error:
ValueError: setting an array element with a sequence.
I have found a godly answer in this webpage.
The pad_sequences function is exactly what I needed.
from tensorflow.python.keras.preprocessing.sequence import pad_sequences
result = pad_sequences(imgs, padding='post')
In my case I needed to stack images with different width and padded with zeros to the left side.
for me this works well:
np.random.seed(42)
image_batch = []
for i in np.random.randint(50,500,size=10):
image_batch.append(np.random.randn(32,i))
for im in image_batch:
print(im.shape)
output: (32, 152)
(32, 485)
(32, 398)
(32, 320)
(32, 156)
(32, 121)
(32, 238)
(32, 70)
(32, 152)
(32, 171)
def stack_images_rows_with_pad(list_of_images):
func = lambda x: np.array(list(zip_longest(*x, fillvalue=0))) # applied row wise
return np.array(list(map(func, zip(*list_of_images)))).transpose(2,0,1)
res = stack_images_rows_with_pad(image_batch)
for im in rez:
print(im.shape)
output: (32, 485)
(32, 485)
(32, 485)
(32, 485)
(32, 485)
(32, 485)
(32, 485)
(32, 485)
(32, 485)
(32, 485)
Try this:
# Create matrices with random first axis length.
depth = np.random.randint(3,20,size=32)
l = []
lmax = 0
for i in depth:
l.append(np.ones((i,10,10,2)))
lmax = i if i > lmax else lmax
# Join the matrices:
new_l = []
for m in l:
new_l.append(np.vstack([m, np.zeros((lmax-m.shape[0], 10, 10, 2))]))
master = np.stack(new_l, axis=0)
master.shape
>>> (32, 19, 10, 10, 2)
I find np.pad almost impossible to work with on higher dimensional matrix - luckily, what you asked was simple, where only one of the dimension will have to extended, such that it's easy to use np.vstack to stack a zeros array that make it conform to a new shape.
A = np.ones((4,3))
border_top_bottom = np.zeros((A.shape[1])).reshape(1,A.shape[1])
print(np.vstack([border_top_bottom,A,border_top_bottom]))
temp = np.vstack([border_top_bottom,A,border_top_bottom])
border_right_left = np.zeros((temp.shape[0])).reshape(temp.shape[0],1)
print(np.hstack([np.hstack([border_right_left,temp,border_right_left])]))

np.reshape returns error 'ValueError: total size of new array must be unchanged'

The array that I'm trying to enter has length 240.
I've tried:
r = np.reshape(array, (3, 80))
because I read somewhere else on this site that the rows and columns entered into reshape have to multiply to the array length.
However, I'm still getting the error:
ValueError: total size of new array must be unchanged
You said you have additional dimensions in your array so you need to keep them:
>>> arr = np.random.random((240, 215, 3))
>>> reshaped = np.reshape(arr, (3, 80, arr.shape[1], arr.shape[2]))
>>> reshaped.shape
(3, 80, 215, 3)
or using unpacking to avoid hardcoding the dimensions:
>>> reshaped = np.reshape(arr, (3, 80, *arr.shape[1:]))
(3, 80, 215, 3)
If you want the last dimension to be ravelled then you could also use -1 as last axis in your reshape:
>>> reshaped_ravel = np.reshape(arr, (3, 80, -1))
>>> reshaped_ravel.shape
(3, 80, 645)

Finding the element in one array corresponding to the maximum value in another

How can I align the 4d z array and the 4d QCLOUD array and to then find out the z value of when QCLOUD max occurs?
print(z.shape)
print(qcloud.shape)
out: (6, 100, 128, 128)
(6, 99, 128, 128)
Ignoring the fact that (np.array(z.shape) > np.array(qcloud.shape)).any(), you want argmax:
idx = np.argmax(qcloud)
result = z[tuple(idx)]

Categories