Python Image array modified between save/load - python

I am modifying images using Image and Numpy in Python 2.7.
I am saving an image with a numpy Integer grayscale array using :
img = Image.fromarray(grayscale_arr, 'L')
img.save(output)
In an other function, i reopen the same image and get the grayscale array with :
img = Image.open(output)
grayscale_arr = np.array(img)
However the arrays do not match. The differences are not big but significant enough ...
My questions are :
First why is that ? Is it an imprecision of some sort ? (just out of curiosity)
And how can I fix this ?
Thank you in advance

Related

How to convert a float32 img to uint8 where range is(-1 to -0.85)?

I want to convert a float32 image into uint8 image in Python.
I tried using the following code, but the output image only has values like 2 and 3 so the image is practically black.
gen_samples[0] * 255).round().astype(np.uint8)
When I try displaying the float32 image I get a blackish/greyish image where I can somewhat make out the required image.
Normalize the array to 0..1 first.
Assuming gen_samples is the image matrix:
arr_min = np.min(gen_samples)
arr_max = np.max(gen_samples)
gen_samples = (gen_samples - arr_min) / (arr_max - arr_min)
Since you tagged the question using scikit-image you are probably using skimage. In this case img_as_ubyte should do the trick:
from skimage.util import image_as_ubyte
img = img_as_ubyte(gen_samples[0])
Further, since you tagged the question with imageio-python I'll assume that the image data actually comes from some (binary) image format rather than being generated in the script. In this case, you can often use the backend that does the decoding and do the conversion while the image is being loaded. This is, however, specific to the format being used, so for a more specific answer you would have to provide more insight into where your images are coming from.

Python PIL read/open TIFF is black only

I try to read a TIFF file with pillow/PIL (7.2.0) in Python (3.8.3), e.g. this image.
The resulting file seems to be corrupted:
from PIL import Image
import numpy as np
myimage = Image.open('moon.tif')
myimage.mode
# 'L'
myimage.format
# 'TIFF'
myimage.size
# (358, 537)
# so far all good, but:
np.array(myimage)
# shows only zeros in the array, likewise
np.array(myimage).sum()
# 0
It doesn't seem to be a problem of the conversion to numpy array only, since if I save it to a jpg (myimage.save('moon.jpg')) the resulting jpg image has the appropriate dimensions but is all black, too.
Where did I do wrong or is it a bug?
I am not an expert in coding but i had same problem and found the TIFF file has 4 layers. R, G ,B and Alpha. When you convert it using PIL it is black.
try to view the image as plt.imshow(myimage[:, :, 0])
you could also remove the Alpha layer by saving the read image ( i used plt.imread('image')) and then saving it as image=image[:,:,3]. Now its a RGB image.
I don't know if i answered your question, but i felt this info might be of help.

Converting an ndarray image into a grayscale image with the same array shape

I'm trying to write a python function that takes an image ndarray as a parameter and returns an ndarray of the grayscale version of that image using broadcasting.
My main issue right now is that my resulting image does not have the same shape (800, 400, 3) as the original.
Edit: it turns out that I had just forgotten to convert the resulting array into np.uint8
Your first convert_bw function don't have any problem, I think problem is how you see the result image (The library you use can't show you the result well). for example you can see the result by following code:
import matplotlib.pyplot as plt
bw = convert_bw(img)
plt.imshow(bw.astype(np.uint8))
It worked for me.

Error when overlaying two images in OpenCV and or PIL

I've tried overlaying two images in openCV both in openCV and in PIL, but to no avail. I'm using a 1000x1000x3 array of np.zeros for the background (aka, a black background) and this random image of my monitor, but I really can't get it to work for some reason unbeknownst to me.
Trying with OpenCV only: (result(if you pay attention, you can see a couple of weird lines and dots in the middle))
base_temp = np.zeros((1000,1000,3))
foreground_temp = cv2.imread('exampleImageThatILinkedAbove.png')
base_temp[offset_y:offset_y+foreground_temp.shape[0], offset_x:offset_x+foreground_temp.shape[1]] = foreground_temp
Trying with PIL: (The result is literally the same as the OpenCV version)
base_temp = cv2.convertScaleAbs(self.base) #Convert to uint8 for cvtColor
base_temp = cv2.cvtColor(base_temp, cv2.COLOR_BGR2RGB) #PIL uses RGB and OpenCV uses BGR
base_temp = Image.fromarray(base_temp) #Convert to PIL Image
foreground_temp = cv2.cvtColor(cv2.convertScaleAbs(self.last_img), cv2.COLOR_BGR2RGB)
foreground_temp = Image.fromarray(foreground_temp)
base_temp.paste(foreground_temp, offset)
I'm using python3.5 and and OpenCV3.4 on Windows 10, if that's any help.
I'd like to avoid any solutions that require saving the cv2 images and then reloading them in another module to convert them but if it's unavoidable that's okay too. Any help would be appreciated!
If you check the type of base_temp, you will see it is float64 and that is going to cause you problems when you try to save it as a JPEG which expects unsigned 8-bit values.
So the solution is to create your base_temp image with the correct type:
base_temp = np.zeros((1000,1000,3), dtype=np.uint8)
The complete code and result look like this:
import cv2
import numpy as np
from PIL import Image
# Make black background - not square, so it shows up problems with swapped dimensions
base_temp=np.zeros((768,1024,3),dtype=np.uint8)
foreground_temp=cv2.imread('monitor.png')
# Paste with different x and y offsets so it is clear when indices are swapped
offset_y=80
offset_x=40
base_temp[offset_y:offset_y+foreground_temp.shape[0], offset_x:offset_x+foreground_temp.shape[1]] = foreground_temp
Image.fromarray(base_temp).save('result.png')

python mahotas.imread reads a 2d image as 3d

I have an image saved by another code of mine. The image is a normal JPG file. I saved it with imsave.
now when I'm reading it in another code, it seems to be 3d :S
the image is here.
and a simple code to read it is this :
import mahotas
img = mahotas.imread('d:/normal.jpg')
print img.shape, img.dtype
Try reading the jpg as greyscale like this:
mahotas.imread('d:/normal.jpg', as_grey = True)
(Author of mahotas here).
The suggestion by Junuxx is correct:
mahotas.imread('file.jpg', as_grey=True)
This reads the RGB file and converts it to grey scale by a weighted average of the components (they are not equally weighted, but use typical coefficients that attempt to be perceptually more accurate).
The alternative (which I rather prefer) is:
im = mahotas.imread('file.jpg')
im = im[:,:,0]
I assume that all the channels have the same values and just use the first one.

Categories