convert ndarray object to Image - python

I have a gray scale image of type uint16, size = (256,256) ndarray object
I want to use PIL to resize it to (75,75) but it requires the input to be of Image type.
How can I convert image of ndarray object into Image type to use image.resize((75,75), Image.ANTIALIAS)
NOTE:
I know I can read image using Image.open if it is saved, but my image is obtained after some image processing steps and is not read from disk
UPDATE:
I am trying to provide image that I have :
import scipy.misc
scipy.misc.imsave('image.png', box_img)
# read this similar format image of type ndarray
image = scipy.ndimage.imread('image.png')
# convert it to Image type
The image attached when read of similar type as I need.
I need to convert this image into Image type
Thanks,
Gopi

from PIL import Image
import numpy as np
# An array of ones for example
img_array = np.ones((256,256), dtype='uint16')
img = Image.fromarray(img_array)
img = img.resize((75,75))

Related

PIL image in grayscale to OpenCV format

I found the previous answer related to a more general conversion from RGB image here: Convert image from PIL to openCV format
I would like to know the difference when an image has to be read as a grayscale format.
images = [None, None]
images[0] = Image.open('image1')
images[1] = Image.open('image2')
print(type(images[0]))
a = np.array(images[0])
b = np.array(images[1])
print(type(a))
im_template = cv2.imread(a, 0)
im_source = cv2.imread(b, 0)
I get the following output:
<class 'PIL.JpegImagePlugin.JpegImageFile'>
<class 'numpy.ndarray'>
Even though I am able to convert the image to ndarray, cv2 says: "bad argument type for built-in operation". I do not need an RGB to BGR conversion. What else should I consider while passing a cv2 read argument?
You are making life unnecessarily difficult for yourself. If you want to load an image as greyscale, and use it with OpenCV, you should just do:
im = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
and that's all. No need to use PIL (which is slower), no need to use cvtColor() because you have already wasted all the memory reading it in BGR anyway.
If you absolutely want to read it using PIL (for some odd reason), use:
import numpy as np
from PIL import Image
# Read in and make greyscale
PILim = Image.open('image.jpg').convert('L')
# Make Numpy/OpenCV-compatible version
openCVim = np.array(PILim)
By the way, if you want to go back to a PIL image from an OpenCV/Numpy image, use:
PILim = Image.fromarray(openCVim)
Since you already have loaded the image, you should use an image conversion function:
im_template = cv2.cvtColor(a, cv2.COLOR_RGB2GRAY)
im_source = cv2.cvtColor(b, cv2.COLOR_RGB2GRAY)

How to convert dtype(uint16) data into a 16bit png image?

I'm trying to encrypt and decrypt an image using RSA algo. For that, I need to read the image as greyscale and then apply the keys and save the uint16 type array into a png or any image format which supports 16bit data. Then I need to read that 16bit data convert it into an array and do the decryption. Now, previously I tried to save the image as .tif and when I read it with
img = sk.imread('image.tiff', plugin = 'tifffile')
it treats the image as RGB, which is not what I want. Now I want to save the uint16 type array to a 16bit png image which will take values between 0 to 65536 and then read it again as a uint16 type data. I tried to save the values to a 16bit png file using
img16 = img.astype(np.uint16)
imgOut = Image.fromarray(img16)
imgOut.save('en.png')
This gives me this error: OSError: cannot write mode I;16 as PNG
I have also tried imgOut = Image.fromarray(img16, 'I') but this yeilds not enough image data
Please help me to save the 16bit data into a .png image. Thank you.
There are a couple of possibilities...
First, using imageio to write a 16-bit PNG:
import imageio
import numpy as np
# Construct 16-bit gradient greyscale image
im = np.arange(65536,dtype=np.uint16).reshape(256,256)
# Save as PNG with imageio
imageio.imwrite('result.png',im)
You can then read the image back from disk and change the first pixel to mid-grey (32768) like this:
# Now read image back from disk into Numpy array
im2 = imageio.imread('result.png')
# Change first pixel to mid-grey
im2[0][0] = 32768
Or, if you don't like imageio, you can use PIL/Pillow and save a 16-bit TIFF:
from PIL import Image
import numpy as np
# Construct 16-bit gradient greyscale image
im = np.arange(65536,dtype=np.uint16).reshape(256,256)
# Save as TIFF with PIL/Pillow
Image.fromarray(im).save('result.tif')
You can then read back the image from disk and change the first pixel to mid-grey like this:
# Read image back from disk into PIL Image
im2 = Image.open('result.tif')
# Convert PIL Image to Numpy array
im2 = np.array(im2)
# Make first pixel mid-grey
im2[0][0] = 32768
Keywords: Image, image processing, Python, Numpy, PIL, Pillow, imageio, TIF, TIFF, PNG, 16 bit, 16-bit, short, unsigned short, save, write.

