Saving predicted tensor to image in TensorFlow – Graph finalized

Question:

I was able to train a model in TensorFlow with my own data. Input and Output of the model are images. I now tried to get the output of the predictions and save it to an png image file to see what’s going on. Unfortunately I am getting an error when running the following function I created to test with predictions. My goal is to save the prediction that is also an image so I can open it with a normal image viewer.

Some more to the code. In my main I am creating an estimator

def predict_element(my_model, features):
  eval_input_fn = tf.estimator.inputs.numpy_input_fn(
    x=features,
    num_epochs=1,
    shuffle=False)

  eval_results = my_model.predict(input_fn=eval_input_fn)

  predictions = eval_results.next() #this returns a dict with my tensors
  prediction_tensor = predictions["y"] #get the tensor from the dict
  
  image_tensor = tf.reshape(prediction_tensor, [IMG_WIDTH, -1]) #reshape to a matrix due my returned tensor is a 1D flat one
  decoded_image = tf.image.encode_png(image_tensor)
  write_image = tf.write_file("output/my_output_image.png", decoded_image)
  
  with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print(sess.run(write_image))

def get_input():
  filename_dataset = tf.data.Dataset.list_files("features/*.png")
  label_dataset = tf.data.Dataset.list_files("labels/*.png")

  # Make a Dataset of image tensors by reading and decoding the files.
  image_dataset = filename_dataset.map(lambda x: tf.cast(tf.image.decode_png(tf.read_file(x), channels=1),tf.float32))
  l_dataset = label_dataset.map(lambda x: tf.cast(tf.image.decode_png(tf.read_file(x),channels=1),tf.float32))

  image_reshape = image_dataset.map(lambda x: tf.reshape(x, [IM_WIDTH * IM_HEIGHT]))
  label_reshape = l_dataset.map(lambda x: tf.reshape(x, [IM_WIDTH * IM_HEIGHT]))

  iterator = image_reshape.make_one_shot_iterator()
  iterator2 = label_reshape.make_one_shot_iterator()

  next_img = iterator.get_next()
  next_lbl = iterator2.get_next()

  features = []
  labels = []
  # read all 10 images and labels and put it in the array
  # so we can pass it to the estimator
  with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(10):
      t1, t2 = sess.run([next_img, next_lbl])
      features.append(t1)
      labels.append(t2)

  return {"x": np.array(features)}, np.array(labels)

def main(unused_argv):
    features, labels = get_input() # creating the features dict {"x": }
    my_estimator = tf.estimator.Estimator(model_fn=my_cnn_model, model_dir="/tmp/my_model")

    predict_element(my_estimator, features)

The error is

Graph is finalized and cannot be modified

With some easy print() statements I could see that retrieving the dict with

eval_results = my_model.predict(input_fn=eval_input_fn)

is probable the one which finalizes the graph.
I absolutely don’t know what to do or where to look for a solution here. How could I save the output?

I tried this in my model_fn:

#the last layer of my network is dropout
predictions = {
   "y": dropout
    }

  if mode == tf.estimator.ModeKeys.PREDICT:
    reshape1 = tf.reshape(dropout, [-1,IM_WIDTH, IM_HEIGHT])
    sliced = tf.slice(reshape1, [0,0,0], [1, IM_WIDTH, IM_HEIGHT])
    encoded = tf.image.encode_png(tf.cast(sliced, dtype=tf.uint8))
    outputfile = tf.write_file(params["output_path"], encoded)
    return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)

My problem here is that I can’t pass back the "outputfile" node so I can work with it.

Asked By: Talto

||

Answers:

Well your graph is finalized and cannot be modified. You can either add this tensorflow operations to your model (before running it) or simply write some python code which saves the images seperately (without using tensorflow). Maybe I’ll find some old code of mine as an example.

You could also create a second graph, then you can use tensorflow without changing the existing model graph.

You have to distinguish between graph nodes and evaluated objects. tf.reshape doesn’t take an array as input but a graph node.
https://www.tensorflow.org/programmers_guide/graphs

Answered By: Felix

for everyone with the same problem here is my solution. I don’t know if this is the proper way but it works.

In my predict function i created a second graph for the reshaping, slicing, encoding and saving like:

  pred_dict = eval_results.next() #generator the predict function returns
  preds = pred_dict["y"] #get the predictions from the dict

  #create the second graph
  g = tf.Graph()
  with g.as_default():
    inp = tf.Variable(preds)
    reshape1 = tf.reshape(printnode, [IM_WIDTH, IM_HEIGHT, -1])
    sliced = tf.slice(reshape1, [0,0,0], [ IM_WIDTH, IM_HEIGHT,1])
    reshaped = tf.reshape(sliced, [IM_HEIGHT, IM_WIDTH, 1])
    encoded = tf.image.encode_png(tf.image.convert_image_dtype(reshaped,tf.uint16))
    outputfile = tf.write_file("/tmp/pred_output/prediction_img.png", encoded)
    with tf.Session() as sess:
      sess.run(tf.global_variables_initializer())
      sess.run(outputfile)
Answered By: Talto
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.