Unexpected result from numpy random.shuffle - python

I am using numpy.random.shuffle to scramble an binary array (code below) but the output does not appear very random. I would expect a random assortment of dots but the resulting array appears to be a semi-regular pattern of dashes. What is going on here?
img = PIL.Image.open(image_path)
array = numpy.array(img)
# threshold image etc
outim=PIL.Image.fromarray(array)
outim.show() # generates left image (below)
numpy.random.shuffle(array)
outim=PIL.Image.fromarray(array)
outim.show() # generates right image (below)

You have shuffled the rows but not the columns. numpy.random.shuffle reorders its input along the first dimension only.
To shuffle the entire thing, try
shape = array.shape
array = array.flatten()
numpy.random.shuffle(array)
array = array.reshape(shape)

Related

Conditional averaged of numpy array based on a different

I have a sequence of N images with some shape (N, x,y). I also have corresponding times for each image, which is just a 1D array of length N.
Some of these times are duplicates, so I want to average the images at the same time steps so that I have a single (x,y) image for each time. I am curious what the best pythonic way for this would be?
Essentially just groupby("time").agg("mean"), but for 2D arrays.
If stick to groupby() paradigm, I would suggest the following:
import numpy as np
import pandas as pd
# the number of 512x512 gray-scale images
N = 200
# the iterator function that generates random images with associated random time points
# the images are numpy 2D arrays
def get_image():
yield [ np.random.randint(24*60*60), np.random.randint(256, size=(512, 512))]
# We generate the list of random images with associated random time points
my_images = [next(get_image()) for _ in range(N)]
df = pd.DataFrame(my_images)
df.columns = ['time_point', 'image']
df = df.sort_values('time_point').reset_index(drop=True)
# making at least some images have same time point as others
df.iloc[range(0,N,5),0] = df.iloc[range(1,N-1,5),0].values
#finally our groupby
result = df.groupby('time_point').mean()
# convert pixels back from floats to integers
result.loc['image'] = result['image'].apply(np.int64)
print(result)

is there any way to initialize numpy array which will contain certain number of element and have shape of (200,200,3)

I want to make a function that takes a list of resized images (size of image is (200,200)) and convert each picture one by one in the form of numpy array. so in the end i will have main numpy array which contain all the 20 images in the form of numpy array. And in the in the end this function will return numpay array of shape (200,200,3) which contain all pics.
What I have done so far is this:
def converttonumpyarray(list_of_resized_images):
for image in list_of_resized_images:
array1 = np.array(image).reshape(200,200,3)
for img in list_of_resized_images:
array2 = np.array(image).reshape(200,200,3)
array1 = np.concatenate((array1,array2))
break
return array1
but reshape function is generating following error:
ValueError: cannot reshape array of size 90000 into shape (200,200,3)
Kindly, let me know if there is any other way to do this working. Thank you

How would you reshape a collection of images from numpy arrays into one big image?

I'm having some trouble reshaping a 4D numpy array to a 2D numpy array. Currently the numpy array is follows, (35280L, 1L, 32L, 32L). The format is number of images, channel, width, height. Basically, I have 35280 image blocks that are 32x32 and I want to combine the image blocks (keeping the indices) to create one big image.
Reshaping is not sufficient, you must carefully rearrange your data with swapaxes.
Sample data :
dims=nbim,_,h,w=np.array([6,1,7,6])
data=arange(dims.prod()).reshape(dims)%256
The images :
figure()
for i in range(nbim):
subplot(1,nbim,i+1)
imshow(data[i,0],vmin=0,vmax=255)
and the big image :
#number of images in each dim :
nh = 2 # a choice
nw=nbim // nh
bigim=data.reshape(nh,nw,h,w).swapaxes(1,2).reshape(nh*h,nw*w)
figure()
imshow(bigim)
You have an array like this:
images = np.random.randint(0,256,(35280, 1, 32, 32))
The first thing you need is to figure out (somehow) what the width of the final image is supposed to be. Let's say for this example that it's (441 * 32, 80 * 32).
Then you can do:
image = images.swapaxes(0,2).reshape((441 * 32, -1))
This gives you almost what you need, except the rows are interleaved, so you have:
AAABBBCCC
DDDEEEFFF
GGGHHHIII
AAABBBCCC
DDDEEEFFF
GGGHHHIII
You can then use "fancy indexing" to rearrange the rows:
image[np.array([0,3,1,4,2,5])]
Now you have:
AAABBBCCC
AAABBBCCC
DDDEEEFFF
DDDEEEFFF
GGGHHHIII
GGGHHHIII
I will leave as an exercise the part where you generate the fancy indexing sequence.

