Cainvas
Model Files
pothole_detection.h5
keras
Model
deepSea Compiled Models
pothole_detection.exe
deepSea
Ubuntu

Pothole Detection

Credit: AITS Cainvas Community

Photo by Jack Last on Dribbble

As we are all aware that Tesla's quest for Self Driving Cars, and we are aware these cars are being developed not just for safety issues of car riders but also to make their journey more comfortable.So, in order to provide comfortable journey it should be able to detect potholes and avoid them.

Importing the Dataste

In [1]:
# This will load the dataset.You will see a folder called ALL in your workspace.
!wget -N "https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/dataset.zip"
!unzip -qo dataset.zip 
!rm dataset.zip
--2020-11-06 06:34:13--  https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/dataset.zip
Resolving cainvas-static.s3.amazonaws.com (cainvas-static.s3.amazonaws.com)... 52.219.62.108
Connecting to cainvas-static.s3.amazonaws.com (cainvas-static.s3.amazonaws.com)|52.219.62.108|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 103508081 (99M) [application/zip]
Saving to: ‘dataset.zip’

dataset.zip         100%[===================>]  98.71M  77.7MB/s    in 1.3s    

2020-11-06 06:34:15 (77.7 MB/s) - ‘dataset.zip’ saved [103508081/103508081]

Importing the libraries

In [2]:
# import libraries

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import cv2
from keras.layers import Dense, Flatten, AveragePooling2D, Dropout
from keras.models import Model
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam

Data Visulization

In [3]:
data_path = "My Dataset/"
In [4]:
# Check images
img = cv2.imread(data_path+"train"+'/'+"Pothole"+"/"+"131.pothole.jpg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
In [5]:
# pothole 
plt.imshow(img)
Out[5]:
<matplotlib.image.AxesImage at 0x7f4a3dadc828>
In [6]:
img.shape
Out[6]:
(396, 863, 3)

Dataset Generation

In [7]:
# Data agumentation on train and test

train_datagen = ImageDataGenerator(rescale = 1./255,
                                   zoom_range = 0.2,
                                   rotation_range=15,
                                   horizontal_flip = True)

test_datagen = ImageDataGenerator(rescale = 1./255)
In [8]:
# create dataset train
training_set = train_datagen.flow_from_directory(data_path + 'train',
                                                 target_size = (224, 224),
                                                 batch_size = 16,
                                                 class_mode = 'categorical',
                                                 shuffle=True)
Found 354 images belonging to 2 classes.
In [9]:
# Create test data set
test_set = test_datagen.flow_from_directory(data_path + 'test',
                                            target_size = (224, 224),
                                            batch_size = 16,
                                            class_mode = 'categorical',
                                            shuffle = False)
Found 16 images belonging to 2 classes.

Model Architecture

In [10]:
# Model creation with changes

model = VGG16(input_shape=(224,224,3),include_top=False)

for layer in model.layers:
    layer.trainable = False

newModel = model.output
newModel = AveragePooling2D()(newModel)
newModel = Flatten()(newModel)
newModel = Dense(128, activation="relu")(newModel)
newModel = Dropout(0.5)(newModel)
newModel = Dense(2, activation='softmax')(newModel)

model = Model(inputs=model.input, outputs=newModel)
In [11]:
model.summary()
Model: "functional_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 224, 224, 3)]     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
_________________________________________________________________
average_pooling2d (AveragePo (None, 3, 3, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 4608)              0         
_________________________________________________________________
dense (Dense)                (None, 128)               589952    
_________________________________________________________________
dropout (Dropout)            (None, 128)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 2)                 258       
=================================================================
Total params: 15,304,898
Trainable params: 590,210
Non-trainable params: 14,714,688
_________________________________________________________________

Model Training

In [12]:
opt=Adam(learning_rate=0.0001)
model.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])
In [13]:
history = model.fit(training_set,
                              validation_data=test_set,
                              epochs=10)    
