how to make each element in an array another array - python

Hi I came across a problem. I have a numpy array with size (256, 144). Each element is 0 in this array. Now I want to make each element in the array to be [0, 0, 0]. Is there a way of doing this?
The code is:
empty_windows = np.zeros(256, 144)
for i in range(256*144):
empty_windows[i] = [0,0,0]
This method doesnt work as it returns an error message "ValueError: setting an array element with a sequence."
Is there a way of doing this? Thank you very much.

If you don't need to do anything with empty_windows while it has size (256, 144), you can simply create it with the proper size:
empty_windows = np.zeros((256, 144, 3))

You could try creating a second numpy array with the required shape, which in your case is (256,144,3) , iterating over it and correcting the elements as required.
empty_windows = np.zeros((256, 144))
x = np.random.rand(256,144,3)
for i in range(256):
for j in range(144):
x[i][j] = [empty_windows[i][j] for _ in range(3)]
empty_windows = x
You may also want to brush up on your understanding of numpy arrays, as the commenter mentioned, particularly how to initialize and iterate over them.

Related

how to add new elements to a numpy array

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, )

What is the correct way to reshape images after raveling?

At the moment I'm trying to np.ravel() my images so I can use np.append() freely, instead of using np.vstack() which many people here say it's not very fast given the loading/unloading things in memory and I worry it might slow my code down.
My idea was to just flatten the images, append them all and then use np.reshape(appended_images, [512,512,3,-1]) to create the tensor. The tensor is created all right, but upon checkup, the images aren't getting displayed, probably because one of these operations is not working the way I think it should be working.
Checking the final array im_stacked[:,:,:,0] with matplotlib returns a blank image, with a warning of values out of range. Upon inspection of only one channel of the image im_stacked[:,:,0,0] I'm faced with this:
This is just the image repeated over and over. Where is my mistake? Why is there some swapping occurring? Reshaping a single raveled image works fine.
Edit: Minimal code added
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
#Image Loading, please use a 512x512x3 image
path = "./path/to/image.png"
im = cv.imread(path)
#Flattening the image
im_raveled = np.ravel(im)
#Starting with an empty array
im_stacked = np.array([])
#For the sake of simplicity this code is just repeated three times
im_stacked = np.append(im_stacked, im_raveled)
im_stacked = np.append(im_stacked, im_raveled)
im_stacked = np.append(im_stacked, im_raveled)
#Using a 515x512x3 image, reshaping the stacked array
im_reshaped = np.reshape(im_stacked, [512,512,3,-1])
#Plotting the images after reshaping
plt.figure()
plt.subplot(1,2,1)
#Plot only the first channel of the first image
plt.imshow(im_reshaped[:,:,0,0])
plt.subplot(1,2,2)
#Plot all channels of the first image
plt.imshow(im_reshaped[:,:,:,0])
plt.show()
Make a sample 3d array:
In [25]: image = np.random.randint(0,256,(512,512,3))
The best way:
In [26]: alist = []
In [27]: for i in range(5):
...: alist.append(image)
...:
It's easy to make an array from such list:
In [28]: np.array(alist).shape
Out[28]: (5, 512, 512, 3)
If you must join them on a new last dimension, use np.stack:
In [29]: np.stack(alist,-1).shape
Out[29]: (512, 512, 3, 5)
np.stack, np.vstack, and even np.append are all covers for np.concatenate. I hate np.append, since it leads too many naive users up the wrong path. It is not an list append clone.
If you must use repeated concatenates do something like:
In [30]: arr = np.zeros((0,512,512,3),image.dtype)
In [31]: arr = np.concatenate([arr,image], axis=0)
Traceback (most recent call last):
File "<ipython-input-31-1fc945fd1c90>", line 1, in <module>
arr = np.concatenate([arr,image], axis=0)
File "<__array_function__ internals>", line 5, in concatenate
ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 4 dimension(s) and the array at index 1 has 3 dimension(s)
oops, even with experience I have troubles getting that started.
In [32]: arr = np.concatenate([arr,image[None,...]], axis=0)
In [33]: arr.shape
Out[33]: (1, 512, 512, 3)
In [34]: arr = np.concatenate([arr,image[None,...]], axis=0)
In [35]: arr.shape
Out[35]: (2, 512, 512, 3)
Repeated concatenate is slow. concatenate takes a whole list of arrays, and should be used as such. Don't try to replicate list code in lists!
List append is easy because there's an obvious "empty" list, and you can efficiently add references to it. Arrays don't have an equivalent "empty" array. Dimensions matter, right from the start. I had to start with a (0,512,512,3) shape. If you don't know the needed dimensions, then don't take this approach.
As for your title question, this might work:
im_reshaped = np.reshape(im_stacked, [-1,512,512,3])
With the repeated np.append, you joined the ravelled arrays end to end, [(786432,),(786432,),(786432,),...]. Effectively the new dimension is a leading one, not a trailing one. It's a crude way of performing the list append and array build that I started with.

