TensorFlow read and decode BATCH of images - python

Using tf.train.string_input_producer and tf.image.decode_jpeg I manage to read from disk and decode a single image.
This is the code:
# -------- Graph
filename_queue = tf.train.string_input_producer(
[img_path, img_path])
image_reader = tf.WholeFileReader()
key, image_file = image_reader.read(filename_queue)
image = tf.image.decode_jpeg(image_file, channels=3)
# Run my network
logits = network.get_logits(image)
# -------- Session
sess = tf.Session()
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
logits_output = sess.run(logits)
The thing is, that when I look at the shape of the logit_outputs I get only 1 value even though the queue is 2 images long.
How can I read and decode the entire queue?

tf.WholeFileReader(), along tf.train.string_input_producer() work as an iterator, and thus does not have an easy way to evaluate the size of the complete dataset it is handling.
To obtain batches of N samples out of it, you could instead use image_reader.read_up_to(filename_queue, N).
Note: you can achieve the same using the newer tf.data pipeline:
def _parse_function(filename):
image_string = tf.read_file(filename)
image_decoded = tf.image.decode_image(image_string)
return image_decoded
# A vector of filenames.
filenames = tf.constant([img_path, img_path])
dataset = tf.data.Dataset.from_tensor_slices((filenames))
dataset = dataset.map(_parse_function).batch(N)
iterator = dataset.make_one_shot_iterator()
next_image_batch = iterator.get_next()
logits = network.get_logits(next_image_batch)
# ...

Related

How to read dataset names from string tensor in tensorflow

I'm new to tensorflow, I have a tensor(string type) in which I have stored image paths of all the required images that i want to use for training a model.
Question : How to read the tensor to queue and then batch it.
My Approach is: Is giving me error
img_names = dataset['f0']
file_length = len(img_names)
type(img_names)
tf_img_names = tf.stack(img_names)
filename_queue = tf.train.string_input_producer(tf_img_names, num_epochs=num_epochs, shuffle=False)
wd=getcwd()
print('In input pipeline')
tf_img_queue = tf.FIFOQueue(file_length,dtypes=[tf.string])
col_Image = tf_img_queue.dequeue(filename_queue)
### Read Image
img_file = tf.read_file(wd+'/'+col_Image)
image = tf.image.decode_png(img_file, channels=num_channels)
image = tf.cast(image, tf.float32) / 255.
image = tf.image.resize_images(image,[image_width, image_height])
min_after_dequeue = 100
capacity = min_after_dequeue + 3 * batch_size
image_batch, label_batch = tf.train.batch([image, onehot], batch_size=batch_size, capacity=capacity, allow_smaller_final_batch = True, min_after_dequeue=min_after_dequeue)
Error : TypeError: expected string or buffer'
I dont know if my approach is right or not
You don't have to create another Queue. You can define a reader that will dequeue elements for you. You can try the following and comment how that goes.
reader = tf.IdentityReader()
key, value = reader.read(filename_queue)
dir = tf.constant(wd)
path = tf.string_join([dir,tf.constant("/"),value])
img_file = tf.read_file(path)
and to check you're feeding correct paths, do
print(sess.run(img_file))
Looking for your feedback.

Trying to expand working code to read multiple JPGs instead of just one into a tensor

I am trying to read in a whole directory into one tensor, with each file in the directory a 28x28 image that is flattened into one row, with each new row representing another image (images are titled 0001.jpg, etc). I have been able to successfully do this for one image but have had no luck creating any loop mechanism to load the files.
I realize this is probably a simple solution but I have no clue how to go about it. If anyone has an example to point me to, or any help would be incredibly appreciated. Thank you.
import numpy as np
import tensorflow as tf
filenames = tf.train.match_filenames_once("C:/train_data/*.jpg")
filename_queue = tf.train.string_input_producer(filenames)
image_reader = tf.WholeFileReader()
_, image_file = image_reader.read(filename_queue)
image_orig = tf.image.decode_jpeg(image_file)
images = tf.image.decode_jpeg(image_file)
images = tf.reshape(images, [-1, 784])
with tf.Session() as sess:
tf.global_variables_initializer().run()
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
image_tensor = sess.run([images])
coord.request_stop()
coord.join(threads)
To load multiple images into the same tensor, you can use tf.train.batch(). For example, to combine 32 images—which must have the same dimensions—into a single tensor, you can modify your program as follows:
filenames = tf.train.match_filenames_once("C:/train_data/*.jpg")
filename_queue = tf.train.string_input_producer(filenames)
image_reader = tf.WholeFileReader()
_, image_file = image_reader.read(filename_queue)
image_orig = tf.image.decode_jpeg(image_file)
images = tf.image.decode_jpeg(image_file)
# `image_batch` contains 32 consecutive images, packed into a single tensor.
image_batch, = tf.train.batch((images,), 32)
If your images might have different sizes, you can use an image-processing function like tf.image.resize_image_with_crop_or_pad() to convert each image to the same shape before passing it to tf.train.batch().

