# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# + colab={"base_uri": "https://localhost:8080/", "height": 35} colab_type="code" id="P608L8jjfs6f" outputId="b3ed6115-be88-41a4-c59e-cca022d4f526"
from google.colab import drive
drive.mount('/content/drive')

# + colab={} colab_type="code" id="HRZcL8BzfH12"
import os
import numpy as np
import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras import Model
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from PIL import Image
import time
import copy
import random
import cv2
import re
import shutil
import pathlib
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
# %matplotlib inline

# + colab={"base_uri": "https://localhost:8080/", "height": 52} colab_type="code" id="DtiMIAPXfH2e" outputId="4d59ed19-cdfe-4d24-97a7-ae192f040afc"
#extract list of images in the folders
base_dir = os.getcwd()
crack_images_path = os.path.join(base_dir, 'drive', 'My Drive', 'Crack_detection', 'training', 'positive')
no_crack_images_path = os.path.join(base_dir, 'drive', 'My Drive', 'Crack_detection', 'training', 'negative')

crack_fnames = os.listdir(crack_images_path)
print("Number of crack images: ", len(crack_fnames))
no_crack_fnames = os.listdir(no_crack_images_path)
print("Number of no crack images: ", len(no_crack_fnames))

# + colab={"base_uri": "https://localhost:8080/", "height": 239} colab_type="code" id="PY-nKMFLfH3C" outputId="15bc1aa6-14ae-475d-c171-e51b7ad1e76a"
# Visualize random crack images
random_numbers = np.random.randint(0, len(crack_fnames), size=2)
random_images = np.array(crack_fnames)[random_numbers.astype(int)]
print("------------crack images--------------")
f, ax = plt.subplots(1,2)
ax[0].imshow(mpimg.imread(os.path.join(crack_images_path, random_images[0])))
ax[1].imshow(mpimg.imread(os.path.join(crack_images_path, random_images[1])))

# + colab={"base_uri": "https://localhost:8080/", "height": 239} colab_type="code" id="bjY-BildfH3Z" outputId="9af46602-379b-4ba4-b98b-8dd96fae07db"
# Visualize random images without crack
random_numbers = np.random.randint(0, len(no_crack_fnames), size=2)
random_images = np.array(no_crack_fnames)[random_numbers.astype(int)]
print("------------images without crack--------------")
f, ax = plt.subplots(1,2)
ax[0].imshow(mpimg.imread(os.path.join(no_crack_images_path, random_images[0])))
ax[1].imshow(mpimg.imread(os.path.join(no_crack_images_path, random_images[1])))


# + colab={"base_uri": "https://localhost:8080/", "height": 329} colab_type="code" id="672LmeKjfH34" outputId="362b936c-2947-40cf-90a5-6ec52685feee"
#create training and validation datasets
def split_data(SOURCE, TRAINING, TESTING, SPLIT_SIZE):
    fnames = os.listdir(SOURCE)
    fnames_filtered = []
    for fname in fnames:
        path = os.path.join(SOURCE, fname)
        if os.path.getsize(path) != 0:
            fnames_filtered.append(fname)
    fnames_shuffled = random.sample(fnames_filtered, len(fnames_filtered))
    size = int(SPLIT_SIZE*len(fnames_filtered))
    train_data = fnames_shuffled[:size]
    test_data = fnames_shuffled[size:]
    for item in train_data:
        source = os.path.join(SOURCE, item)
        destination = os.path.join(TRAINING, item)
        shutil.copyfile(source, destination)
    for file in test_data:
        source = os.path.join(SOURCE, file)
        destination = os.path.join(TESTING, file)
        shutil.copyfile(source, destination)

positive_source_dir = os.path.join(base_dir, 'dataset', 'Positive')
negative_source_dir = os.path.join(base_dir, 'dataset', 'Negative')
train_positive_dir = os.path.join(base_dir, 'crack-v-no_crack', 'training', 'positive')
train_negative_dir = os.path.join(base_dir, 'crack-v-no_crack', 'training', 'negative')
val_positive_dir = os.path.join(base_dir, 'crack-v-no_crack', 'validation', 'positive')
val_negative_dir = os.path.join(base_dir, 'crack-v-no_crack', 'validation', 'negative')
split_size = .8
split_data(positive_source_dir, train_positive_dir, val_positive_dir, split_size)

# + colab={} colab_type="code" id="vUj5EWTnfH4N" outputId="2cf2bc6e-3030-4981-9779-8fb7cd6b20b0"
split_data(negative_source_dir, train_negative_dir, val_negative_dir, split_size)
print(len(os.listdir(train_positive_dir)))
print(len(os.listdir(val_positive_dir)))
print(len(os.listdir(train_negative_dir)))
print(len(os.listdir(val_negative_dir)))