Epoch 1/10
23/23 [==============================] - 91s 4s/step - loss: 0.6862 - accuracy: 0.6497 - val_loss: 0.4673 - val_accuracy: 0.8125
Epoch 2/10
23/23 [==============================] - 85s 4s/step - loss: 0.4112 - accuracy: 0.8136 - val_loss: 0.3792 - val_accuracy: 0.8125
Epoch 3/10
23/23 [==============================] - 86s 4s/step - loss: 0.2963 - accuracy: 0.8870 - val_loss: 0.3661 - val_accuracy: 0.8125
Epoch 4/10
23/23 [==============================] - 86s 4s/step - loss: 0.2755 - accuracy: 0.8785 - val_loss: 0.3460 - val_accuracy: 0.8125
Epoch 5/10
23/23 [==============================] - 86s 4s/step - loss: 0.2161 - accuracy: 0.9322 - val_loss: 0.3411 - val_accuracy: 0.8125
Epoch 6/10
23/23 [==============================] - 89s 4s/step - loss: 0.1992 - accuracy: 0.9463 - val_loss: 0.4292 - val_accuracy: 0.7500
Epoch 7/10
23/23 [==============================] - 86s 4s/step - loss: 0.1718 - accuracy: 0.9350 - val_loss: 0.3719 - val_accuracy: 0.8125
Epoch 8/10
23/23 [==============================] - 86s 4s/step - loss: 0.1663 - accuracy: 0.9322 - val_loss: 0.3363 - val_accuracy: 0.8750
Epoch 9/10
23/23 [==============================] - 86s 4s/step - loss: 0.1402 - accuracy: 0.9633 - val_loss: 0.3392 - val_accuracy: 0.8750
Epoch 10/10
23/23 [==============================] - 86s 4s/step - loss: 0.1217 - accuracy: 0.9605 - val_loss: 0.3781 - val_accuracy: 0.8125

Tarining Curves

In [14]:
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs=range(len(acc))
In [15]:
plt.plot(epochs,acc,label='Trainin_acc',color='blue')
plt.plot(epochs,val_acc,label='Validation_acc',color='red')
plt.legend()
plt.title("Training and Validation Accuracy")
Out[15]:
Text(0.5, 1.0, 'Training and Validation Accuracy')
In [16]:
plt.plot(epochs,loss,label='Training_loss',color='blue')
plt.plot(epochs,val_loss,label='Validation_loss',color='red')
plt.legend()
plt.title("Training and Validation loss")
Out[16]:
Text(0.5, 1.0, 'Training and Validation loss')

Accessing Model Performance

In [17]:
class_dict = {0:'Plain',
              1:'Pothole'}
In [18]:
# New Data for testing 

file_path =  'My Dataset/test/Plain/2.jpg'
test_image = cv2.imread(file_path)
test_image = cv2.cvtColor(test_image, cv2.COLOR_BGR2RGB)
test_image = cv2.resize(test_image, (224,224),interpolation=cv2.INTER_CUBIC)
plt.imshow(test_image)
test_image = np.expand_dims(test_image,axis=0)
probs = model.predict(test_image)
pred_class = np.argmax(probs)

pred_class = class_dict[pred_class]

if (pred_class == 'Plain'):
    print('Plain Road Detected')
else:
    print('Pothole Detected')
Plain Road Detected
In [19]:
# New Data for testing 

file_path =  'My Dataset/test/Pothole/2.jpg'
test_image = cv2.imread(file_path)
test_image = cv2.cvtColor(test_image, cv2.COLOR_BGR2RGB)
test_image = cv2.resize(test_image, (224,224),interpolation=cv2.INTER_CUBIC)
plt.imshow(test_image)
test_image = np.expand_dims(test_image,axis=0)
probs = model.predict(test_image)
pred_class = np.argmax(probs)

pred_class = class_dict[pred_class]

if (pred_class == 'Plain'):
    print('Plain Road Detected')
else:
    print('Pothole Detected')
Pothole Detected

Saving the Model

In [20]:
model.save("pothole_detection.h5")

Compiling the Model with DeepC Compiler

In [21]:
!deepCC pothole_detection.h5
reading [keras model] from 'pothole_detection.h5'
Saved 'pothole_detection.onnx'
reading onnx model from file  pothole_detection.onnx
Model info:
  ir_vesion :  5 
  doc       : 
WARN (ONNX): graph-node block1_conv1's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block1_conv2's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block2_conv1's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block2_conv2's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block3_conv1's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block3_conv2's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block3_conv3's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block4_conv1's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block4_conv2's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block4_conv3's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block5_conv1's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block5_conv2's attribute auto_pad has no meaningful data.
WARN (ONNX): graph-node block5_conv3's attribute auto_pad has no meaningful data.
WARN (ONNX): terminal (input/output) input_1's shape is less than 1.
             changing it to 1.
WARN (ONNX): terminal (input/output) dense_1's shape is less than 1.
             changing it to 1.
WARN (GRAPH): found operator node with the same name (dense_1) as io node.
running DNNC graph sanity check ... passed.
Writing C++ file  pothole_detection_deepC/pothole_detection.cpp
INFO (ONNX): model files are ready in dir pothole_detection_deepC
g++ -std=c++11 -O3 -I. -I/opt/tljh/user/lib/python3.7/site-packages/deepC-0.13-py3.7-linux-x86_64.egg/deepC/include -isystem /opt/tljh/user/lib/python3.7/site-packages/deepC-0.13-py3.7-linux-x86_64.egg/deepC/packages/eigen-eigen-323c052e1731 pothole_detection_deepC/pothole_detection.cpp -o pothole_detection_deepC/pothole_detection.exe
Model executable  pothole_detection_deepC/pothole_detection.exe