I have some code that I am using with tensorflow datasets.
It's worked fine previously and it may still work. But I don't think so
img = parse_image(img_paths[0])
img = tf.image.resize(img, [224, 224])
plt.imshow(img)
Just outputs a blank 224x224 canvas.
img = parse_image(img_paths[0])
plt.imshow(img)
outputs the image correctly.
img_paths is a list of strings with pathnames
I have tried:
img = parse_image(img_paths[0])
img = tf.image.resize([img], [224, 224])
plt.imshow(img[0])
and
img = parse_image(img_paths[0])
img = tf.image.resize(img, [224, 224])
plt.imshow(img.numpy())
and
img = parse_image(img_paths[0])
img = tf.image.resize([img], [224, 224])
plt.imshow(img.numpy()[0])
The shape is correct and this code has worked before.
And may still work, I'm thinking I may not use it correctly anymore (been a while since I wrote it).
thanks for any hints or thoughts you can provide? And of course solutions ;-)
The "problem" is with Matplotlib. When you resize with Tensorflow, it turns your input to float. Matplotlib accepts two image formats, integers between 0-255 and floats between 0 and 1. If you call plt.imshow() on floats of more than 1, it will clip all values and you'll see a white image. It's like you would give Matplotlib only pixels at 1.0 (or 255).
tf.image.convert_image_dtype has a saturate argument, and its default value makes it that the 0-255 integer range becomes 0-1 float. This is why it "works", because Matplotlib understands that format. After this, the Tensorflow resizing operation keeps it between 0-1 too, so it works.
Huh,
I saw something elsewhere and added this line:
img = tf.image.convert_image_dtype(img, tf.float32)
before resizing and it worked.
This is extremely weird because I didn't need this line before. Maybe due to a version update?
Either way this works:
img = parse_image(train_img_paths[0])
img = tf.image.convert_image_dtype(img, tf.float32)
img = tf.image.resize(img, [224, 224])
plt.imshow(img)
Related
I have the following image:
Original Image
I am using the following code to resize this image to 1600x1200.
img = cv2.imread('R.png')
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_image.resize(1600,1200)
I am then returned the following image:
Final Image
I have tried to fix this by using different image formats (jpg, tif), but this does not seem to help. I also tried using different interpolation algorithms like INTER_NEAREST and INTER_LINEAR, and these produce the same results.
Does anyone have an idea?
You are calling the resize() function on the numpy array that represents the grayscale image, which only changes the shape of the array. You should use the resize() function from OpenCV:
img = cv2.imread('R.png')
resized_image = cv2.resize(img, (1600, 1200), interpolation = cv2.INTER_LINEAR)
Besides of that, I think you have mistakenly swapped the width and height of the image, it should be 1200 x 1200 to keep the scale.
I'm converting a .png image to float32 the following way and I'm obtaining a broken image as shown below. If I remove the tf.image.convert_image_dtype call, everything goes well.
image = tf.io.read_file(filename)
image = tf.image.decode_png(image, channels=3)
image = tf.image.convert_image_dtype(image, tf.float32)
I've also tried different images with different formats like .bmp and .jpg but same thing happens. The code I use to visualize the image generated the above way is just:
a = a.numpy()
a = Image.fromarray(a, 'RGB')
As I've said, if I just remove the tf.image.convert_image_dtype call everything goes well.
Here are the download links of both images (I have less than 10 reputation here so I can't upload photos yet).
original_image
obtained_image
You can convert it back to integer like this
import tensorflow as tf
import numpy as np
from PIL import Image
image = tf.io.read_file("C:\\<your file>.png")
image = tf.image.decode_png(image, channels=3)
image = tf.image.convert_image_dtype(image, tf.float32)
a = image.numpy()
a = (a * 255 / np.max(a)).astype('uint8')
a = Image.fromarray(a, 'RGB')
a.show()
I have an image stored in a numpy array that I want to convert to PIL.Image in order to perform an interpolation only available with PIL.
When trying to convert it through Image.fromarray() it raises the following error:
TypeError: Cannot handle this data type
I have read the answers here and here but they do not seem to help in my situation.
What I'm trying to run:
from PIL import Image
x # a numpy array representing an image, shape: (256, 256, 3)
Image.fromarray(x)
tl;dr
Does x contain uint values in [0, 255]? If not and especially if x ranges from 0 to 1, that is the reason for the error.
Explanation
Most image libraries (e.g. matplotlib, opencv, scikit-image) have two ways of representing images:
as uint with values ranging from 0 to 255.
as float with values ranging from 0 to 1.
The latter is more convenient when performing operations between images and thus is more popular in the field of Computer Vision.
However PIL seems to not support it for RGB images.
If you take a look here
it seems that when you try to read an image from an array, if the array has a shape of (height, width, 3) it automatically assumes it's an RGB image and expects it to have a dtype of uint8!
In your case, however, you have an RBG image with float values from 0 to 1.
Solution
You can fix it by converting your image to the format expected by PIL:
im = Image.fromarray((x * 255).astype(np.uint8))
I solved it different way.
Problem Situation:
When working with gray image or binary image, if the numpy array shape is (height, width, 1), this error will be raised also.
For example, a 32 by 32 pixel gray image (value 0 to 255)
np_img = np.random.randint(low=0, high=255, size=(32, 32, 1), dtype=np.uint8)
# np_img.shape == (32, 32, 1)
pil_img = Image.fromarray(np_img)
will raise TypeError: Cannot handle this data type: (1, 1, 1), |u1
Solution:
If the image shape is like (32, 32, 1), reduce dimension into (32, 32)
np_img = np.squeeze(np_img, axis=2) # axis=2 is channel dimension
pil_img = Image.fromarray(np_img)
This time it works!!
Additionally, please make sure the dtype is uint8(for gray) or bool(for binary).
In my case it was only because I forgotted to add the "RGB" arg in the "fromarray" func.
pil_img = Image.fromarray(np_img, 'RGB')
I found a different issue for the same error in my case. The image I used was in RGBA format, so before using fromarray() function just convert it to RGB using the convert() function and it will work perfectly fine.
image_file = Image.open(image_file)
image_file = image_file.convert('RGB')
P.S.: Posting this solution as an initial step, before converting the image to np.
In my case file format of the images was changed to png to jpg. It worked well when I corrected the image format of the error images.
According to the scikit-image's documentation, you can convert an image to unsigned byte format, with values in [0, 255] using img_as_ubyte:
from skimage import img_as_ubyte
from PIL import Image
new_image = Image.fromarray(img_as_ubyte(image))
I'm trying resize images retrieved from cifar10 in the original 32x32 to 96x96 for use with MobileNetV2, howevery I'm running into this error. Tried a variety of solutions but nothing seems to work.
My code:
for a in range(len(train_images)):
train_images[a] = cv2.resize(train_images[a], dsize=(minSize, minSize), interpolation=cv2.INTER_CUBIC)
Error I'm getting:
----> 8 train_images[a] = cv2.resize(train_images[a], dsize=(minSize, minSize), interpolation=cv2.INTER_CUBIC)
ValueError: could not broadcast input array from shape (96,96,3) into shape (32,32,3)
Sometimes you have to convert the image from RGB to grayscale. If that is the problem, the only thing you should do is gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY), resize the image and then again resized_image = cv2.cvtColor(gray_image, cv2.COLOR_GRAY2RGB)
I have never run into this error but if the first option doesn't work, you can try and resize image with pillow like this:
from PIL import Image
im = Image.fromarray(cv2_image)
nx, ny = im.size
im2 = im.resize((nx*2, ny*2), Image.LANCZOS)
cv2_image = cv2.cvtColor(numpy.array(im2), cv2.COLOR_RGB2BGR)
You can make this into a function and call it in the list comprehension. I hope this solves your problem :)
This is simply because you are reading the 32x32 image from train_images and trying to save the reshaped image (96x96) in the same array which is impossible!
Try something like:
train_images_reshaped = np.array((num_images, 96, 96, 3))
for a in range(len(train_images)):
train_images_reshaped[a] = cv2.resize(train_images[a], dsize=(minSize, minSize), interpolation=cv2.INTER_CUBIC)
There are some interpolation algorithms in OpenCV. Such as-
INTER_NEAREST – a nearest-neighbor interpolation
INTER_LINEAR – a bilinear interpolation (used by default)
INTER_AREA – resampling using pixel area relation. It may be a
preferred method for image decimation, as it gives moire’-free
results. But when the image is zoomed, it is similar to the
INTER_NEAREST method.
INTER_CUBIC – a bicubic interpolation over 4×4 pixel neighborhood
INTER_LANCZOS4 – a Lanczos interpolation over 8×8 pixel neighborhood
Code:
image_scaled=cv2.resize(image,None,fx=.75,fy=.75,interpolation = cv2.INTER_LINEAR)
img_double=cv2.resize(image,None,fx=2,fy=2,interpolation=cv2.INTER_CUBIC)
image_resize=cv2.resize(image,(200,300),interpolation=cv2.INTER_AREA)
image_resize=cv2.resize(image,(500,400),interpolation=cv2.INTER_LANCZOS4)
You can find the details about python implementation here as well: How to resize images in OpenCV python
I'm trying to mimic what this line of code does, using imageio :
img_array = scipy.misc.imread('/Users/user/Desktop/IMG_5.png', flatten=True)
img_data = 255.0 - img_array.reshape(784)`
However when using imageio I get:
img = imageio.imread('/Users/user/Desktop/IMG_5.png')
img.flatten()
Output: Image([212, 211, 209, ..., 192, 190, 191], dtype=uint8)
img.reshape(1, 784)
ValueError: cannot reshape array of size 2352 into shape (1,784)
Can someone explain what is going on here, why is my image size 2352? I resized the image to 28x28 pixels before importing it.
I know this question already has an accepted answer, however, it implies to use skimage library instead of imageio as the question (and scipy) suggest. So here it goes.
According to imageio's doc on translating from scipy, you should change flatten argument by as_gray argument.
So this line:
img_array = scipy.misc.imread('/Users/user/Desktop/IMG_5.png', flatten=True)
should gives you same result as this:
img_array = imageio.imread('/Users/user/Desktop/IMG_5.png', as_gray=True)
It worked for me. If it didn't work for you, perhaps there is another problem. Providing an image as an example might help.
An RGB image has three channels, so 784 pixels three times is 2352. Shouldn't you save the results of img.flatten() in a variable? img_flat = img.flatten(). If you do this you should get the three color layers flatten to one gray-scale layer, then you can reshape it.
Edit: It's probably going to be easier to just use skimage in the same fashion you used the deprecated scipy:
from skimage import transform,io
# read in grey-scale
grey = io.imread('your_image.png', as_grey=True)
# resize to 28x28
small_grey = transform.resize(grey, (28,28), mode='symmetric', preserve_range=True)
# reshape to (1,784)
reshape_img = small_grey.reshape(1, 784)