Advanced Indexing in 3 Dimensional Numpy ndarray In Python

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.

Iteratively appending ndarray arrays using numpy in Python

I am trying to figure out how to iteratively append 2D arrays to generate a singular larger array. On each iteration a 16x200 ndarray is generated as seen below:
For each iteration a new 16x200 array is generated, I would like to 'append' this to the previously generated array for a total of N iterations. For example for two iterations the first generated array would be 16x200 and for the second iteration the newly generated 16x200 array would be appended to the first creating a 16x400 sized array.
train = np.array([])
for i in [1, 2, 1, 2]:
spike_count = [0, 0, 0, 0]
img = cv2.imread("images/" + str(i) + ".png", 0) # Read the associated image to be classified
k = np.array(temporallyEncode(img, 200, 4))
# Somehow append k to train on each iteration
In the case of the above embedded code the loop iterates 4 times so the final train array is expected to be 16x800 in size. Any help would be greatly appreciated, I have drawn a blank on how to successfully accomplish this. The code below is a general case:
import numpy as np
totalArray = np.array([])
for i in range(1,3):
arrayToAppend = totalArray = np.zeros((4, 200))
# Append arrayToAppend to totalArray somehow
While it is possible to perform a concatenate (or one of the 'stack' variants) at each iteration, it is generally faster to accumulate the arrays in a list, and perform the concatenate once. List append is simpler and faster.
alist = []
for i in range(0,3):
arrayToAppend = totalArray = np.zeros((4, 200))
alist.append(arrayToAppend)
arr = np.concatenate(alist, axis=1) # to get (4,600)
# hstack does the same thing
# vstack is the same, but with axis=0 # (12,200)
# stack creates new dimension, # (3,4,200), (4,3,200) etc
Try using numpy hstack. From the documention, hstack takes a sequence of arrays and stack them horizontally to make a single array.
For example:
import numpy as np
x = np.zeros((16, 200))
y = x.copy()
for i in xrange(5):
y = np.hstack([y, x])
print y.shape
Gives:
(16, 400)
(16, 600)
(16, 800)
(16, 1000)
(16, 1200)

Insert A numpy multi dimensional array inside another 1d array

I already have an array with shape (1, 224, 224), a single channel image. I want to change that to (1, 1, 224, 224). I have been trying
newarr.shape
#(1,224,224)
arr = np.array([])
np.append(arr, newarr, 1)
I always get this
IndexError: axis 1 out of bounds [0, 1). If i remove the axis as 0 , then the array gets flattened . What am I doing wrong ?
A dimension of 1 is arbitrary, so it sounds like you want to simply reshape the array. This can accomplished by:
newarr.shape = (1, 1, 244, 244)
or
newarr = newarr[None]
The only way to do an insert into a higher dimensional array is
bigger_arr = np.zeros((1, 1, 224, 224))
bigger_arr[0,...] = arr
In other words, make a target array of the right size, and assign values.
np.append is a booby trap. Avoid it.
Occasionally that's a useful way of thinking of this. But it's simpler, and quicker, to think of this as a reshape problem.
bigger_arr = arr.reshape(1,1,224,224)
bigger_arr = arr[np.newaxis,...]
arr.shape = (1,1,224,224) # a picky inplace change
bigger_arr = np.expand_dims(arr, 0)
This last one does
a.reshape(shape[:axis] + (1,) + a.shape[axis:])
which gives an idea of how to deal with dimensions programmatically.

Categories