How to save 4d numpy array to images - python

I want to create an image date_set which includes 176 small images (128*128*3) from one big image (1408, 2048, 3).
I do the following thing:
step 1.
Load the big image and convert it to numpy array. (1408, 2048, 3) 3d array
step 2.
cut it into 176 pieces: (176, 128, 128, 3) 4d array
step 3.
I don't know how to save 176 images from 4d array in this step. Does anyone could help me to solve this problem?
Thanks very much!
from astropy.io import fits
from astropy.utils.data import download_file
image_file = download_file('https://data.sdss.org/sas/dr12/boss/photoObj/frames/301/1035/3/frame-irg-001035-3-0011.jpg', cache=True )
image = imread(image_file)
def blockshaped(arr, nrows, ncols, c):
"""
Return an array of shape (n, nrows, ncols) where
n * nrows * ncols = arr.size
If arr is a 2D array, the returned array should look like n subblocks with
each subblock preserving the "physical" layout of arr.
"""
h, w = arr.shape[:2]
return (arr.reshape(h//nrows, nrows, -1, ncols, c)
.swapaxes(1,2)
.reshape(-1, nrows, ncols, c))
a= image[:1408, :]
b= blockshaped(a, 128, 128, 3)
b.shape
b.shape = (176, 128, 128, 3)

Here's a possible way to do it.
import numpy as np
import scipy.misc
images = np.zeros((176,128,128,3))
for i in range(len(images)):
scipy.misc.imsave('date_set_' + str(i) + '.jpg', images[i,:,:,:])

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

How to stack numpy array along an axis

I have two numpy arrays, one with shape let's say (10, 5, 200), and another one with the shape (1, 200), how can I stack them so I get as a result an array of dimensions (10, 6, 200)? Basically by stacking it to each 2-d array iterating along the first dimension
a = np.random.random((10, 5, 200))
b = np.zeros((1, 200))
I'v tried with hstack and vstack but I get an error in incorrect number of axis
Let's say:
a = np.random.random((10, 5, 200))
b = np.zeros((1, 200))
Let's look at the volume (number of elements) of each array:
The volume of a is 10*5*200 = 10000.
The volume of an array with (10,6,200) is 10*5*200=1200.
That is you want to create an array that has 2000 more elements.
However, the volume of b is 1*200 = 200.
This means a and b can't be stacked.
As hpaulj mentioned in the comments, one way is to define an numpy array and then fill it:
result = np.empty((a.shape[0], a.shape[1] + b.shape[0], a.shape[2]))
result[:, :a.shape[1], :] = a
result[:, a.shape[1]:, :] = b

How to take n block of a 3d array in python?

I had 328 grayscale images with the size 128*128 and I convert all of them into a 3D array with the shape (128,128,328). Now I want to convert it into 5 separated 3d arrays with the shape of (128,128,64) without changing in sequence.
As you can see 328 is not divisible by 64 and using dsplit function is not working.
Is there any way to slice the 3d array on depth axes dynamically?
import numpy as np
arr = np.zeros(shape=(128,128,328))
# make aray divisible by 5 (trim it to the depth of 320)
arr = arr[:, :, :320]
# Split array
arrays = np.dsplit(arr, 5)
for array in arrays:
print(array.shape)
Output:
(128, 128, 64)
(128, 128, 64)
(128, 128, 64)
(128, 128, 64)
(128, 128, 64)
EDIT: Here is the same thing written in a dynamic way.
import numpy as np
num_subarrays = 5
subarray_depth = 64
# Initialize array
arr = np.zeros(shape=(128,128,328))
# make aray divisible by subarray_depth
arr = arr[:, :, :(arr.shape[2] // subarray_depth) * subarray_depth]
# Split array
arrays = np.dsplit(arr, num_subarrays)
for array in arrays:
print(array.shape)

Select random arrays from a stack of arrays

I have a numpy array np_arr with a shape as such
(3787, 256, 256)
I want to sample 20 random arrays from the existing array such that
(20, 256, 256)
I tried
import random
new_array = random.sample(np_arr,20)
but that didn't work.
How do I go about it
You can use np.random.choiceto randomly choose indices of the first dimension, then index your array with it:
import numpy as np
# Generating random data
rand_arr = np.random.rand(3787, 256, 256)
rand_idx = np.random.choice(rand_arr.shape[0], 20)
rand_arr[rand_idx]
# > shape = (20, 256, 256)
# In one line:
rand_arr[np.random.choice(rand_arr.shape[0], 20)]

Calculating the density of an MNIST database grayscale image

Using this function:
import numpy as np
def blockshaped(arr, nrows, ncols):
''' Return an array of shape (n, nrows, ncols) where
n * nrows * ncols = arr.size
If arr is a 2D array, the returned array should look like n subblocks with
each subblock preserving the "physical" layout of arr.
'''
h, w = arr.shape
assert h % nrows == 0, "{} rows is not evenly divisble by {}".format(h, nrows)
assert w % ncols == 0, "{} cols is not evenly divisble by {}".format(w, ncols)
return (arr.reshape(h//nrows, nrows, -1, ncols)
.swapaxes(1, 2)
.reshape(-1, nrows, ncols))
I was able to divide my image into blocks of 16 pixels each.
What I want to do is calculate the density of the black pixels in each block.
I know that the values of pixels range from 0 to 255.
I wanted to do black_density = numberof_zeros / 16, but I'm not sure.
Well, if you want to know the density of black, in each block of your image you simply do
np.sum(block_shaped(img, 16, 16).reshape(-1, 16*16) <= black_threshold, axis=1)
If you are uncertain about the threshold you could try Otsu method, either by blocks or the whole image, it depends on what you really want.

Categories