Tensorflow: open a PIL.Image?

10,776

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.

Share:
10,776
IronWaffleMan
Author by

IronWaffleMan

Updated on June 26, 2022

Comments

  • IronWaffleMan
    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 me TypeError: 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
    IronWaffleMan over 7 years
    Afraid neither of those work. Passing in image.getdata() as the parameter to sess.run gave me: ValueError: Cannot feed value of shape (50176, 3) for Tensor 'DecodeJpeg/contents:0', which has shape '()'. Trying to do image = tf.gfile.FastGFile(image, 'rb').read() gave me TypeError: 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
    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
    IronWaffleMan over 7 years
    I know it does, but I'm not passing it a filename. I'm passing it an image I've modified with PIL.