Shank Shank - 4 months ago 11
Python Question

List of Images from a list of 128x512 arrays improve efficiency

I have a list of 128x512 arrays as shown below:

[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.]], dtype=float32),
array([[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
...,
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.]], dtype=float32),
array([[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
[ 0., 0., 0., ..., 0., 0., 0.],
...,


I am converting this list of arrays to a list of RGB images and so far my code is:

#makes an array of all the images

image_out = [[] for i in range(len(blue_Rad_list))]

for i in range(len(blue_Rad_list)):

startTime = time.time()

image_arr = [np.int_(np.float_(x/np.amax(blue_Rad_list))*256) for x in blue_Rad_list[i]]
image_out[i] = Image.new('RGB', (width, height))
image_out[i].putdata(np.asarray(image_arr).ravel())


del image_arr[:]

stopTime = time.time()

print(stopTime - startTime)


After running my code, I get something like this:

<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CDCE90>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CDCED0>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CDCF10>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CDCF50>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CDCF90>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CDCFD0>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CE9050>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CE9090>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CE90D0>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CE9110>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CE9150>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CE9190>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CE91D0>,
<PIL.Image.Image image mode=RGB size=128x512 at 0x7F47D4CE9210>]


In the above code,
blue_Rad_list
is the list of 128x512 arrays. This code works but its taking a lot of time to give me the entire list of images when there are around 180 elements. Is there a more efficient way I can do this. Thanks for any help.

Answer Source

With the idea of performing less work once we go inside the loop, specially those compute heavy work, here's an approach making use of a multi-dim array instead of list of arrays as input. In the process, we would be leveraging the vectorized operations supported by NumPy to cover all elements -

# Convert to 3D array. If you already have the multi-dim array that was used to
# create the list of arrays. Use that instead of imgs
imgs = np.array(blue_Rad_list)

# Perfomr the image conversion operation formerly done within loop
imgs1 = np.int_(np.float_(imgs/np.amax(imgs))*256).reshape(imgs.shape[0],-1)

# Loop through and create list of PIL images
image_out = [[] for i in range(len(blue_Rad_list))]
for i in range(len(imgs)):
    image_out[i] = Image.new('RGB', (width, height))
    image_out[i].putdata(imgs1[i])

It seems we could optimize one-step further by initializing for the data storage before going into loop, like so -

image_out = [Image.new('RGB', (width, height))]*len(imgs)
for i in range(len(imgs)):
    image_out[i].putdata(imgs1[i])