Dataset description and preprocessing

For this we will be using the Belgian traffic dataset (BelgiumTS for Classification (cropped images)). This dataset can be download from http://btsd.ethz.ch/shareddata/. Here are a quick glimpse about the traffic signs convention in Belgium:

  • Belgian traffic signs are usually in Dutch and French. This is good to know, but for the dataset that you'll be working with, it's not too important!
  • There are six categories of traffic signs in Belgium: warning signs, priority signs, prohibitory signs, mandatory signs, signs related to parking and standing still on the road and, lastly, designatory signs.

Once we download the aforementioned dataset, we will see the following directory structure (training left, test right):

The images are in .ppm format; otherwise we could've used TensorFlow built-in image loader (example, tf.image.decode_png). However, we can use the skimage Python package.

In Python 3, execute $ sudo pip3 install scikit-image for skimage to install and use this package. So let's get started by showing the directory path as follows:

Train_IMAGE_DIR = "<path>/BelgiumTSC_Training/"
Test_IMAGE_DIR = ""<path>/BelgiumTSC_Testing/"

Then let's write a function using the skimage library to read the images and returns two lists:

  • images: A list of Numpy arrays, each representing an image
  • labels: A list of numbers that represent the images labels
def load_data(data_dir):
# All subdirectories, where each folder represents a unique label
directories = [d for d in os.listdir(data_dir)if os.path.isdir(os.path.join(data_dir, d))]

# Iterate label directories and collect data in two lists, labels and images.
labels = []
images = []
for d in directories:label_dir = os.path.join(data_dir, d)
file_names = [os.path.join(label_dir, f)
for f in os.listdir(label_dir) if f.endswith(".ppm")]

# For each label, load it's images and add them to the images list.
# And add the label number (i.e. directory name) to the labels list.
for f in file_names:images.append(skimage.data.imread(f))
labels.append(int(d))
return images, labels

The preceding code block is straightforward and contains inline comments. How about showing related statistics about images? However, before that, let's invoke the preceding function:

# Load training and testing datasets.
train_data_dir = os.path.join(Train_IMAGE_DIR, "Training")
test_data_dir = os.path.join(Test_IMAGE_DIR, "Testing")

images, labels = load_data(train_data_dir)

Then let's see some statistics:

print("Unique classes: {0} 
Total Images: {1}".format(len(set(labels)), len(images)))
>>>
Unique classes: 62
Total Images: 4575

So we have 62 classes to be predicted (that is, a multiclass image classification problem) and we have many images too that should be sufficient to satisfy a smaller CNN.Now let's see the class distribution visually:

# Make a histogram with 62 bins of the `labels` data and show the plot: 
plt.hist(labels, 62)
plt.xlabel('Class')
plt.ylabel('Number of training examples')
plt.show()

Therefore, from the preceding figure, we can see that classes are very imbalanced. However, to make it simpler, we won't take care of this but next, it would be great to visually inspect some files, say displaying the first image of each label:

def display_images_and_labels(images, labels):
unique_labels = set(labels)
plt.figure(figsize=(15, 15))
i = 1
for label in unique_labels:
# Pick the first image for each label.
image = images[labels.index(label)]
plt.subplot(8, 8, i) # A grid of 8 rows x 8 column
splt.axis('off')
plt.title("Label {0} ({1})".format(label, labels.count(label)))
i += 1
_= plt.imshow(image)
plt.show()
display_images_and_labels(images, labels)

Now you can see from the preceding figure that the images come in different sizes and shapes. Moreover, we can see it using Python code, as follows:

for img in images[:5]:
print("shape: {0}, min: {1}, max: {2}".format(img.shape, img.min(), img.max()))
>>>
shape: (87, 84, 3), min: 12, max: 255
shape: (289, 169, 3), min: 0, max: 255
shape: (205, 76, 3), min: 0, max: 255
shape: (72, 71, 3), min: 14, max: 185
shape: (231, 228, 3), min: 0, max: 255

Therefore, we need to apply some pre-processing such as resizing, reshaping, and so on to each image. Let's say each image will have size of 32 x 32:

images32 = [skimage.transform.resize(img, (32, 32), mode='constant') 

for img in images]for img in images32[:5]:
print("shape: {0}, min: {1}, max: {2}".format(img.shape, img.min(), img.max()))
>>>
shape: (32, 32, 3), min: 0.06642539828431372, max: 0.9704350490196079
shape: (32, 32, 3), min: 0.0, max: 1.0
shape: (32, 32, 3), min: 0.03172870710784261, max: 1.0
shape: (32, 32, 3), min: 0.059474571078431314, max: 0.7036305147058846
shape: (32, 32, 3), min: 0.01506204044117481, max: 1.0

Now, all of our images have same size. The next task would be to convert labels and image features as a numpy array:

labels_array = np.array(labels)
images_array = np.array(images32)
print("labels: ", labels_array.shape, "nimages: ", images_array.shape)
>>>
labels: (4575,)
images: (4575, 32, 32, 3)

Fantastic! The next task would be creating our second CNN, but this time we will be using TensorFlow contrib package, which is a high-level API that supports layering ops.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset