Road Crack Detection¶
Credit: AITS Cainvas Community
Photo by Teodor Hristov for Lobster on Dribbble
By using the we can assess the quality of the road, Also mark the landmarks where the damage is made and thereby allowing fast repair planning.
In [1]:
from matplotlib import pyplot as plt
import cv2
import numpy as np
from PIL import Image
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers, callbacks, optimizers
from sklearn.metrics import confusion_matrix, f1_score
from tensorflow import keras
import os, shutil
import random
from PIL import Image
Getting the Dataset¶
In [2]:
!wget "https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/Road_Crack_DCSV9HG.zip"
!unzip -qo "Road_Crack.zip"
In [3]:
data_dir = 'Road Crack/'
batch_size = 64
# image_size = (32, 32)
image_size = (28, 28)
print("Training set")
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
color_mode="grayscale",
image_size=image_size,
seed=113,
shuffle=True,
batch_size=batch_size
)
print("Validation set")
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
color_mode="grayscale",
image_size=image_size,
seed=113,
shuffle=True,
batch_size=batch_size
)
As you can see the dataset is containing 40000 images segregation on Postive and Negative with negative having no cracks and positive contains crack
In [4]:
Xtrain = np.empty((0,*image_size,1))
ytrain = np.empty((0,1))
for x in train_ds.enumerate():
for y in x[1][0]:
Xtrain = np.append(Xtrain, np.expand_dims(np.array(y),0), axis = 0)
#print(Xtrain.shape)
ytrain = np.append(ytrain, np.array(x[1][1]))
#print(ytrain.shape)
Xtrain.shape, ytrain.shape
Out[4]:
In [5]:
class_names = train_ds.class_names
print(class_names)
In [6]:
Xval = np.empty((0,*image_size,1))
yval = np.empty((0,1))
for x in val_ds.enumerate():
for y in x[1][0]:
Xval = np.append(Xval, np.expand_dims(np.array(y),0), axis = 0)
#print(Xtrain.shape)
yval = np.append(yval, np.array(x[1][1]))
#print(ytrain.shape)
Xval.shape, yval.shape
Out[6]:
In [7]:
print("Number of samples - ")
for i in range(len(class_names)):
print(class_names[i], "-", yval.tolist().count(float(i)))
Lets visualize the data¶
In [8]:
num_samples = 4 # the number of samples to be displayed in each class
for x in class_names:
plt.figure(figsize=(10, 10))
filenames = os.listdir(data_dir + x)
for i in range(num_samples):
ax = plt.subplot(1, num_samples, i + 1)
img = Image.open(os.path.join(data_dir, x, filenames[i]))
plt.imshow(img)
plt.title(x)
plt.axis("off")
In [9]:
Xtrain = Xtrain/255
Xval = Xval/255
Model¶
In [10]:
model = keras.models.Sequential([
layers.Conv2D(8, 3, activation='relu', input_shape=Xtrain[0].shape),
layers.MaxPool2D(pool_size=(2, 2)),
layers.Conv2D(16, 3, activation='relu'),
layers.MaxPool2D(pool_size=(2, 2)),
layers.Conv2D(32, 3, activation='relu'),
layers.MaxPool2D(pool_size=(2, 2)),
layers.Flatten(),
layers.Dense(32, activation='relu'),
layers.Dense(1, activation='sigmoid')
])
cb = [callbacks.EarlyStopping(monitor = 'val_loss', patience = 5, restore_best_weights = True)]
model.summary()
In [11]:
model.compile(loss=keras.losses.BinaryCrossentropy(), optimizer=optimizers.Adam(0.0001), metrics=['accuracy'])
history = model.fit(Xtrain, ytrain, validation_data=(Xval, yval), epochs=300, callbacks=cb)
In [12]:
model.evaluate(Xval, yval)
ypred = (model.predict(Xval)>0.5).astype('int')
cm = confusion_matrix(yval, ypred)
cm = cm.astype('int') / cm.sum(axis=1)[:, np.newaxis]
fig = plt.figure(figsize = (4, 4))
ax = fig.add_subplot(111)
for i in range(cm.shape[1]):
for j in range(cm.shape[0]):
if cm[i,j] > 0.8:
clr = "white"
else:
clr = "black"
ax.text(j, i, format(cm[i, j], '.2f'), horizontalalignment="center", color=clr)
_ = ax.imshow(cm, cmap=plt.cm.Blues)
ax.set_xticks(range(len(class_names)))
ax.set_yticks(range(len(class_names)))
ax.set_xticklabels(class_names, rotation = 90)
ax.set_yticklabels(class_names)
plt.xlabel('Predicted')
plt.ylabel('True')
plt.show()
Graphs¶
In [13]:
def plot(history, variable1, variable2):
plt.plot(range(len(history[variable1])), history[variable1])
plt.plot(range(len(history[variable2])), history[variable2])
plt.legend([variable1, variable2])
plt.title(variable1)
plot(history.history, "loss", 'val_loss')
In [18]:
plot(history.history, "accuracy", 'val_accuracy')
In [14]:
# pick random test data sample from one batch
x = random.randint(0, 32 - 1) # default batch size is 32
for i in val_ds.as_numpy_iterator():
img, label = i
plt.axis('off') # remove axes
plt.imshow(img[x]) # shape from (64, 64, 64, 1) --> (64, 64, 1)
output = model.predict(np.expand_dims(img[x],0))[0][0] # getting output; input shape (64, 64, 3) --> (1, 64, 64, 1)
pred = (output > 0.5).astype('int')
print("Predicted: ", class_names[pred], '(', output, '-->', pred, ')') # Picking the label from class_names base don the model output
print("True: ", class_names[label[x]])
break
In [15]:
x = random.randint(0, 32 - 1) # default batch size is 32
for i in val_ds.as_numpy_iterator():
img, label = i
plt.axis('off') # remove axes
plt.imshow(img[x]) # shape from (64, 64, 64, 1) --> (64, 64, 1)
output = model.predict(np.expand_dims(img[x],0))[0][0] # getting output; input shape (64, 64, 3) --> (1, 64, 64, 1)
pred = (output > 0.5).astype('int')
print("Predicted: ", class_names[pred], '(', output, '-->', pred, ')') # Picking the label from class_names base don the model output
print("True: ", class_names[label[x]])
break
In [16]:
model.save("road_crack.h5")
DeepCC¶
In [17]:
!deepCC "road_crack.h5"