Контекст
Бетонные поверхностные трещины являются основным дефектом строительных конструкций. Инспекция здания, которая проводится для оценки жесткости и прочности на растяжение здания. Обнаружение трещин играет важную роль в осмотре здания, обнаружении трещин и определении состояния здания.
Содержание
Наборы данных содержат изображения различных бетонных поверхностей с трещинами и без них. Данные изображения разделены на две части: негативные (без трещин) и позитивные (с трещинами) в отдельной папке для классификации изображений. Каждый класс имеет 20 000 изображений, всего 40 000 изображений размером 227 x 227 пикселей с каналами RGB. Набор данных создается из 458 изображений с высоким разрешением (4032x3024 пикселя) с помощью метода, предложенного Zhang et al (2016). Выяснилось, что изображения с высоким разрешением сильно различаются по качеству обработки поверхности и условиям освещения. Никакого увеличения данных с точки зрения случайного вращения, переворота или наклона не применяется.
Благодарности
Этот набор данных взят с веб-сайта Mendeley Data — Crack Detection, предоставленного Чагларом Фиратом Озгенелем.
Озгенель, Чаглар Фират (2019), Изображения бетонных трещин для классификации, данные Mendeley, v2 http://dx.doi.org/10.17632/5y9wdsg2zt.2
Научно-исследовательская работа
Ссылка на набор данных: - https://www.kaggle.com/arunrk7/surface-crack-detection
ИМПОРТ НЕОБХОДИМЫХ БИБЛИОТЕК
import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import plotly.express as px from sklearn.metrics import confusion_matrix, classification_report import tensorflow as tf from pathlib import Path from sklearn.model_selection import train_test_split
СОЗДАНИЕ СПРАВОЧНИКОВ ДЛЯ ПОЛОЖИТЕЛЬНЫХ И НЕГАТИВНЫХ ИЗОБРАЖЕНИЙ
positive_dir = Path('../input/surface-crack-detection/Positive') negative_dir = Path('../input/surface-crack-detection/Negative')
ФУНКЦИЯ ДОБАВЛЕНИЯ ЭТИКЕТОК К КАЖДОМУ ПУТИ ИЗОБРАЖЕНИЯ
def generate_df(image_dir, label): filepaths = pd.Series(list(image_dir.glob(r'*.jpg')), name='Filepath').astype(str) labels = pd.Series(label, name='Label', index=filepaths.index) df = pd.concat([filepaths, labels], axis=1) return df
СОЗДАНИЕ ОКОНЧАТЕЛЬНОГО ФРЕЙМА ДАННЫХ
positive_df = generate_df(positive_dir, label="POSITIVE") negative_df = generate_df(negative_dir, label="NEGATIVE") df = pd.concat([positive_df, negative_df], axis=0).sample(frac=1.0, random_state=1).reset_index(drop=True) df
РАЗДЕЛЕНИЕ НАБОРА ДАННЫХ НА 70 % ОБУЧАЮЩЕГО НАБОРА И 30 % ТЕСТИРОВАНИЯ
train_df, test_df = train_test_split(df,train_size=0.7,shuffle=True,random_state=42) Image Data Generator generates batches of tensor image data with real-time data augmentation. For more insights check the tensorflow official documentation https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image/ImageDataGenerator train_gen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255,validation_split=0.2) test_gen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255) flow_from_dataframe checks the path available on the dataframe and then automatically search for the image in train directory. Then it make the desired preprocessing steps available in ImageDataGenerator More insights can be found from this article https://vijayabhaskar96.medium.com/tutorial-on-keras-imagedatagenerator-with-flow-from-dataframe-8bd5776e45c1 train_data = train_gen.flow_from_dataframe( train_df, x_col='Filepath', y_col='Label', target_size=(120, 120), color_mode='rgb', class_mode='binary', batch_size=32, shuffle=True, seed=42, subset='training') Found 22400 validated image filenames belonging to 2 classes. val_data = train_gen.flow_from_dataframe( train_df, x_col='Filepath', y_col='Label', target_size=(120, 120), color_mode='rgb', class_mode='binary', batch_size=32, shuffle=True, seed=42, subset='validation') Found 5600 validated image filenames belonging to 2 classes. test_data = train_gen.flow_from_dataframe( test_df, x_col='Filepath', y_col='Label', target_size=(120, 120), color_mode='rgb', class_mode='binary', batch_size=32, shuffle=False, seed=42) Found 12000 validated image filenames belonging to 2 classes.
Обучение модели
inputs = tf.keras.Input(shape=(120, 120, 3)) x = tf.keras.layers.Conv2D(filters=16, kernel_size=(3, 3), activation='relu')(inputs) x = tf.keras.layers.MaxPool2D(pool_size=(2, 2))(x) x = tf.keras.layers.Conv2D(filters=32, kernel_size=(3, 3), activation='relu')(x) x = tf.keras.layers.MaxPool2D(pool_size=(2, 2))(x) x = tf.keras.layers.GlobalAveragePooling2D()(x) outputs = tf.keras.layers.Dense(1, activation='sigmoid')(x) model = tf.keras.Model(inputs=inputs, outputs=outputs) model.compile( optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) print(model.summary()) Model: "model" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) [(None, 120, 120, 3)] 0 _________________________________________________________________ conv2d (Conv2D) (None, 118, 118, 16) 448 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 59, 59, 16) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 57, 57, 32) 4640 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 28, 28, 32) 0 _________________________________________________________________ global_average_pooling2d (Gl (None, 32) 0 _________________________________________________________________ dense (Dense) (None, 1) 33 ================================================================= Total params: 5,121 Trainable params: 5,121 Non-trainable params: 0 _________________________________________________________________
Подгонка модели
history = model.fit(train_data,validation_data=val_data,epochs=10, callbacks=[tf.keras.callbacks.EarlyStopping( monitor='val_loss', patience=3, restore_best_weights=True)]) At the end of 10th epoch we are getting an accuracy of 0.9793 and validation accuracy of 0.9759.
Потери при обучении и валидации с течением времени
fig = px.line( history.history, y=['loss', 'val_loss'], labels={'index': "Epoch", 'value': "Loss"}, title="Training and Validation Loss Over Time") fig.show()
Обучение и проверка точности с течением времени
fig = px.line( history.history, y=['accuracy', 'val_accuracy'], labels={'index': "Epoch", 'value': "Accuracy"}, title="Training and Validation Accuracy Over Time") fig.show()
Оценка модели на тестовом наборе
def evaluate_model(model, test_data): results = model.evaluate(test_data, verbose=0) loss = results[0] acc = results[1] print(" Test Loss: {:.5f}".format(loss)) print("Test Accuracy: {:.2f}%".format(acc * 100)) evaluate_model(model, test_data)
Потеря теста: 0,05720
Точность теста: 97,91%
Точность теста составляет 97,91 %, а потеря при тестировании — 0,05720, что очень хорошо.
Матрица путаницы
y_pred = np.squeeze((model.predict(test_data) >= 0.5).astype(np.int)) cm = confusion_matrix(test_data.labels, y_pred) clr = classification_report(test_data.labels, y_pred, target_names=["NEGATIVE", "POSITIVE"]) plt.figure(figsize=(6, 6)) sns.heatmap(cm, annot=True, fmt='g', vmin=0, cmap='viridis', cbar=False) plt.xticks(ticks=np.arange(2) + 0.5, labels=["NEGATIVE", "POSITIVE"]) plt.yticks(ticks=np.arange(2) + 0.5, labels=["NEGATIVE", "POSITIVE"]) plt.xlabel("Predicted") plt.ylabel("Actual") plt.title("Confusion Matrix") plt.show()
Мы получили 11 749 правильных прогнозов из 12 000 записей в тестовом наборе.
Отчет о классификации
print("Classification Report:\n----------------------\n", clr) Classification Report: ---------------------- precision recall f1-score support NEGATIVE 0.97 0.99 0.98 5991 POSITIVE 0.99 0.97 0.98 6009 accuracy 0.98 12000 macro avg 0.98 0.98 0.98 12000 weighted avg 0.98 0.98 0.98 12000
Вы можете подписаться на меня в Linkedin, Github и Kaggle.
Ссылка на гитхаб
Ссылка на Kaggle
https://www.kaggle.com/ratul6/surface-crack-image-detection-acc-97-91