How to open a CR2 file in python OpenCV

I've managed to come very far on a program I'm writing. I don't know how to load CR2 files into an OpenCV Image. I've tried the following:
raw = rawpy.imread(sys.argv[1])
rgb = raw.postprocess()
PILrgb = scipy.misc.toimage(rgb)
image = cv2.imdecode(PILrgb, 1)
It was an attempt at converting the numpyarray returned by Postprocess the currently loaded RAW image and return the new resulting image as numpy array. Then calling spicy.misc.toimage to Takes a numpy array and returns a PIL image..
I get the following msg though TypeError: buf is not a numpy array, neither a scalar
It may be easier if you only rawpy
import rawpy
import cv2
raw = rawpy.imread(sys.argv[1]) # access to the RAW image
rgb = raw.postprocess() # a numpy RGB array
image = cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR) # the OpenCV image

Python: How to write a single channel png file from numpy array?

I want to write a single channel png image from a numpy array in python?
In Matlab that would be
A = randi(100,100,255)
imwrite(uint8(A),'myFilename.png','png');
I saw exampels using from PIL import Image and Image.fromarray() but they are for jpeg and 3-channel pngs only it appears...
I already found the solution using opencv, I will post it here. Hopefully it will shorten someone else's searching...
Here is a solution using opencv / cv2
import cv2
myImg = np.random.randint(255, size=(200, 400)) # create a random image
cv2.imwrite('myImage.png',myImg)
PIL's Image.fromarray() automatically determines the mode to use from the datatype of the passed numpy array, for example for an 8-bit greyscale image you can use:
from PIL import Image
import numpy as np
data = np.random.randint(256, size=(100, 100), dtype=np.uint8)
img = Image.fromarray(data) # uses mode='L'
This however only works if your array uses a compatible datatype, if you simply use data = np.random.randint(256, size=(100, 100)) that can result in a int64 array (typestr <i8), which PIL can't handle.
You can also specify a different mode, e.g. to interpret a 32bit array as an RGB image:
data = np.random.randint(2**32, size=(100, 100), dtype=np.uint32)
img = Image.fromarray(data, mode='RGB')
Internally Image.fromarray() simply tries to guess the correct mode and size and then invokes Image.frombuffer().
The image can then be saved as any format PIL can handle e.g: img.save('filename.png')
You might want not to utilise OpenCV for simple image manipulation. As suggested, use PIL:
im = Image.fromarray(arr)
im.save("output.png", "PNG")
Have you tried this? What has failed here that led you to concluding that this is JPEG-only?

Converting raw images to tiff by using rawpy module in python

I'm new to image processing. I just wanted to get a tiff image from raw format(NEF). I used rawpy module to get the desired output, yet the tiff image is RGB with 4 channels. I couldn't know why there is a fourth channel in the new image?
Can anyone please explain to me what is going on, and how I can get tiff image with three RGB channels?
import rawpy
import matplotlib.pylab as plt
raw_image = "DSC_0001.NEF"
raw = rawpy.imread(raw_image)
rgb = raw.postprocess()
plt.imsave("new.tiff", rgb )
image = plt.imread("new.tiff")
print(image.shape)
The array shape is : (2868, 4310, 4) !
Finally I found the reason:
plt.imsave saves the image in RGBA , while I can use skim age.io.imsave and it will save it as RGB.
Source: Github Issue entry

Categories

Resources