tf.WholeFileReader() not reading - python

My code seems to find the jpeg image perfectly, because if I mess up the path it will not proceed, also I printed out the return from match_filenames_once and there was the correct list of image files. However the following code does not seem to load the images into the queue. What is wrong with the filename_queue?
Here is my code:
filename_queue = tf.train.string_input_producer(
tf.train.match_filenames_once("./resized2/*.jpg"),shuffle=False)
image_reader = tf.WholeFileReader()
myfilename, image_file = image_reader.read(filename_queue)
image = tf.image.decode_jpeg(image_file)
# Start a new session to show example output.
with tf.Session() as sess:
init_op = tf.global_variables_initializer(), tf.local_variables_initializer()
sess.run(init_op)
# Start populating the filename queue.
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
for i in range(1): #length of your filename list
image_tensor = image.eval() #here is your image Tensor :)
print(myfilename)
print(image.shape)
#Image.fromarray(np.asarray(image_tensor)).show()
coord.request_stop()
coord.join(threads)
Here is the output:
Tensor("ReaderReadV2:0", shape=(), dtype=string)
(?, ?, ?)

Try to print shape of image_tensor
print(image_tensor.shape)
image in your code is Tensor, and it has unknown size, because it come to graph from arbitrary jpeg image, and TF can't define it's size, when TF create graph. But image_tensor is np.array with image loaded from disk.

Related

Adding base64 decoding layer before input layer in Tensorflow Graph

