Adding Elements to numpy array Changes Input Value - python

Code:
from PIL import Image
import numpy as np
img = Image.open('test.tif')
imarray = np.zeros(shape = (34,23,18))
for i in range(34): # there are 34 images in the .tif file
for j in range(18): # each slice has size 18x23
for k in range(23):
try:
img.seek(i)
imarray[i,k,j] = img.getpixel((k,j))
except EOFError:
break
The purpose of this code is to accept .tif greyscale stacks. I want to be able to work with them as numpy arrays, so storing the original pixel values is essential.
This code successfully copies each slice to the np.array "imarray." However, it changes the values. For example, I printed all of the "img.getpixel" values for a given slice, and the values (type int) ranged between 2000 and 65500. However, the values in imarray (type float64) did not exceed 2800. I tried casting, ie:
imarray[0,j,i] = np.float64(img.getpixel((j,i)))
But it did not help. How can I revise this code to avoid my input data (img.getpixels) changing? If there are better alternatives to this approach, I'm happy to hear

Related

saving multiple 3D array of size (22,6,2840) as images

I am generating multiple 3D numpy array of size (22,6,2840),each array containing 22 array of size(6,2840).Now I want to save this array (22,6,2840) as images. I don't know if I can do that. I tried to do this using plt.savefig but it didn't work. I am trying for more than 2 weeks to find how I can do it.
Any help would be appreciated.
signals=np.zeros((22,6,2840))
t=0
movement=int(S*256)
if(S==0):
movement=_SIZE_WINDOW_SPECTOGRAM
while data.shape[1]-(t*movement+_SIZE_WINDOW_SPECTOGRAM) > 0:
for i in range(0, 22):
start = t*movement
stop = start+_SIZE_WINDOW_SPECTOGRAM
signals[i,:]=wavelet(data[i,start:stop])
if(signalsBlock is None):
signalsBlock=np.array([signals])
else:
signalsBlock=np.append(signalsBlock, [signals], axis=0)
nSpectogram=nSpectogram+1
if(signalsBlock.shape[0]==50):
saveSignalsOnDisk(signalsBlock, nSpectogram)
signalsBlock=None
t = t+1
try using the PyPNG library. You will have to reshape your array to a 2-D format and then write it as a png. The link to the library is here
image_2d = numpy.reshape(image_3d, (-1, column_count * plane_count))
pngWriter.write(out, image_2d)
Also, one more method by using PIL Image is provided here. However, that works with mostly RGB style 3 channel images.

Save 3D array into a stack of 2D images in Python

I made a 3D array, which consists of numbers(0~4). What I want is to save 3D array as a stack of 2D images(if possible, save *.tiff file). What am I supposed to do?
import numpy as np
a = np.random.randint(0,5, size=(100,100,100))
a = a.astype('int8')
Actually, I made it. This is my code.
With this code, I don't need to stack a series of 2D image(array).
Make a 3D array, and save it. That is just what I did for this.
import numpy as np
from skimage.external import tifffile as tif
a = np.random.randint(0,5, size=(100,100,100))
a = a.astype('int8')
tif.imsave('a.tif', a, bigtiff=True)
This should work. I haven't tested it but I have separated color images into RGB slices using this method and it should work pretty much the same way here, assuming you don't want to do anything with those pixel values first. (They will be very close to the same color in an image).
import imageio
import numpy as np
a = np.random.randint(0,5, size=(100,100,100))
a = a.astype('int8')
for i in range(100):
newimage = a[:, :, i]
imageio.imwrite("path/to/image%d.tiff" %i, newimage)
What exactly do you mean by "stack"? As you refer to tiff as output format, I assume here you want your data in one file as a multiframe-tiff.
This can easily be done with imageio's mimwrite() function:
# import numpy as np
# a = np.random.randint(0,5, size=(100,100,100))
# a = a.astype('int8')
import imageio
imageio.mimwrite("image.tiff", a)
Note that this function relies on having the counter for your several frames as first parameter and x and y follw. See also its documentation.
However, if I'm wrong and you want to have n (e.g. 100) separate tif-files, you can also use the normal imwrite() function in a loop:
n = len(a)
for i in range(n):
imageio.imwrite(f'image_{i:03}.tiff', a[i])

How to efficiently write a binary file containing mixed label and image data

The cifar10 tutorial deals with binary files as input. Each record/example on these CIFAR10 datafiles contain mixed label (first element) and image data information. The first answer in this page shows how to write binary file from a numpy array (which accumulates the label and image data information in each row) using ndarray.tofile() as follows:
import numpy as np
images_and_labels_array = np.array([[...], ...], dtype=np.uint8)
images_and_labels_array.tofile("/tmp/images.bin")
This is perfect for me when the maximum number of classes is 256 as the uint8 datatype is sufficient. However, when the maximum number of classes is more than 256, then I have to change the dtype=np.uint16 in the images_and_labels_array. The consequence is just doubling the size. I would like to know if there is an efficient way to overcome it. If yes, please provide an example.
When I write binary files I usually just use the python module struct, which works somehow like this:
import struct
import numpy as np
image = np.zeros([2, 300, 300], dtype=np.uint8)
label = np.zeros([2, 1], dtype=np.uint16)
with open('data.bin', 'w') as fo:
s = image.shape
for k in range(s[0]):
# write label as uint16
fo.write(struct.pack('H', label[k, 0]))
# write image as uint8
for i in range(s[1]):
for j in range(s[2]):
fo.write(struct.pack('B', image[k, i, j]))
This should result in a 300*300*2 + 2*1*2 = 180004 bytes big binary file.
Its probably not the fastest way to get the job done, but for me it worked sufficiently fast so far. For other datatypes see the documentation

python image size function in PIL

I am using the PIL package in python and I want to import the pixels into a matrix after I convert it to grayscale this is my code
from PIL import Image
import numpy as np
imo = Image.open("/home/gauss/Pictures/images.jpg")
imo2 = imo.convert('L')
dim = imo2.size
pic_mat = np.zeros(shape=(dim[0] , dim[1]))
for i in range(dim[0]):
for j in range(dim[1]):
pic_mat[i][j] = imo2.getpixel((i,j))
My question is about the size function. it usually returns a tuple (a,b) where a is the width of the picture and the b is the length of the picture, but doesn't that mean that a is the column in a matrix and b is the row in a matrix. I am wondering this to see if I set up my matrix properly.
Thank you
Try just doing
pic_mat = np.array(imo.convert('L'))
You can also avoid doing things like shape=(dim[0] , dim[1]) by slicing the size tuple like this shape=dim[:2] (the :2 is even redundant in this case but I like to be careful...)

Optimize iteration throught numpy array

I'm swapping values of a multidimensional numpy array in Python. But the code is too slow. Another thread says:
Typically, you avoid iterating through them directly. ... there's a good chance that it's easy to vectorize.
So, do you know a way to optimize the following code?
import PIL.Image
import numpy
pil_image = PIL.Image.open('Image.jpg').convert('RGB')
cv_image = numpy.array(pil_image)
# Convert RGB to BGR
for y in range(len(cv_image)):
for x in range(len(cv_image[y])):
(cv_image[y][x][0], cv_image[y][x][2]) = (cv_image[y][x][2],
cv_image[y][x][0])
For an 509x359 image this last more than one second, which is way too much. It should perform it's task in no time.
How about this single operation inverting the matrix along the last axis?
cv_image = cv_image[:,:,::-1]

Categories

Resources