List of arrays containing tuples(?)

I've been running into a TypeError: list indices must be integers, not tuple. However, I can't figure out how to fix it, as I'm apparently misunderstanding where the tuple is (wasn't even aware there would be one from what I understand). Shouldn't my index and the values that I'm passing in all be integers?
def videoVolume(images):
""" Create a video volume from the image list.
Note: Simple function to convert a list to a 4D numpy array.
Args:
images (list): A list of frames. Each element of the list contains a
numpy array of a colored image. You may assume that each
frame has the same shape, (rows, cols, 3).
Returns:
output (numpy.ndarray): A 4D numpy array. This array should have
dimensions (num_frames, rows, cols, 3) and
dtype np.uint8.
"""
output = np.zeros((len(images), images[0].shape[0], images[0].shape[1],
images[0].shape[2]), dtype=np.uint8)
# WRITE YOUR CODE HERE.
for x in range(len(images)):
output[:,:,:,:] = [x, images[x,:,3], images[:,x,3], 3]
# END OF FUNCTION.
return output
The tuple referred to in the error message is the x,:,3 in the index here:
images[x,:,3]
The reason this is happening is that images is passed in as a list of frames (each a 3d numpy array), but you are trying to access it as though it is itself a numpy array. (Try doing lst = [1, 2, 3]; lst[:,:] and you'll see you get the same error message).
Instead, you meant to access it as something like images[x][:,:,:], for instance
for x in range(len(images)):
output[x,:,:,:] = images[x][:,:,:]

scipy -- how to insert an array of zeros into another array with different dimensions

If i have an array:
myzeros=scipy.zeros((c*pos,c*pos)) , c=0.1 , pos=100
and an array:
grid=scipy.ones((pos,pos))
How can i insert the zeros into the grid in random positions? The problem is with the dimensions.
I know that in 1d you can do:
myzeros=sc.zeros(c*pos) # array full of (zeros)
grid=sc.ones(pos) # grid full of available positions(ones)
dist=sc.random.permutation(pos)[:c*pos] # distribute c*pos zeros in random
# positions
grid[dist]=myzeros
I tried something similar but it doesn't work. I tried also: myzeros=sc.zeros(c*pos), but it still does not work.
There are several ways, but the easiest seems to be to first convert the 2D grid into a 1D grid and proceed as in the 1D case, then convert back to 2D:
c = 0.1
pos = 100
myzeros=scipy.zeros((c*pos,c*pos))
myzeros1D = myzeros.ravel()
grid=scipy.ones((pos,pos))
grid1D = grid.ravel()
dist=sc.random.permutation(pos*pos)[:c*pos*c*pos]
grid1D[dist]=myzeros1D
myzeros = myzeros1D.reshape((c*pos,c*pos))
grid = grid1D.reshape((pos, pos))
EDIT: to answer your comment: if you only want a part of the myzeros to go into the grid array, you have to make the dist array smaller. Example:
dist = scipy.random.permutation(pos*pos)[:c*pos]
grid1D[dist] = myzeros1D[:c*pos]
And I hope you are aware, that this last line can be written as
grid1D[dist] = 0
if you really only want to set those elements to a single instead of using the elements from another array.

Categories

Resources