Tensorflow image reading & display - python

I've got a bunch of images in a format similar to Cifar10 (binary file, size = 96*96*3 bytes per image), one image after another (STL-10 dataset). The file I'm opening has 138MB.
I tried to read & check the contents of the Tensors containing the images to be sure that the reading is done right, however I have two questions -
Does the FixedLengthRecordReader load the whole file, however just provide inputs one at a time? Since reading the first size bytes should be relatively fast. However, the code takes about two minutes to run.
How to get the actual image contents in a displayable format, or display them internally to validate that the images are read well? I did sess.run(uint8image), however the result is empty.
The code is below:
import tensorflow as tf
def read_stl10(filename_queue):
class STL10Record(object):
pass
result = STL10Record()
result.height = 96
result.width = 96
result.depth = 3
image_bytes = result.height * result.width * result.depth
record_bytes = image_bytes
reader = tf.FixedLengthRecordReader(record_bytes=record_bytes)
result.key, value = reader.read(filename_queue)
print value
record_bytes = tf.decode_raw(value, tf.uint8)
depth_major = tf.reshape(tf.slice(record_bytes, [0], [image_bytes]),
[result.depth, result.height, result.width])
result.uint8image = tf.transpose(depth_major, [1, 2, 0])
return result
# probably a hack since I should've provided a string tensor
filename_queue = tf.train.string_input_producer(['./data/train_X'])
image = read_stl10(filename_queue)
print image.uint8image
with tf.Session() as sess:
result = sess.run(image.uint8image)
print result, type(result)
Output:
Tensor("ReaderRead:1", shape=TensorShape([]), dtype=string)
Tensor("transpose:0", shape=TensorShape([Dimension(96), Dimension(96), Dimension(3)]), dtype=uint8)
I tensorflow/core/common_runtime/local_device.cc:25] Local device intra op parallelism threads: 4
I tensorflow/core/common_runtime/local_session.cc:45] Local session inter op parallelism threads: 4
[empty line for last print]
Process finished with exit code 137
I'm running this on my CPU, if that adds anything.
EDIT: I found the pure TensorFlow solution thanks to Rosa. Apparently, when using the string_input_producer, in order to see the results, you need to initialize the queue runners.
The only required thing to add to the code above is the second line from below:
...
with tf.Session() as sess:
tf.train.start_queue_runners(sess=sess)
...
Afterwards, the image in the result can be displayed with matplotlib.pyplot.imshow(result). I hope this helps someone. If you have any further questions, feel free to ask me or check the link in Rosa's answer.

Just to give a complete answer:
filename_queue = tf.train.string_input_producer(['/Users/HANEL/Desktop/tf.png']) # list of files to read
reader = tf.WholeFileReader()
key, value = reader.read(filename_queue)
my_img = tf.image.decode_png(value) # use png or jpg decoder based on your files.
init_op = tf.global_variables_initializer()
with tf.Session() as sess:
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 = my_img.eval() #here is your image Tensor :)
print(image.shape)
Image.fromarray(np.asarray(image)).show()
coord.request_stop()
coord.join(threads)
Or if you have a directory of images you can add them all via this Github source file
#mttk and #salvador-dali: I hope it is what you need

According to the documentation you can decode JPEG/PNG images.
It should be something like this:
import tensorflow as tf
filenames = ['/image_dir/img.jpg']
filename_queue = tf.train.string_input_producer(filenames)
reader = tf.WholeFileReader()
key, value = reader.read(filename_queue)
images = tf.image.decode_jpeg(value, channels=3)
You can find a bit more info here

After speaking with you in the comments, I believe that you can just do this using numpy/scipy. The ideas is to read the image in the numpy 3d-array and feed it into the variable.
from scipy import misc
import tensorflow as tf
img = misc.imread('01.png')
print img.shape # (32, 32, 3)
img_tf = tf.Variable(img)
print img_tf.get_shape().as_list() # [32, 32, 3]
Then you can run your graph:
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
im = sess.run(img_tf)
and verify that it is the same:
import matplotlib.pyplot as plt
fig = plt.figure()
fig.add_subplot(1,2,1)
plt.imshow(im)
fig.add_subplot(1,2,2)
plt.imshow(img)
plt.show()
P.S. you mentioned: Since it's supposed to parallelize reading, it seems useful to know.. To which I can say that rarely in data-analysis reading of the data is the bottleneck. Most of your time you will spend training your model.

Load names with tf.train.match_filenames_once get the number of files to iterate over with tf.size
open session and enjoy ;-)
import tensorflow as tf
import numpy as np
import matplotlib;
from PIL import Image
matplotlib.use('Agg')
import matplotlib.pyplot as plt
filenames = tf.train.match_filenames_once('./images/*.jpg')
count_num_files = tf.size(filenames)
filename_queue = tf.train.string_input_producer(filenames)
reader=tf.WholeFileReader()
key,value=reader.read(filename_queue)
img = tf.image.decode_jpeg(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):
image=img.eval()
print(image.shape)
Image.fromarray(np.asarray(image)).save('te.jpeg')

