I try to rescale 2D images (greyscale).
The image size is 256x256 and the desired output is 224x224.
The pixel values range from 0 to 1300.
I tried 2 approaches to rescale them with Lanczos Interpolation:
First using PIL Image:
import numpy as np
from PIL import Image
import cv2
array = np.random.randint(0, 1300, size=(10, 256, 256))
array[0] = Image.fromarray(array[0]).resize(size=(224, 224), resample=Image.LANCZOS)
resulting in the error message: ValueError: image has wrong mode
And then CV2:
array[0] = cv2.resize(array[0], dsize=(224, 224), interpolation=cv2.INTER_LANCZOS4)
resulting in the error message: ValueError: could not broadcast input array from shape (224,224) into shape (256,256)
How to do it properly?
In the second case, you are resizing a 256x256 image to 224x224, then assigning it back into a slice of the original array. This slice still has size 256x256, so NumPy doesn't know how to do the data copy.
Instead, create a new output array of the right sizes:
array = np.random.randint(0, 1300, size=(10, 256, 256))
newarray = np.zeros((10, 224, 224))
newarray[0] = cv2.resize(array[0], dsize=(224, 224), interpolation=cv2.INTER_LANCZOS4)
In the PIL part, you have a few issues.
Firstly, you need to check the dtype of things you create! You create an array of np.int64 when you use np.random() like that. As you know your data only maxes out at 1300, an unsigned 16-bit is preferable:
array = np.random.randint(0, 1300, size=(10, 256, 256), dtype=np.uint16)
Secondly, when you create a PIL Image from the Numpy array, you need to tell PIL the mode - greyscale or Lightness here:
array[0] = Image.fromarray(array[0], 'L')
Thirdly, you are trying to stuff the newly created PIL Image back into a Numpy array - don't do that:
newVariable = Image.fromarray(...).resize()
Related
I want to convert PIL to numpy but I get this error what should I do?
import numpy as np
from PIL import Image
import PIL
import matplotlib.pyplot as plt
img_path = "F:\Pictures\Reza's WLP\wallpaper\sample.png"
img = Image.open(img_path)
img_2 = img.resize((100,100))
img_array = np.array(img_2.getdata()).reshape(img_2.size[0], img_2.size[1])
plt.imshow(img_array)
ValueError: cannot reshape array of size 30000 into shape (100,100)
Notice that the array is three times bigger than you're expecting (30000 = 3 * 100 * 100). That's because an array representing an RGB image isn't just two-dimensional: it has a third dimension, of size 3 (for the red, green and blue components of the colour).
So:
img_array = np.array(img_2.getdata()).reshape(img_2.size[0], img_2.size[1], 3)
Alternatively, you could specify the third dimension's size as -1. This means you're asking numpy to figure it out from the dimensions you've already told it: it knows that the source has 30000 elements, so if you want to reshape it into (100, 100, x), then x must be 3.
img_array = np.array(img_2.getdata()).reshape(img_2.size[0], img_2.size[1], -1)
try adding a -1 at the end of the reshape
like .reshape(a,b,-1)
I have an array (generated from PIL image) of shape (500,500,3) and need to convert it to (180,180,3). No matter what I try, it doesn't seem to work. Here is the code:
window = img[i:i+window_size_dim1, j:j+window_size_dim2]
img = Image.fromarray(window)
img_array = image.img_to_array(img)
img_array.reshape((180,180,3))
and the error:
ValueError: cannot reshape array of size 750000 into shape (180,180,3)
any ideas are much appreciated!
I'm trying to convert an RGB image to a greyscale image, then to a numpy array using the following code snippet:
img = Image.open("image1.png")
img = img.convert('L')
img = np.array(img, dtype='f')
print(img.shape)
The result is a numpy array of shape (128, 128). Is there anyway that I could convert a greyscale image to a numpy array so that it would have the color channel as well, i.e. the shape would be (128, 128, 1)?
Like #Mark mentioned in comments, add a dimension to the end if your array using newaxis:
img=img[...,None]
None will do similar as np.newaxis. It does not create a color, but adds a dimension similar to a single channel image.
I took some images and replaced them with numpy array.
The image is a RGB image.
The converted numpy array is of size (256, 256, 3).
I wanted to import only the Y channel after I switched this RGB image to YCbCr.
What I want is an array of size (256,256, 1).
So I used [:,:, 0] in the array.
However, I have now become a two-dimensional image as shown in the code below.
I created an array of (256, 256, 1) size with 15 lines of code.
But I failed to see it again as an image.
Below is my code.
from PIL import Image
import numpy as np
img = Image.open('test.bmp') # input image 256 x 256
img = img.convert('YCbCr')
img.show()
print(np.shape(img)) # (256, 256, 3)
arr_img = np.asarray(img)
print(np.shape(arr_img)) # (256, 256, 3)
arr_img = arr_img[:, :, 0]
print(np.shape(arr_img)) # (256, 256)
arr_img = arr_img.reshape( * arr_img.shape, 1 )
print(np.shape(arr_img)) # (256, 256, 1)
pi = Image.fromarray(arr_img)
pi.show # error : TypeError: Cannot handle this data type
When I forcibly changed a two-dimensional image into a three-dimensional image,
The image can not be output.
I want to have a purely (256, 256, 1) sized array.
Y image of the channel!
I tried to use arr_img = arr_img [:,:, 0: 1] but I got an error.
How can I output an image with only Y (256,256,1) size and save it?
A single-channel image should actually be in 2D, with shape of just (256, 256). Extracting out the Y channel is effectively the same as having a greyscale image, which is just 2D. Adding the third dimension is causing the error because it is expecting just the two dimensions.
If you remove the reshape to (256, 256, 1), you will be able to save the image.
Edit:
from PIL import Image
import numpy as np
img = Image.open('test.bmp') # input image 256 x 256
img = img.convert('YCbCr')
arr_img = np.asarray(img) # (256, 256, 3)
arr_img = arr_img[:, :, 0] # (256, 256)
pi = Image.fromarray(arr_img)
pi.show()
# Save image
pi.save('out.bmp')
Try this:
arr_img_1d = np.expand_dims(arr_img, axis=1)
Here is the numpy documentation for the expand_dims function.
I load images with numpy/scikit. I know that all images are 200x200 pixels.
When the images are loaded, I notice some have an alpha channel, and therefore have shape (200, 200, 4) instead of (200, 200, 3) which I expect.
Is there a way to delete that last value, discarding the alpha channel and get all images to a nice (200, 200, 3) shape?
Just slice the array to get the first three entries of the last dimension:
image_without_alpha = image[:,:,:3]
scikit-image builtin:
from skimage.color import rgba2rgb
from skimage import data
img_rgba = data.logo()
img_rgb = rgba2rgb(img_rgba)
https://scikit-image.org/docs/dev/user_guide/transforming_image_data.html#conversion-from-rgba-to-rgb-removing-alpha-channel-through-alpha-blending
https://scikit-image.org/docs/dev/api/skimage.color.html#rgba2rgb
Use PIL.Image to remove the alpha channel
from PIL import Image
import numpy as np
img = Image.open("c:\>path_to_image")
img = img.convert("RGB") # remove alpha
image_array = np.asarray(img) # converting image to numpy array
print(image_array.shape)
img.show()
If images are in numpy array to convert the array to Image use Image.fromarray to convert array to Image
pilImage = Image.fromarray(numpy_array)