I have a tiled numpy array of shape (16, 32, 16, 16), that is each tile is 16x16 pixels in a grid 32 tiles wide and 16 high.
From here I want to reshape it to a 256 high x 512 wide 2D image, and I can't quite find the right incantation of splits, slices, and reshapes to get to what I want.
You can combine numpy's reshape and transpose to get this job done. I am not entirely sure which of the three "16"s belongs to the 32x16 repetition grid, but assuming it's the first one:
import numpy as np
data = np.random.random((16, 32, 16, 16))
# put number of repetitions next to respective dimension
transposed_data = np.transpose(data, (0, 2, 1, 3))
# concatenate repeated dimensions via reshape
reshaped_data = transposed_data.reshape((16 * 16, 32 * 16))
print(reshaped_data.shape)
Related
I am trying to randomly sample 30% of a NumPy array of shape (790, 64, 64, 1). The last dimension is the channel info for the image so essentially it's a 3D image. The intention is to generate 2D slices orthogonally across each dimension in a random way so as to get 30% of the total information of the original.
I looked at this question to understand how to randomly generate slices but I'm being unable to extend it to my use case.
So far I'm only able to generate the size of the data I would need.
dim1_len = 0.3 * img.shape[0]
dim2_len = 0.3 * img.shape[1]
dim3_len = 0.3 * img.shape[2]
Sorry if the question is a little broad.
First a few comments, you say you want to keep 30 % of the original information.
If you keep 30% of each axis you only end up with 0.3*0.3*0.3 = 0.027 (2.7%) of the information. Consider using 0.3 ^(1/3)as reduction factor.
The next thing is that you maybe want to preserve the spatial ordering of the randomly sampled indices, so maybe include a np.sort(...) to the question you linked.
Now to the main question, you can use np.meshgrid(*arrays, sparse=True, indexing='ij') to get
a list of arrays which can be used for broadcasting. This comes in handy for adding the necessary newaxis to the random indices.
import numpy as np
img = np.random.random((790, 64, 64, 1))
alpha = 0.3 ** (1/3)
shape_new = (np.array(img.shape[:-1]) * alpha).astype(int)
idx = [np.sort(np.random.choice(img.shape[i], shape_new[i], replace=False))
for i in range(3)]
# shapes: [(528,) (42,) (42,)]
idx_o = np.meshgrid(*idx, sparse=True, indexing='ij')
# shapes: [(528, 1, 1)
# (1, 42, 1)
# (1, 1, 42)]
img_new = img[tuple(idx_o)]
# shape: (528, 42, 42, 1)
I have a numpy array of images in that shape:
(50000, 32, 32, 3)
50000 is the number of images
32, 32 are the height and width
3 are the RGB values with a range of 0-1
I would like to convert it to a 2D shape of:
(50000, 1024)
Here I would have 50000 images represented in one row,
the RGB value would be converted to let's say an hexadecimal value
I've went through a lot of conversion processes into stack overflow and I've found some.
I know that if my array was a 3D array with an already converted value I could easily use reshape()function to convert it to 2D.
Now what I'm searching is the easiest way to convert RGB values and reshape my array
Would this be possible in 1 or two lines or should I use an external function?
First convert the RGB values in the last dimension to the HEX value using whatever function you like. This SO answer may help.
Reshape then works on any number of dimensions:
import numpy as np
def rgb2hex(r, g, b):
return '#%02x%02x%02x' % (r, g, b)
vfunc = np.vectorize(rgb2hex)
a = (np.random.uniform(0,1,(10,5,5,3))*255).astype(int)
c = vfunc(a[:,:,:,0], a[:,:,:,1], a[:,:,:,2])
c.reshape((10,25))
In order to do so, you firstly need to reshape the ndarray (np.reshape):
a = np.random.randint(1,10,(500, 32, 32, 3))
a_r = np.reshape(a, (500, 1024, 3))
print(a_r.shape)
# (500, 1024, 3)
Now, in order to convert the RGB values along the last dimension to hexadecimal representation as you suggest, you could define a function that returns a hexadecimal representation of the three values with a simple string formatting:
def rgb_to_hex(x):
return '#{:02X}{:02X}{:02X}'.format(*rgb.reshape(3))
In order to apply the conversion along all rows in the last axis, you can use np.apply_along_axis:
a_new = np.apply_along_axis(rgb2hex, axis=-1, arr=a_r).shape
print(a_new.shape)
# (500, 1024)
The following combines the RGB values into a single value
x=np.zeros((100,32,32,3))
x[:,:,:,0] = np.trunc(x[:,:,:,0]) + np.trunc(x[:,:,:,1] *256) + np.trunc(x[:,:,:,2] *65535)
y=x[:,:,:,0]
print(y.shape)
The resulting shape of y: (100, 32, 32)
Next you can use the reshape function on y.
I'm working on an array shaped as follows
(64, 1, 64, 64)
This is in fact one grayscale image that was split into 64 patches, each patch with 64*64px.
Now I need to rebuild it into a 512*512px image.
I've tried using
np.reshape(arr, (512, 512))
but of course the resulting image is not as expected.
How do I resolve this?
It depends on how your patches are arranged. But the first thing you could try is
image.reshape(8, 8, 64, 64).swapaxes(1, 2).reshape(512, 512)
This is assuming that the original zeroth dimension lists the patches row by row, i.e. 0-7 are the first row of patches from left to right, 8-15 the second row and so on.
The first reshape reestablishes that arrangement, after it choosing index i, j for axes 0 and 1 addresses the j+1st patch in the i+1st row.
Now comes the interesting bit: When merging axes by reshape:
only adjacent dimensions can be combined
all but the rightmost axis in each block will be dispersed
Since we want to keep each patch together we have to rearrange in such a way that the current axes 2 and 3 become the rightmost members of blocks. That is what the swapaxes does.
By now the shape is (8, 64, 8, 64) and axes 1 and 3 are the within-patch coordinates. Combining two pairs ( 8, 64 -> 512 8, 64 -> 512 ) is all that's left to do.
I have a numpy array of shape (2500, 16, 32, 24), and I want to make it into a ( something, 24) array, but I don't want numpy to shuffle my values. The 32 x 24 dimension at the end represent images and I want the corresponding elements to be consistent. Any ideas?
EDIT: Ok , I wasn't clear enough. (something, 24) = (1280000, 24).
Use arr.reshape(-1,arr.shape[-1]) or if you know it will be 24 arr.reshape(-1,24)
I am putting data in numpy arrays for comparisons. They way the data is stored sometimes the dimensions are out of order. For example if the first array has the shape (10, 20, 30, 40), sometimes the second array will have the shape (10, 20, 40, 30). We can assume that the lengths of the dimensions will be unique.
Is there an easy way to convert the shape of the second array to the shape of the first without knowing the number of dimensions or the length of the dimensions beforehand? I think I can do it with a long series of elif statements and transpose operations, but I'm hoping there is a cleaner method available.
Use shape.index to find where each axis needs to be, then use transpose to re-order the axes:
import numpy as np
A = np.ones((10, 20, 40, 30))
B = np.ones((10, 20, 30, 40))
new_order = [A.shape.index(i) for i in B.shape]
B = B.transpose(new_order)