# + colab={"base_uri": "https://localhost:8080/", "height": 1000} colab_type="code" id="C_OPMMUcfH4m" outputId="cc17d1db-22dc-41d2-9472-2ef5a8933e25"
# Create an instance of the inception model from the local pre-trained weights
local_weights_file = os.path.join(base_dir, 'drive', 'My Drive', 'Crack_detection', 'inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5')
# Import the inception model  
from tensorflow.keras.applications.inception_v3 import InceptionV3

pre_trained_model = InceptionV3(input_shape = (227, 227, 3), 
                                include_top = False, 
                                weights = None)

pre_trained_model.load_weights(local_weights_file)

# Make all the layers in the pre-trained model non-trainable
for layer in pre_trained_model.layers:
  layer.trainable = False
  
# Print the model summary
pre_trained_model.summary()

# + colab={"base_uri": "https://localhost:8080/", "height": 35} colab_type="code" id="-geRmFYQfH5H" outputId="259f8597-d505-48f5-e5c3-a9aa4d28a51a"
last_layer = pre_trained_model.get_layer('mixed7')
print('last layer output shape: ', last_layer.output_shape)
last_output = last_layer.output


# + colab={} colab_type="code" id="s9EoCXOLfH5c"
# Define a Callback class that stops training once training accuracy reaches 99.9%
class myCallback(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs={}):
    if(logs.get('accuracy') is not None and logs.get('accuracy')>0.999):
      print("\nReached 99.9% accuracy so cancelling training!")
      self.model.stop_training = True


# + colab={"base_uri": "https://localhost:8080/", "height": 1000} colab_type="code" id="bi_bTFFGfH5u" outputId="f6db334d-4050-4efd-8be3-ac27e832a294"
from tensorflow.keras.optimizers import RMSprop

# Flatten the output layer
x = layers.Flatten()(last_output)
# Add a fully connected layer with 128 hidden units with ReLU activation
x = layers.Dense(128, activation='relu')(x)
# Add a dropout rate of 0.2
x = layers.Dropout(0.2)(x)                  
# Add a final sigmoid layer for classification
x = layers.Dense  (1, activation='sigmoid')(x)           

model = Model( pre_trained_model.input, x) 

model.compile(optimizer = RMSprop(lr=0.0001), 
              loss = 'binary_crossentropy', 
              metrics = ['accuracy'])

model.summary()

# + colab={"base_uri": "https://localhost:8080/", "height": 52} colab_type="code" id="iNgv1wh2fH6A" outputId="ea62257c-1dd3-454e-a640-45c791cf06f9"
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_dir = os.path.join(base_dir, 'drive', 'My Drive', 'Crack_detection', 'training')
validation_dir = os.path.join(base_dir, 'drive', 'My Drive', 'Crack_detection', 'validation')
# Add data-augmentation parameters to ImageDataGenerator
train_datagen = ImageDataGenerator(rescale = 1./255.,
                                   rotation_range = 40,
                                   width_shift_range = 0.2,
                                   height_shift_range = 0.2,
                                   shear_range = 0.2,
                                   zoom_range = 0.2,
                                   horizontal_flip = True,
                                   fill_mode='nearest')

# rescale validation images
val_datagen = ImageDataGenerator( rescale = 1./255. )

# Flow training images in batches of 64 using train_datagen generator
train_generator = train_datagen.flow_from_directory(train_dir,
                                                    batch_size = 64,
                                                    class_mode = 'binary', 
                                                    target_size = (227, 227))     

# Flow validation images in batches of 64 using test_datagen generator
validation_generator =  val_datagen.flow_from_directory( validation_dir,
                                                          batch_size  = 64,
                                                          class_mode  = 'binary', 
                                                          target_size = (227, 227))

# + colab={"base_uri": "https://localhost:8080/", "height": 372} colab_type="code" id="Dm_b4vm9fH6U" outputId="d5a3ef7c-c055-40d6-9bb2-7b2ce35550d5"
callbacks = myCallback()
history = model.fit(
            train_generator,
            validation_data = validation_generator,
            epochs = 10,
            verbose = 2,
            callbacks=[callbacks])

# + colab={"base_uri": "https://localhost:8080/", "height": 354} colab_type="code" id="jzRd_f0cfH6_" outputId="a3e151c6-d127-42b4-ca5d-0fc1603a0f4f"
acc = history.history['accuracy']
print(acc)
val_acc = history.history['val_accuracy']
print(val_acc)
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(acc))

plt.plot(epochs, acc, 'r', label='Training accuracy')
plt.plot(epochs, val_acc, 'b', label='Validation accuracy')
plt.title('Training and validation accuracy')
plt.legend(loc=0)
plt.figure()