I want to add a layer to decode a base64 string to a numpy array which is a JPEG image. This layer needs to be in front of my original first layer of the model. I want to add a decoding layer because of this way I can reduce the network traffic and the speed.
I consist of a *.pb file which i load into a graph by this I try to manipulate that graph with the graph_editor module of Tensorflow which i'm stuck at.
def decode(entry):
extracted_image = tf.io.decode_jpeg(tf.io.decode_base64(entry))
expanded = tf.expand_dims(extracted_image, axis=0)
resized = tf.image.resize_images(expanded, size=[320, 320])
squeezed = tf.squeeze(resized, axis=0)
return squeezed
with tf.Session() as sess:
print("load graph")
with tf.gfile.FastGFile(GRAPH_PB_PATH, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
sess.graph.as_default()
tf.import_graph_def(graph_def, name='')
graph_nodes = [n for n in graph_def.node]
# Get Graph
g = tf.get_default_graph()
input_feat = tf.placeholder(shape=(), dtype=tf.string, name="input_images_str")
decoded_input = tf.map_fn(decode, input_feat, dtype=tf.float32)
input_tensor = g.get_tensor_by_name("input_images:0")
_conn = graph_editor.connect(decoded_input, input_tensor)
print(_conn)
I also tried connecting the original input_tensor with the decoding layer in Tensorflow.
input_tensor = tf.get_default_graph().get_tensor_by_name("input_images:0")
input_feat = tf.placeholder(shape=(), dtype=tf.string, name="input_images_str")
decoded_input = tf.map_fn(decode, input_feat, dtype=tf.float32)
input_tensor = tf.matmul(decoded_input, input_tensor)
output_tensor = tf.get_default_graph().get_tensor_by_name("feature_fusion/concat_3:0")
# Saving
inputs = {
"input_images_str": input_feat
}
outputs = {"feature_fusion/concat_3": output_tensor}
tf.saved_model.simple_save(
sess, './tf_model/1', inputs, outputs
)
The last method gave this back when making a prediction with a base64 image.
InvalidArgumentError (see above for traceback): You must feed a value for placeholder tensor 'input_images' with dtype float and shape [?,?,?,3]

Loading images in tensorflow queue provides random image instead of FIFO

I am trying to load an image with tensorflow, but I need the files to be in order. When I load the image it loads a random image but not in the order I provided through my initial array. However, my understanding is that string_input_producer(file_names) is FIFO. Why are my images random and how do I make it load images in order?
with open("name.json", 'r') as f:
data = json.load(f)
file_names = []
for i, row in enumerate(data):
load_location = row['location']
file_names.append(load_location)
filename_queue = tf.train.string_input_producer(file_names) # list of files to read
count_num_files = tf.size(file_names)
reader=tf.WholeFileReader()
key,value=reader.read(filename_queue)
img = tf.image.decode_png(value)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
num_files = sess.run(count_num_files)
for i in range(num_files):
# this does not match
location = file_names[i]
# with this image
image_eval=img.eval()
coord.request_stop()
coord.join(threads)
Stupid mistake, string_input_producer shuffle setting defaults to True:
filename_queue = tf.train.string_input_producer(file_names, shuffle=False)

Memory not freed when running TensorFlow Inception v3?

I am trying to classify a set of photos (<10000) using Tensorflow Inception v3.
I'm using the TensorFlow Docker installation CPU Binary image plus source code on a Macbook Air with 4gb DDR3.
I've written a python script to spawn a subprocess to classify each image:
"""
classifier_spawner.py
Runs custom_classify_image.py in subprocess
"""
if __name__ == "__main__":
import sqlite3
import subprocess as sub
from ast import literal_eval
conn = sqlite3.connect("database_name.db")
c = conn.cursor()
c.execute("SELECT * FROM images")
images = c.fetchall()
for image in images:
p = sub.Popen(["python", "custom_classify_image.py", "--image_file=image_dir/" + str(image[0]) + ".jpg"], stdout=sub.PIPE, stderr=sub.PIPE)
output, errors = p.communicate()
categories = literal_eval(output)
for cat in categories:
c.execute("""INSERT OR IGNORE INTO classification (image_id, class_id, probability) VALUES(?,?,?)""", (str(image[0]), str(cat[0]), float(cat[1])))
conn.commit()
print("Classification complete, exiting.")
conn.close()
I have amended run_inference_on_image(image) in classify_image.py as provided with TensorFlow to print a python list of tuples of the top 5 classifications, as shown.
"""My custom run_inference_on_image(image) """
def run_inference_on_image(image):
"""Runs inference on an image.
Args:
image: Image file name.
Returns:
Nothing
"""
if not tf.gfile.Exists(image):
tf.logging.fatal('File does not exist %s', image)
image_data = tf.gfile.FastGFile(image, 'rb').read()
# Creates graph from saved GraphDef.
"""Creates a graph from saved GraphDef file and returns a saver."""
# Creates graph from saved graph_def.pb.
with tf.gfile.FastGFile(os.path.join(
FLAGS.model_dir, 'classify_image_graph_def.pb'), 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
_ = tf.import_graph_def(graph_def, name='')
with tf.Session() as sess:
# Some useful tensors:
# 'softmax:0': A tensor containing the normalized prediction across
# 1000 labels.
# 'pool_3:0': A tensor containing the next-to-last layer containing 2048
# float description of the image.
# 'DecodeJpeg/contents:0': A tensor containing a string providing JPEG
# encoding of the image.
# Runs the softmax tensor by feeding the image_data as input to the graph.
softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')
predictions = sess.run(softmax_tensor,
{'DecodeJpeg/contents:0': image_data})
predictions = np.squeeze(predictions)
# Creates node ID --> English string lookup.
node_lookup = NodeLookup()
top_k = predictions.argsort()[-FLAGS.num_top_predictions:][::-1]
top_k_tup_list = []
for node_id in top_k:
human_string = node_lookup.id_to_string(node_id)
score = predictions[node_id]
top_k_tup_list.append((human_string, score))
sess.close()
print(top_k_tup_list)
My issue is that when I run classifier_spawner.py, after the subprocess has completed, the memory that it used is not freed and after ~10 classifications my disk is full (after writing ~15gb to disk). I then have to delete my virtual machine.
I don't understand why this is happening, shouldn't the virtual memory the subprocess uses be freed after (1) the TensorFlow session is ended and (2) the process has exited?
Thanks in advance, if you need any clarification please let me know.

How to feed Cifar10 trained model with my own image and get label as output?

I am trying to use the trained model based on the Cifar10 tutorial and would like to feed
it with an external image 32x32 (jpg or png).
My goal is to be able to get the label as an output.
In other words, I want to feed the Network with a single jpeg image of size 32 x 32, 3 channels with no label as an input and have the inference process give me the tf.argmax(logits, 1).
Basically I would like to be able to use the trained cifar10 model on an external image and see what class it will spit out.
I have been trying to do that based on the Cifar10 Tutorial and unfortunately always have issues. especially with the Session concept and the batch concept.
Any help doing that with Cifar10 would be greatly appreciated.
Here is the implemented code so far with compilation issues :
#!/usr/bin/env python
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from datetime import datetime
import math
import time
import tensorflow.python.platform
from tensorflow.python.platform import gfile
import numpy as np
import tensorflow as tf
import cifar10
import cifar10_input
import os
import faultnet_flags
from PIL import Image
FLAGS = tf.app.flags.FLAGS
def evaluate():
filename_queue = tf.train.string_input_producer(['/home/tensor/.../inputImage.jpg'])
reader = tf.WholeFileReader()
key, value = reader.read(filename_queue)
input_img = tf.image.decode_jpeg(value)
init_op = tf.initialize_all_variables()
# Problem in here with Graph / session
with tf.Session() as sess:
sess.run(init_op)
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
for i in range(1):
image = input_img.eval()
print(image.shape)
Image.fromarray(np.asarray(image)).show()
# Problem in here is that I have only one image as input and have no label and would like to have
# it compatible with the Cifar10 network
reshaped_image = tf.cast(image, tf.float32)
height = FLAGS.resized_image_size
width = FLAGS.resized_image_size
resized_image = tf.image.resize_image_with_crop_or_pad(reshaped_image, width, height)
float_image = tf.image.per_image_whitening(resized_image) # reshaped_image
num_preprocess_threads = 1
images = tf.train.batch(
[float_image],
batch_size=128,
num_threads=num_preprocess_threads,
capacity=128)
coord.request_stop()
coord.join(threads)
logits = faultnet.inference(images)
# Calculate predictions.
#top_k_predict_op = tf.argmax(logits, 1)
# print('Current image is: ')
# print(top_k_predict_op[0])
# this does not work since there is a problem with the session
# and the Graph conflicting
my_classification = sess.run(tf.argmax(logits, 1))
print ('Predicted ', my_classification[0], " for your input image.")
def main(argv=None):
evaluate()
if __name__ == '__main__':
tf.app.run() '''
Some basics first:
First you define your graph: image queue, image preprocessing, inference of the convnet, top-k accuracy
Then you create a tf.Session() and work inside it: starting the queue runners, and calls to sess.run()
Here is what your code should look like
# 1. GRAPH CREATION
filename_queue = tf.train.string_input_producer(['/home/tensor/.../inputImage.jpg'])
... # NO CREATION of a tf.Session here
float_image = ...
images = tf.expand_dims(float_image, 0) # create a fake batch of images (batch_size=1)
logits = faultnet.inference(images)
_, top_k_pred = tf.nn.top_k(logits, k=5)
# 2. TENSORFLOW SESSION
with tf.Session() as sess:
sess.run(init_op)
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
top_indices = sess.run([top_k_pred])
print ("Predicted ", top_indices[0], " for your input image.")
EDIT:
As #mrry suggests, if you only need to work on a single image, you can remove the queue runners:
# 1. GRAPH CREATION
input_img = tf.image.decode_jpeg(tf.read_file("/home/.../your_image.jpg"), channels=3)
reshaped_image = tf.image.resize_image_with_crop_or_pad(tf.cast(input_img, width, height), tf.float32)
float_image = tf.image.per_image_withening(reshaped_image)
images = tf.expand_dims(float_image, 0) # create a fake batch of images (batch_size = 1)
logits = faultnet.inference(images)
_, top_k_pred = tf.nn.top_k(logits, k=5)
# 2. TENSORFLOW SESSION
with tf.Session() as sess:
sess.run(init_op)
top_indices = sess.run([top_k_pred])
print ("Predicted ", top_indices[0], " for your input image.")
The original source code in cifar10_eval.py can also be used for testing own individual images as it is shown in the following console output
nbatfai#robopsy:~/Robopsychology/repos/gpu/tensorflow/tensorflow/models/image/cifar10$ python cifar10_eval.py --run_once True 2>/dev/null
[ -0.63916457 -3.31066918 2.32452989 1.51062226 15.55279636
-0.91585422 1.26451302 -4.11891603 -7.62230825 -4.29096413]
deer
nbatfai#robopsy:~/Robopsychology/repos/gpu/tensorflow/tensorflow/models/image/cifar10$ python cifar2bin.py matchbox.png input.bin
nbatfai#robopsy:~/Robopsychology/repos/gpu/tensorflow/tensorflow/models/image/cifar10$ python cifar10_eval.py --run_once True 2>/dev/null
[ -1.30562115 12.61497402 -1.34208572 -1.3238833 -6.13368177
-1.17441642 -1.38651907 -4.3274951 2.05489922 2.54187846]
automobile
nbatfai#robopsy:~/Robopsychology/repos/gpu/tensorflow/tensorflow/models/image/cifar10$
and code snippet
#while step < num_iter and not coord.should_stop():
# predictions = sess.run([top_k_op])
print(sess.run(logits[0]))
classification = sess.run(tf.argmalogits[0], 0))
cifar10classes = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]
print(cifar10classes[classification])
#true_count += np.sum(predictions)
step += 1
# Compute precision # 1.
precision = true_count / total_sample_count
# print('%s: precision # 1 = %.3f' % (datetime.now(), precision))
More details can be found in the post How can I test own image to Cifar-10 tutorial on Tensorflow?

How to use image_summary to view images from different batches in Tensorflow?

I am curious about how image_summary works. There is a parameter called max_images, which controls how many images would be shown. However it seems the summary only displays images from one batch. If we use bigger value of max_iamges, we will just view more images from the batch. Is there a way I can view for example one image from each batch?
To view one image from each batch, you need to fetch the result of the tf.image_summary() op every time you run a step. For example, it you have the following setup:
images = ...
loss = ...
optimizer = ...
train_op = optimizer.minimize(loss)
init_op = tf.initialize_all_variables()
image_summary_t = tf.image_summary(images.name, images, max_images=1)
sess = tf.Session()
summary_writer = tf.train.SummaryWriter(...)
sess.run(init_op)
...you could set up your training loop to capture one image per iteration as follows:
for _ in range(10000):
_, image_summary = sess.run([train_op, image_summary_t])
summary_writer.add_summary(image_summary)
Note that capturing summaries on each batch might be inefficient, and you should probably only capture the summary periodically for faster training.
EDIT: The above code writes a separate summary for each image, so your log will contain all of the images, but they will not all be visualized in TensorBoard. If you want to combine your summaries to visualize images from multiple batches, you could do the following:
combined_summary = tf.Summary()
for i in range(10000):
_, image_summary = sess.run([train_op, image_summary_t])
combined_summary.MergeFromString(image_summary)
if i % 10 == 0:
summary_writer.add_summary(combined_summary)
combined_summary = tf.Summary()
I was able to solve this by creating a new image_summary op for each batch. i.e. I went from something that looked like:
train_writer = tf.train.SummaryWriter('summary_dir')
img = tf.image_summary("fooImage", img_data)
for i in range(N_BATCHES):
summary, _ = sess.run([img, train_step])
train_writer.add_summary(summary, i)
(Which, frustratingly, was not doing what I expected.) To...
train_writer = tf.train.SummaryWriter('summary_dir')
for i in range(N_BATCHES):
# Images are sorted in lexicographic order, so zero-pad the name
img = tf.image_summary("fooImage{:06d}".format(i), img_data)
summary, _ = sess.run([img, train_step])
train_writer.add_summary(summary)

Categories

Resources