Tensorflow: open a PIL.Image?
Solution 1
Use the img_to_array
function from Keras:
import tensorflow as tf
from PIL import Image
pil_img = Image.new(3, (200, 200))
image_array = tf.keras.preprocessing.image.img_to_array(pil_img)
Solution 2
The 'DecodeJpeg:0/contents:0' is an operation that is meant to decode a base64 string to raw image data. You are trying to feed in the raw image data. So you should feed it into the 'DecodeJpeg:0' wich is the output of the 'DecodeJpeg:0/contents:0' or to into the 'Mul:0' that is the input of the graph. Don't forget to resize as the input should be of shape (299,299,3) The Mul takes in a (1,299,299,3)
Try it like this:
image = Image.open("example.jepg")
image.resize((299,299), Image.ANTIALIAS)
image_array = np.array(image)[:, :, 0:3] # Select RGB channels only.
prediction = sess.run(softmax_tensor, {'DecodeJpeg:0': image_array})
or
prediction = sess.run(softmax_tensor, {'Mul:0': [image_array]})
as well discussed in this stackoverflow question
To visualize the operations:
for i in sess.graph.get_operations():
print (i.values())
Hope this helps
Solution 3
Not sure why Maximilian's answers didn't work, but here's what did work for me:
from io import BytesIO
def predict(image, labels, sess):
imageBuf = BytesIO()
image.save(imageBuf, format="JPEG")
image = imageBuf.getvalue()
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predictions = sess.run(softmax_tensor,
{'DecodeJpeg/contents:0': image})
predictions = np.squeeze(predictions)
top_k = predictions.argsort()[-5:][::-1] # Getting top 5 predictions
return predictions[top_k[0]], labels[top_k[0]] # Return the raw value of tag matching and the matching tag.
Made a byte buffer, saved the PIL Image into it, got its value and passed it in. I'm still new to Tensorflow and image processing, so if anyone has a concrete reason why this worked and Max's stuff didn't, it would make a good addendum to this answer.
IronWaffleMan
Updated on June 26, 2022Comments
-
IronWaffleMan almost 2 years
I have a script that obscures part of an image and runs it through a prediction net to see which parts of the image most strongly influence the tag prediction. To do this, I open a local image with PIL and resize it, along with adding a black box at various intervals. I use Tensorflow to open my model and I want to pass the image to the model, but it's not expecting a value with this specific shape:
Traceback (most recent call last): File "obscureImage.py", line 55, in <module> originalPrediction, originalTag = predict(originalImage, labels) File "obscureImage.py", line 23, in predict {'DecodeJpeg/contents:0': image}) File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\tensorflow\python\client\session.py", line 766, in run run_metadata_ptr) File "C:\Users\User\AppData\Local\Programs\Python\Python35\lib\site-packages\tensorflow\python\client\session.py", line 943, in _run % (np_val.shape, subfeed_t.name, str(subfeed_t.get_shape()))) ValueError: Cannot feed value of shape (224, 224, 3) for Tensor 'DecodeJpeg/contents:0', which has shape '()'
This is my code:
def predict(image, labels): with tf.Session() as sess: #image_data = tf.gfile.FastGFile(image, 'rb').read() # What I used to use. softmax_tensor = sess.graph.get_tensor_by_name('final_result:0') predictions = sess.run(softmax_tensor, {'DecodeJpeg/contents:0': image}) predictions = np.squeeze(predictions) top_k = predictions.argsort()[-5:][::-1] # Getting top 5 predictions return predictions[0], labels[top_k[0]] # Return the raw value of tag matching and the matching tag. originalImage = Image.open(args.input).resize((args.imgsz,args.imgsz)).convert('RGB') originalPrediction, originalTag = predict(originalImage, labels)
Opening and using the image from the disk works fine, but of course then it's not my modified image. I tried using
tf.image.decode_jpeg(image,0)
as the parameter for the softmax tensor, but that gives meTypeError: Expected string passed to parameter 'contents' of op 'DecodeJpeg', got <PIL.Image.Image image mode=RGB size=224x224 at 0x2592F883358> of type 'Image' instead.
-
IronWaffleMan over 7 yearsAfraid neither of those work. Passing in
image.getdata()
as the parameter tosess.run
gave me:ValueError: Cannot feed value of shape (50176, 3) for Tensor 'DecodeJpeg/contents:0', which has shape '()'
. Trying to doimage = tf.gfile.FastGFile(image, 'rb').read()
gave meTypeError: Expected binary or unicode string, got <PIL.Image.Image image mode=RGB size=224x224 at 0x28C3F772898>
. Seems a bit odd to me that it expects something of shape ()... -
Maximilian Peters over 7 years@IronWaffleMan: FastGFile expects a string with the filename, not the image itself. I updated the question to avoid confusion.
-
IronWaffleMan over 7 yearsI know it does, but I'm not passing it a filename. I'm passing it an image I've modified with PIL.