(Can't comment, not enough reputation, but here is a modified version that worked for me)
To #HamedMP error about the No default session is registered you can use InteractiveSession to get rid of this error:
https://www.tensorflow.org/versions/r0.8/api_docs/python/client.html#InteractiveSession
And to #NumesSanguis issue with Image.show, you can use the regular PIL .show() method because fromarray returns an image object.
I do both below (note I'm using JPEG instead of PNG):
import tensorflow as tf
import numpy as np
from PIL import Image
filename_queue = tf.train.string_input_producer(['my_img.jpg']) # list of files to read
reader = tf.WholeFileReader()
key, value = reader.read(filename_queue)
my_img = tf.image.decode_jpeg(value) # use png or jpg decoder based on your files.
init_op = tf.initialize_all_variables()
sess = tf.InteractiveSession()
with sess.as_default():
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 = my_img.eval() #here is your image Tensor :)
Image.fromarray(np.asarray(image)).show()
coord.request_stop()
coord.join(threads)

You can use tf.keras API.
import tensorflow as tf
import numpy as np
from tensorflow.keras.preprocessing.image import load_img, array_to_img
tf.enable_eager_execution()
img = load_img("example.png")
img = tf.convert_to_tensor(np.asarray(img))
image = tf.image.resize_images(img, (800, 800))
to_img = array_to_img(image)
to_img.show()

First of all scipy.misc.imread and PIL are no longer available. Instead use imageio library but you need to install Pillow for that as a dependancy
pip install Pillow imageio
Then use the following code to load the image and get the details about it.
import imageio
import tensorflow as tf
path = 'your_path_to_image' # '~/Downloads/image.png'
img = imageio.imread(path)
print(img.shape)
or
img_tf = tf.Variable(img)
print(img_tf.get_shape().as_list())
both work fine.

I used CIFAR10 format instead of STL10 and code came out like
filename_queue = tf.train.string_input_producer(filenames)
read_input = read_cifar10(filename_queue)
with tf.Session() as sess:
tf.train.start_queue_runners(sess=sess)
result = sess.run(read_input.uint8image)
img = Image.fromarray(result, "RGB")
img.save('my.jpg')
The snippet is identical with mttk and Rosa Gronchi, but Somehow I wasn't able to show the image during run-time, so I saved as the JPG file.

Related

How to create a function that returns outputs from tensorflow 1.x model given input?

It might look like a silly question but I have only worked with tf 2.x with eager execution so I have no idea about functionality of tf 1.x. When I run the code twice, (code given below works fine for 1 time) it throws an error. It makes kind of sense because it uses static graphs and all.
Let us suppose we have a code like:
def predict(my_input):
# process the input, access the global `tf1.x` model and return result
return result
QUESTION:
Where exactly am I supposed to put this predict function or how should I create the predict so that I could use it with some serving package like flask / fastapi etc?
This code is extracted from the test_model.py file of the DPED paper
! git clone https://github.com/aiff22/DPED
%cd ./DPED
CODE
import imageio
from PIL import Image
import numpy as np
import tensorflow as tf
from models import resnet
import utils
import os
import sys
import matplotlib.pyplot as plt
# process arguments
phone, dped_dir, test_subset, iteration, resolution, use_gpu = ('iphone_orig', 'dped/', 'full', 'all', 'orig', 'true')
tf.compat.v1.disable_v2_behavior() # disable tf 2.x workings
# get all available image resolutions
res_sizes = utils.get_resolutions()
# get the specified image resolution
IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_SIZE = utils.get_specified_res(res_sizes, phone, resolution)
# disable gpu if specified
config = tf.compat.v1.ConfigProto(device_count={'GPU': 0}) if use_gpu == "false" else None
# create placeholders for input images
x_ = tf.compat.v1.placeholder(tf.float32, [None, IMAGE_SIZE])
x_image = tf.reshape(x_, [-1, IMAGE_HEIGHT, IMAGE_WIDTH, 3])
# generate enhanced image
enhanced = resnet(x_image)
with tf.compat.v1.Session(config=config) as sess:
# load pre-trained model
saver = tf.compat.v1.train.Saver()
saver.restore(sess, "models_orig/" + phone)
########### this is the part which reads the image path and returns the results as enhanced_image ##########
image = np.float16(np.array(Image.fromarray(imageio.imread(path))
.resize([res_sizes[phone][1], res_sizes[phone][0]]))) / 255
image_crop = utils.extract_crop(image, resolution, phone, res_sizes)
image_crop_2d = np.reshape(image_crop, [1, IMAGE_SIZE])
# get enhanced image
enhanced_2d = sess.run(enhanced, feed_dict={x_: image_crop_2d})
enhanced_image = np.reshape(enhanced_2d, [IMAGE_HEIGHT, IMAGE_WIDTH, 3])

TensorFlow : create own dataset for training with different size of image

Hello I continue to learn about the deep learning, so i try to creat my own data set for training.
I have data set of cat and dog(1000 images of cat & 10000 images of dogs) with DIFFERENT size (because I dont find data set with same size) so I need to resize them.
My code return no error but tensorflow doesnt fill my batch and I really dont understand why. It is my first script in deep learning so its complicated for me to find what is it wrong.
I saw this thread : TensorFlow: training on my own image
And the doc of the official web site
code:
import tensorflow as tf #tensor flow
import numpy as np
import glob, os
from pprint import pprint
filenames = list()
os.chdir(".")
for file in glob.glob("*.jpg"):
filenames.append( file)
# filenames = ['im_01.jpg', 'im_02.jpg', 'im_03.jpg', 'im_04.jpg']
filename_queue = tf.train.string_input_producer(filenames)
reader = tf.WholeFileReader()
filename, content = reader.read(filename_queue)
image = tf.image.decode_jpeg(filename, channels=3)
image = tf.cast(image, tf.float32)
resized_image = tf.image.resize_images(image, [224, 224])
image_batch = tf.train.batch([resized_image], batch_size=10000)
print (image_batch)
if I change the batch size, it change nothing to the output.
I really dont know why it doesnt works
print return
Tensor("batch:0", shape=(10000, 224, 224, 3), dtype=float32)
How can I do ?
thanks
thomas

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)

Categories