plt.show()

# + colab={} colab_type="code" id="1-xNsykWfH7a" outputId="de0a3589-617c-4ab5-ce53-4f0f41d0e17e"
# predicting images using image as input
from tensorflow.keras.preprocessing import image

def predict_image(model, test_image, print_class=False):
    '''predict the test image
    input: model, test_image(raw image), print_class(boolean)
    output: the predicted class(str)'''
    path = os.path.join(os.getcwd(), 'test_images', test_image)
    #test_fnames = os.listdir(test_dir)
    #for fname in test_fnames:
        #path = os.path.join(test_dir, fname)
    img = image.load_img(path, target_size=(227, 227))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x = x/255.
    classes = model.predict(x)
    print(classes)
    if classes[0]>0.5:
        class_name = 'crack'
    else:
        class_name = 'no crack'
    if print_class:
        print(class_name)
    return class_name

predict(model, '06704.jpg',print_class = True)   

# + colab={"base_uri": "https://localhost:8080/", "height": 161} colab_type="code" id="yz5ZTna6fH7t" outputId="f83bc2f9-262b-4e9d-e6aa-aad6a286ab20"
model.save('trained_model')

# + colab={"base_uri": "https://localhost:8080/", "height": 124} colab_type="code" id="wVa9shxsorbH" outputId="97c5b8ed-7295-4db6-cdc9-c5e5424f0e84"
# !zip -r /content/file.zip /content/trained_model

# + colab={"base_uri": "https://localhost:8080/", "height": 34} colab_type="code" id="GQFSS-Qpo1Hh" outputId="4459e163-b5e5-4f09-901a-1c2be7b52325"
from google.colab import files
files.download("/content/file.zip")

# + colab={} colab_type="code" id="An12plrhfH7_"
model = tf.keras.models.load_model('trained_model')
model.summary()

# +
# Select mode of optimization
mode = " " 

if mode == 'Storage':
    optimization = tf.lite.Optimize.OPTIMIZE_FOR_SIZE
elif mode == 'Speed':
    optimization = tf.lite.Optimize.OPTIMIZE_FOR_LATENCY
else:
    optimization = tf.lite.Optimize.DEFAULT

# +
# Convert to tensorflow lite model
converter = tf.lite.TFLiteConverter.from_saved_model('trained_model')

# Set the optimzations
converter.optimizations = [optimization]

# Invoke the converter to finally generate the TFLite model
tflite_model = converter.convert()
# -

tflite_model_file = pathlib.Path('./model.tflite')
tflite_model_file.write_bytes(tflite_model)

# Load TFLite model and allocate tensors.
interpreter = tf.lite.Interpreter(model_path="model.tflite")
interpreter.allocate_tensors()
# Get input and output tensors.
input_index = interpreter.get_input_details()[0]["index"]
output_index = interpreter.get_output_details()[0]["index"]


# +
#predict a single image using tf.lite interpreter
def predict_tlite_one(img, print_class=False):
    '''predict the test image
    input: model, test_image(raw image), print_class(boolean)
    output: the predicted class(str)'''
    #img = np.expand_dims(img, axis=0)
    #img = np.divide(img, 255.)
    input_data = np.array(img, dtype=np.float32)
    interpreter.set_tensor(input_index, input_data)
    interpreter.invoke()
    classes = interpreter.get_tensor(output_index)
    print(classes)
    if classes[0]>0.5:
        class_name = 'Positive'
    else:
        class_name = 'Negative'
    if print_class:
        print(class_name)
    return class_name

#test_image = '06732.jpg'
#path = os.path.join(os.getcwd(), 'test_images', test_image)
#img = cv2.imread(path)
#predict_tlite_one(img, print_class=True)


