I've got a video sequence, saved in 3-dimensional numpy array.
import numpy as np
noise_50 = np.ones((422, 480, 640), dtype=np.float)
I want to remove frames 0:25, 231:272, 372:421 and keep frames 26:231 and 273:371.
Is it possible to do with slice objects in one operation?
I've seen the question Python: shorter syntax for slices with gaps? but it considers only 1-dimensional arrays.
If I try s_ from index tricks, as suggested there, it broadcasts second slice to the next axis and crops frames
retain = np.s_[26:230, 273:371]
n_50 = noise_50[retain]
n_50.shape
>>> (204, 98, 640)
^^^ ^^ - should be 303, 480
I also cannot create sum of slices
retain = slice(26, 230) + slice(273, 371)
> TypeError: unsupported operand type(s) for +: 'slice' and 'slice'
Hey there is sort of a way of doing it in one operation. Numpy allows you to pass in a list/array of indices to a dimension of the slice. So all you need to do is join some ranges that you want to keep and pass that into the first dim. Like in the example below that outputs New shape (303, 480, 640)
import numpy as np
def mslice(data, ranges):
d = np.concatenate([np.arange(*r, step=1) for r in ranges])
return data[d, :, :]
# some dummy frame data
frames = np.zeros((422, 480, 640))
keep = mslice(frames, [(26, 231), (273, 371)])
print('New shape', keep.shape)
Related
I created an array with size (256, 144, 3).
empty_windows = np.empty((256, 144, 3))
Then I want to append new elements into the array with:
for i in range(256):
for j in range(144):
empty_windows[i, j] = np.append(empty_windows[i, j], np.asarray(some_new_array)).reshape(3, )
But it doesnt work as I get the error msg:
ValueError: cannot reshape array of size 6 into shape (3,)
Is there a way of doing it? Thank you.
I hope, it will help you understanding concatenate 3dim array
import numpy as np
empty_windows = np.empty((256, 144, 3))
random_arr = np.random.randint(0, 100, size=(256, 144, 3)) # it's dimension should be same
np.concatenate([empty_windows, random_arr], axis=2) # it can concatenate into an array axis=2 defines 3rd dimension
np.empty and np.append are dangerous functions to use. They are not clones of the the empty list [] and list.append.
empty_windows = np.empty((256, 144, 3))
has made a (256,144,3) shape array with float values - they are unpredictable, but more than likely not what you want. Look at that array, or a smaller example to see for yourself. Also read, and if necessary reread, the np.empty docs. np.zeros is safer.
With scalar i,j,
empty_windows[i, j]
is a (3,) shape array, or slot.
When you np.append it with another (3,) shape, the result is a (6,) shape, with the first 3 value being those "random" values originally in empty_window. The error tells you quite clearly that it can't put a (6,) shape array into a slot that only holds (3,).
Your goal isn't clear, but you can't grow a (n,m,3) shape array to (n,m,6) by doing this kind of "row" by "row" append.
You can set the "row" with new values, as in:
empty_windows[i, j] = np.asarray(some_new_array)).reshape(3, )
I have a matrix and I am obtaining a 2 channel matrix with images having size 256x120.
Now, I need to store several images so I need to reshape my matrix to (No.ofimages,256,120,2).
I tried to use reshape and then append:
But I am getting a TypeError: 'builtin_function_or_method' object is not subscriptable when using reshape
Any ideas on how I can solve it?
Based on my current understanding of your issue:
import numpy as np
img = np.random.random((112,112,2))
print(img.shape)
result = np.empty((0, 112, 112, 2)) # first axis is zero, for adding images along it
for i in range(100): # replace this loop with something that reads in the images
result = np.append(result, img[np.newaxis, ...], axis=0) # add a new axis to each image and append them to result
print(result.shape)
Will produce:
(112, 112, 2)
(100, 112, 112, 2)
To access the images stored in the result variable, simply use indexing:
print(result[1].shape) # e.g., access the second image
Will produce:
(112, 112, 2)
I'm currently learning about broadcasting in Numpy and in the book I'm reading (Python for Data Analysis by Wes McKinney the author has mentioned the following example to "demean" a two-dimensional array:
import numpy as np
arr = np.random.randn(4, 3)
print(arr.mean(0))
demeaned = arr - arr.mean(0)
print(demeaned)
print(demeand.mean(0))
Which effectively causes the array demeaned to have a mean of 0.
I had the idea to apply this to an image-like, three-dimensional array:
import numpy as np
arr = np.random.randint(0, 256, (400,400,3))
demeaned = arr - arr.mean(2)
Which of course failed, because according to the broadcasting rule, the trailing dimensions have to match, and that's not the case here:
print(arr.shape) # (400, 400, 3)
print(arr.mean(2).shape) # (400, 400)
Now, i have gotten it to work mostly, by substracting the mean from every single index in the third dimension of the array:
demeaned = np.ones(arr.shape)
for i in range(3):
demeaned[...,i] = arr[...,i] - means
print(demeaned.mean(0))
At this point, the returned values are very close to zero and i think, that's a precision error. Am i actually right with this thought or is there another caveat, that i missed?
Also, this doesn't seam to be the cleanest, most 'numpy'-way to achieve what i wanted to achieve. Is there a function or a principle that i can make use of to improve the code?
As of numpy version 1.7.0, np.mean, and several other functions, accept a tuple in their axis parameter. This means that you can perform the operation on the planes of the image all at once:
m = arr.mean(axis=(0, 1))
This mean will have shape (3,), with one element for each plane of the image.
If you want to subtract the means of each pixel individually, you have to remember that broadcasting aligns shape tuples on the right edge. That means that you need to insert an extra dimension:
n = arr.mean(axis=2)
n = n.reshape(*n.shape, 1)
Or
n = arr.mean(axis=2)[..., None]
Try np.apply_along_axis().
np.apply_along_axis(lambda x: x - np.mean(x), 2, arr)
Output: you get the array of the same shape where each cell is demeaned in the dimension you want (the second parameter, here it is 2).
I have a ndarray of shape (68, 64, 64) called 'prediction'. These dimensions correspond to image_number, height, width. For each image, I have a tuple of length two that contains coordinates that corresponds to a particular location in each 64x64 image, for example (12, 45). I can stack these coordinates into another Numpy ndarray of shape (68,2) called 'locations'.
How can I construct a slice object or construct the necessary advanced indexing indices to access these locations without using a loop? Looking for help on the syntax. Using pure Numpy matrixes without loops is the goal.
Working loop structure
Import numpy as np
# example code with just ones...The real arrays have 'real' data.
prediction = np.ones((68,64,64), dtype='float32')
locations = np.ones((68,2), dtype='uint32')
selected_location_values = np.empty(prediction.shape[0], dtype='float32')
for index, (image, coordinates) in enumerate(zip(prediction, locations)):
selected_locations_values[index] = image[coordinates]
Desired approach
selected_location_values = np.empty(prediction.shape[0], dtype='float32')
correct_indexing = some_function_here(locations). # ?????
selected_locations_values = predictions[correct_indexing]
A straightforward indexing should work:
img = np.arange(locations.shape[0])
r = locations[:, 0]
c = locations[:, 1]
selected_locations_values = predictions[img, r, c]
Fancy indexing works by selecting elements of the indexed array that correspond to the shape of the broadcasted indices. In this case, the indices are quite straightforward. You just need the range to tell you what image each location corresponds to.
I have 4554 images in my numpy array X_train with the shape of the array as follows.
print(np.shape(X_train))
(4554,) # TOtal numbe of images
X_train[0].shape
(120, 120, 4) # Each image is 120x120 with 4 channels.
Now I want to reshape the array into (4554, 120, 120, 4), so that when I print
print(np.shape(X_train)
It gives me the shape (4554, 120, 120, 4) instead of (4554,).
I tried the following reshape method but it gives me error.
X_train=X_train.reshape((X_train.shape[0],X_train[0].shape))
Error: TypeError: 'tuple' object cannot be interpreted as an integer
You're looking for the numpy.stack() method.
If you have a list of 3d matrices, you can make a 4d matrix like so:
numpy.stack(your_list_of_training_data, axis=0)
See the documentation here for an explanation: https://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.stack.html
To convert 2D array to 4D, try to flat 2D array first and then reshape as below , hope it works.
num_images = 4554
X_train_flat = [img.flatten() for img in X_train]
X_train_flat = np.array(X_train_flat)
X_train = X_train_flat.reshape(num_images, 120, 120, 4)