Tensorflow mixes up images and labels when making batch

So I've been stuck on this problem for weeks. I want to make an image batch from a list of image filenames. I insert the filename list into a queue and use a reader to get the file. The reader then returns the filename and the read image file.
My problem is that when I make a batch using the decoded jpg and the labels from the reader, tf.train.shuffle_batch() mixes up the images and the filenames so that now the labels are in the wrong order for the image files. Is there something I am doing wrong with the queue/shuffle_batch and how can I fix it such that the batch comes out with the right labels for the right files?
Much thanks!
import tensorflow as tf
from tensorflow.python.framework import ops
def preprocess_image_tensor(image_tf):
image = tf.image.convert_image_dtype(image_tf, dtype=tf.float32)
image = tf.image.resize_image_with_crop_or_pad(image, 300, 300)
image = tf.image.per_image_standardization(image)
return image
# original image names and labels
image_paths = ["image_0.jpg", "image_1.jpg", "image_2.jpg", "image_3.jpg", "image_4.jpg", "image_5.jpg", "image_6.jpg", "image_7.jpg", "image_8.jpg"]
labels = [0, 1, 2, 3, 4, 5, 6, 7, 8]
# converting arrays to tensors
image_paths_tf = ops.convert_to_tensor(image_paths, dtype=tf.string, name="image_paths_tf")
labels_tf = ops.convert_to_tensor(labels, dtype=tf.int32, name="labels_tf")
# getting tensor slices
image_path_tf, label_tf = tf.train.slice_input_producer([image_paths_tf, labels_tf], shuffle=False)
# getting image tensors from jpeg and performing preprocessing
image_buffer_tf = tf.read_file(image_path_tf, name="image_buffer")
image_tf = tf.image.decode_jpeg(image_buffer_tf, channels=3, name="image")
image_tf = preprocess_image_tensor(image_tf)
# creating a batch of images and labels
batch_size = 5
num_threads = 4
images_batch_tf, labels_batch_tf = tf.train.batch([image_tf, label_tf], batch_size=batch_size, num_threads=num_threads)
# running testing session to check order of images and labels
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)
print image_path_tf.eval()
print label_tf.eval()
coord.request_stop()
coord.join(threads)
Wait.... Isn't your tf usage a little weird?
You are basically running the graph twice by calling:
print image_path_tf.eval()
print label_tf.eval()
And since you are only asking for image_path_tf and label_tf, anything below this line is not even run:
image_path_tf, label_tf = tf.train.slice_input_producer([image_paths_tf, labels_tf], shuffle=False)
Maybe try this?
image_paths, labels = sess.run([images_batch_tf, labels_batch_tf])
print(image_paths)
print(labels)
From your code I'm unsure how your labels are encoded/extracted from the jpeg images. I used to encode everything in the same file, but have since found a much more elegant solution. Assuming you can get a list of filenames, image_paths and a numpy array of labels labels, you can bind them together and operate on individual examples with tf.train.slice_input_producer then batch them together using tf.train.batch.
import tensorflow as tf
from tensorflow.python.framework import ops
shuffle = True
batch_size = 128
num_threads = 8
def get_data():
"""
Return image_paths, labels such that label[i] corresponds to image_paths[i].
image_paths: list of strings
labels: list/np array of labels
"""
raise NotImplementedError()
def preprocess_image_tensor(image_tf):
"""Preprocess a single image."""
image = tf.image.convert_image_dtype(image_tf, dtype=tf.float32)
image = tf.image.resize_image_with_crop_or_pad(image, 300, 300)
image = tf.image.per_image_standardization(image)
return image
image_paths, labels = get_data()
image_paths_tf = ops.convert_to_tensor(image_paths, dtype=tf.string, name='image_paths')
labels_tf = ops.convert_to_tensor(image_paths, dtype=tf.int32, name='labels')
image_path_tf, label_tf = tf.train.slice_input_producer([image_paths_tf, labels_tf], shuffle=shuffle)
# preprocess single image paths
image_buffer_tf = tf.read_file(image_path_tf, name='image_buffer')
image_tf = tf.image.decode_jpeg(image_buffer_tf, channels=3, name='image')
image_tf = preprocess_image_tensor(image_tf)
# batch the results
image_batch_tf, labels_batch_tf = tf.train.batch([image_tf, label_tf], batch_size=batch_size, num_threads=num_threads)