# +
def predict_tlite_real(input_image, height=227, width=227, save_crops = False):
    path = os.path.join(os.getcwd(), 'real_images', input_image)
    img = cv2.imread(path)
    img_height, img_width, channels = img.shape
    output_image = np.zeros_like(img)
    k=0
    if img_height > 1500:
        slide_h = height
    else:
        slide_h = 113
    if img_width > 1500:
        slide_w = width
    else:
        slide_w = 113
    for i in range(0,img_height,slide_h):
        for j in range(0,img_width,slide_w):
            a = img[i:i+height, j:j+width]
            h, w, c = a.shape
            if h == 227 and w == 227: 
                a_input = np.expand_dims(a, axis=0)
                a_input = a_input/255.
                predicted_class = predict_tlite_one(a_input)
            ## save image
                file, ext = os.path.splitext(input_image)
                image_name = file.split('/')[-1]
                folder_name = 'out_' + image_name
            ## Put predicted class on the cropped image
                if predicted_class == 'Positive':
                    color = (0,0, 255)
                else:
                    color = (0, 255, 0)
                cv2.putText(a, predicted_class, (50,50), cv2.FONT_HERSHEY_SIMPLEX , 0.7, color, 1, cv2.LINE_AA) 
            #b = np.zeros_like(a, dtype=np.uint8)
                b = np.zeros_like(a)
                b[:] = color
                add_img = cv2.addWeighted(a, 0.9, b, 0.1, 0)
            ## Save crops
                if save_crops:
                    if not os.path.exists(os.path.join('real_images', folder_name)):
                        os.makedirs(os.path.join('real_images', folder_name))
                    filename = os.path.join('real_images', folder_name,'img_{}.png'.format(k))
                    cv2.imwrite(filename, add_img)
                output_image[i:i+height, j:j+width,:] = add_img
                k+=1
    ## Save output image
    cv2.imwrite(os.path.join('real_images','predictions', folder_name+ '.jpg'), output_image)
    return output_image

predict_tlite_real('lab_crack1.jpg')
# -

input_image = 'road_surface_crack2.jpg'
path = os.path.join(os.getcwd(), 'real_images', input_image)
img = cv2.imread(path)
img_height, img_width, channels = img.shape
for i in range(0,img_height,500):
    for j in range(0,img_width,500):
        a = img[i:i+500, j:j+500]
        print(a)

# +
# predicting images using single image as input (tensorflow)
from tensorflow.keras.preprocessing import image

def predict(model, img, print_class=False):
    '''predict the test image
    input: model, test_image(raw image), print_class(boolean)
    output: the predicted class(str)'''
    #path = os.path.join(os.getcwd(), 'test_images', test_image)
    #test_fnames = os.listdir(test_dir)
    #for fname in test_fnames:
        #path = os.path.join(test_dir, fname)
    #img = image.load_img(path, target_size=(227, 227))
    #x = image.img_to_array(img)
    img = np.expand_dims(img, axis=0)
    img = img/255.
    classes = model.predict(img)
    print(classes)
    if classes[0]>0.5:
        class_name = 'Positive'
    else:
        class_name = 'Negative'
    if print_class:
        print(class_name)
    return class_name


# -

test_image = '12759_1.jpg'
path = os.path.join(os.getcwd(), 'test_images', test_image)
img = image.load_img(path, target_size=(227, 227))
img = image.img_to_array(img)
predict(model, img,print_class = True) 


# + colab={} colab_type="code" id="USJB2ls8fH8Q"
def predict_real_image(input_image, height=227, width=227, save_crops = False):
    path = os.path.join(os.getcwd(), 'real_images', input_image)
    img = cv2.imread(path)
    img_height, img_width, channels = img.shape
    output_image = np.zeros_like(img)
    k=0
    if img_height > 1500:
        slide_h = height
    else:
        slide_h = 113
    if img_width > 1500:
        slide_w = width
    else:
        slide_w = 113
    for i in range(0,img_height,slide_h):
        for j in range(0,img_width,slide_w):
            a = img[i:i+height, j:j+width]
            h, w, c = a.shape
            if h == 227 and w == 227:           
                predicted_class = predict(model,a)
            ## save image
                file, ext = os.path.splitext(input_image)
                image_name = file.split('/')[-1]
                folder_name = 'out_' + image_name
            ## Put predicted class on the cropped image
                if predicted_class == 'Positive':
                    color = (0,0, 255)
                else:
                    color = (0, 255, 0)
                cv2.putText(a, predicted_class, (50,50), cv2.FONT_HERSHEY_SIMPLEX , 0.7, color, 1, cv2.LINE_AA) 
            #b = np.zeros_like(a, dtype=np.uint8)
                b = np.zeros_like(a)
                b[:] = color
                add_img = cv2.addWeighted(a, 0.9, b, 0.1, 0)
            ## Save crops
                if save_crops:
                    if not os.path.exists(os.path.join('real_images', folder_name)):
                        os.makedirs(os.path.join('real_images', folder_name))
                    filename = os.path.join('real_images', folder_name,'img_{}.png'.format(k))
                    cv2.imwrite(filename, add_img)
                output_image[i:i+height, j:j+width,:] = add_img
                k+=1
    ## Save output image
    cv2.imwrite(os.path.join('real_images','predictions', folder_name+ '.jpg'), output_image)
    return output_image


# + colab={} colab_type="code" id="0qapnTKdfH8i"
predict_real_image('road_surface_crack3.jpg')
# -



StarcoderdataJupyterScriptsDedupFiltered