Image Input Pipeline Using Tensorflow

Purnendu Shukla
Analytics Vidhya
Published in
5 min readJul 16, 2021

--

A simple approach on how to use tf.data API to create an input pipeline for the image dataset

Intro

Hey all,

This is an extension of my previous article and also a hands-on practical guide(theory-part) for applying the knowledge gained to an image data set.

The dataset we are using is a simple one and is used most often for demonstration purposes- Dogs and Cats Dataset(link in reference). However here you can also use a very good extension that does the job of creating a dataset for you.

Creating Dataset

So the dataset I have formed can be created using an extension called ‘Fatkun Batch Download Image’. For using follow these steps:

-> install the application

-> open the images page

-> Start the application

-> Hit Current Tab & Hit the download button.

Make sure you download the images in separate folders, if not it is advised to split them separately into folders as:

Separate Folders

Loading Dataset

Now in the input pipeline, we have tf.data.Dataset.list_files(filepath) which will help us to load file paths from the directory.

So we can load our data as :

> We load our data from GitHub

# loading from github
!git clone ‘https://github.com/DevloperHS/Dockship---Utility.git'

Note: I have been using collab and importing my files from GitHub so the path may change but the overall structure will remain the same:)

> Importing modules

# importing modulesimport tensorflow as tf
import numpy

> Loading Files

image_ds = tf.data.Dataset.list_files('/content/Dockship---Utility/Tf Input Pipeline/images/*/*', shuffle = 'False')# view the files
for i in image_ds.take(5):
print(i.numpy())
includes only file path

As can be seen as of nowimage_ds now only contains the file path and not the actual files. But in a bit, we will be seeing how one can load actual images.

Preprocessing

A general step of any image analysis is to preprocess the raw data into something understandable and in this section, we will look at how we can apply some preprocessing steps to our dataset.

Shuffling

To maintain no bias in our dataset generally, we shuffle/mix our dataset. This can be achieved using shuffle() method as :

image_ds = image_ds.shuffle(200)#view files
for i in image_ds.take(5):
print(i.numpy())
Shuffled Dataset

Splitting

To create our data ready for the model, we need to split our dataset as train and test. In general, we use train_test_split , but as we are working in tensorflow , it provides a simple workaround as described below

We can get len of our dataset, multiply the percentange of data by that length we want to keep for training and use take() and skip() method to perform the split into train_ds and test_ds as:

'''
- use `take` to keep that much of data
- use `skip` to pass the take ammount of data'''# get length of iamge dataset in img_cout
img_count = len(image_ds)
img_count
# define train size
train_size = int (img_count*0.8) # 80% of data
train_size
# perform the split
train_ds = image_ds.take(train_size)
test_ds = image_ds.skip(train_size)
print(len(train_ds))
print(len(test_ds))
Length of the training set
Length of the test set

Mapping

Mapping refers to applying some process or custom function over the entire dataset in one shot. It can be used using map() method.

Here we will be writing few functions which will load labels, entire images from the dataset, and rescale them. Details of each function are given below:

load_labels(file_path)- This function will take in the file_path and returns the labels out of it by using tf.strings.split(file_path, separator)[n] where separator will be os.path.sep :-which separates the file path into its component.

#get labels fndef get_labels(file_path):
import os
return tf.strings.split(file_path , os.path.sep)[-2]

Note: We haven’t used split("/")[n] as the tf.data.dataset is a tensor object and not a list or string, so we need to handle it carefully, please keep in mind using the traditional method will result in an error.

process_image(file_path)- The main function that is responsible for:

  • loading data using tf.io.read_file(file_path)
  • loading labels using get_labels() the function we defined earlier,
  • decode image using tf.image.decode_img_type(img) # optional,
  • resize it using tf.image.resize(file , [dimension])
  • returning images and labels.
def process_img(file_path):
label = get_labels(file_path)
img = tf.io.read_file(file_path)
img = tf.image.decode_jpeg(img)
img = tf.image.resize(img, [224,224])
return img , label

re_scale(img, labels): This function ensures scaling of all values of images array between(0-1) and labels as it is.

def re_scale(img, labels):
return img/255 , labels

Finally applying a map to each function can be done as:

# processing image using fn
train_ds = train_ds.map(process_img)
test_ds = test_ds.map(process_img)
# viewing files
for img, label in train_ds.take(3): # only 3 elementd
print('*** Image', img.numpy()[0][0]) # 1st row
print('*** Label', label.numpy())
Processed Dataset — Not Scaled
# here our file_path is train_ds itself as it hols all the file paths for training set train_ds = train_ds.map(scale)# viewing files
for img, label in train_ds.take(3):
print('img: ', img.numpy()[0][0])
print('labels', label.numpy())
Processed Dataset — Scaled

Since this article is only for demonstration and purpose so I am not including the whole train & deploy pipeline. Also there are many preprocessing that this API can do but not including as I have demonstrated for common cases.

Final Words

With this, we have come to the end of our article. I suggest you practice the coding part as it will be fun and also increases your knowledge base. All the materials used here are provided in the reference section. If you have any queries regarding any code, please leave a comment below, also make sure you share if you liked it.

References

--

--

Purnendu Shukla
Analytics Vidhya

An Aspiring Data Scientist Always Eager To Learn And Share My Knowledge