Cannot read image successfully in tensorflow

I want to read the jpeg images into batch for image recognation. The images are in the /Image_p/ file and the image name are listed in the label.csv file, which are presented like 14634_right.
My question is how to fix my code to read the images into batch successfully?
To be more spcific, I don't know whether should I write a for loop and where to implement it.
For the original code, I got the error message on tf.train.shuffle_batch() function:
ValueError: All shapes must be fully defined: [TensorShape([Dimension(None), Dimension(None), Dimension(3)]), TensorShape([])]
My origin code:
# filepath
csv_filepath = r'C:\Users\Jeffy\OneDrive\Course\NMDA\retinaProject\label.csv'
# image parameter
pic_num = 100
pic_height = 64
pic_width = 64
batch_size = 10
# =============================================================================
# import library
import tensorflow as tf
import numpy as np
# =============================================================================
# read csv data
csv = np.loadtxt(open(csv_filepath,"rb"), delimiter=",", dtype='str')
pic_filename = ["" for x in range(pic_num)]
for i in range(pic_num):
pic_filename[i] = eval(csv[i,0]).decode("utf-8") +'.jpeg'
# read the data into batch
for i in range(pic_num):
# read and decode the image
image_contents = tf.read_file('Image_p/' + eval(csv[i,0]).decode("utf-8") +'.jpeg')
image = tf.image.decode_jpeg(image_contents, channels=3)
image = tf.to_float(image)
# Generate batch
batch = tf.train.shuffle_batch([image, float(eval(csv[i,1]))],
batch_size = batch_size,
num_threads = 1,
capacity = batch_size * 100,
min_after_dequeue = batch_size * 10)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
image_tensor = sess.run([batch])
print(batch)
coord.request_stop()
coord.join(threads)
Plus, I have also writen a new file which can read a image successfully (thanks for the help from martianwars).
My test code:
import tensorflow as tf
# read and decode the image
image_contents = tf.read_file('Image_p/11247_left.jpeg')
image = tf.image.decode_jpeg(image_contents, channels=3)
with tf.Session() as sess:
img = sess.run(image)
print(img)
image will have a (?, ?, 3) shape since it's not yet been read, but you have specified the channel in the decode_jpeg() function. Try to print this instead,
with tf.Session() as sess:
img = sess.run(image)
print(img)

Open and convert to tensor an image from CSV file in TensorFlow

I've got the below function, mostly from this question. That person is trying to read five columns that are all ints. I'm trying to read two columns: one an image file path and one an int. So I need to open the file and convert it into a tensor.
So my question is: how do I read the file and convert it into the necessary tensor?
I've tried quite a few different things like reading the file and converting that string to a tensor using .
def read_from_csv(filename_queue):
reader = tf.TextLineReader()
_, csv_row = reader.read(filename_queue)
record_defaults = [[""],[0]]
image_path, label = tf.decode_csv(csv_row, field_delim=" ", record_defaults=record_defaults)
# here's where I need to read the file somehow...
image = tf.read_file(image_path) # I probably need this somewhere
print(image) # Tensor("DecodeJpeg:0", shape=(?, ?, 3), dtype=uint8)
image = tf.image.decode_jpeg(image, channels=3)
return image, label
I also tried using numpy (can't recall exactly what) but that didn't work either.
Ok, here's what I was missing:
def read_from_csv(filename_queue):
reader = tf.TextLineReader()
key, value = reader.read(filename_queue)
record_defaults = [[""],[0]]
image_path, label = tf.decode_csv(value, field_delim=" ", record_defaults=record_defaults)
#following line contains the important change...
image = tf.image.decode_jpeg(tf.read_file(image_path), channels=3)
return image, label
def input_pipeline(batch_size, num_epochs=None):
filename_queue = tf.train.string_input_producer(["./28_dense.csv"], num_epochs=num_epochs, shuffle=True)
image, label = read_from_csv(filename_queue)
image = tf.reshape(image, [28,28,3])
min_after_dequeue = 5
capacity = min_after_dequeue + 3 * batch_size
image_batch, label_batch = tf.train.batch( [image, label], batch_size=batch_size, capacity=capacity)
return image_batch, label_batch
file_length = 1
examples, labels = input_pipeline(file_length, 1)
The step I was missing was simply reading the file with tf.read_file(image_path). I figured decode_jpeg would do that.
Also just a tip: to inspect values of TF stuff (I hesitate to say variables, etc.) create a session like the following:
with tf.Session() as sess:
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
real_value = sess.run([value]) # see value above
print(real_value)

Categories