2023年MathorCup高校数学建模挑战赛—大数据竞赛
A题 基于计算机视觉的坑洼道路检测和识别
原题再现:
坑洼道路检测和识别是一种计算机视觉任务,旨在通过数字图像(通常是地表坑洼图像)识别出存在坑洼的道路。这对于地质勘探、航天科学和自然灾害等领域的研究和应用具有重要意义。例如,它可以帮助在地球轨道上识别坑洼,以及分析和模拟地球表面的形态
在坑洼道路检测任务中,传统的分类算法往往不能取得很好的效果,因为坑洼图像的特征往往是非常复杂和多变的。然而,近年来深度学习技术的发展,为坑洼道路检测提供了新的解决方案。
深度学习具有很强的特征提取和表示能力,可以从图像中自动提取出最重要的特征。在坑洼图像分类任务中,利用深度学习可以提取到坑洼的轮廓、纹理和形态等特征,并将其转换为更容易分类的表示形式。同时,还可以通过迁移学习和知识蒸馏等技术进一步提升分类性能。例如,一些研究者使用基于深度学习的方法对道路图像进行分类,将其分为正常、坑洼两类;另外,一些研究者还使用基于迁移学习的方法,从通用的预训练模型中学习坑洼图像的特征,并利用这些特征来分类坑洼图像。
本赛题希望通过对已标记的道路图像进行分析、特征提取与建模,从而对于一张新的道路图像能够自动识别坑洼状态。具体任务如下:
初赛问题
问题1:结合给出的图像文件,提取图像特征,建立一个识别率高、速度快、分类准确的模型,用于识别图像中的道路是正常或者坑洼。
问题2:对问题1中构建的模型进行训练,并从不同维度进行模型评估,
问题3:利用已训练的模型识别测试集中的坑洼图像,并将识别结果放在“test result.csv”中。
附件说明:
附件1:data.zip;
训练数据集,文件中共包含301张图片。
文件名中包含“normal”字符表示正常道路,否则为坑洼道路。
附件 3:test data.zip;
测试数据集,文件中包含几千张图片。
整体求解过程概述(摘要)
本文主要建立了一个预训练的计算机视觉模型,对坑洼道路进行有效的检测。首先对题目给出的数据集进行数据清洗和分析图像特征,再从CNN中选取四个较为典型的预训练模型进行分别训练,检测,并选出最优、最适合本题的DenseNet-121模型进行训练和多维度评估,并最终对题目给出的数据集进行检测。
针对问题一,对训练数据集进行数据清洗,重新分类错误图片,像素统一处理为224×224 大小,之后进行7:3的训练集和验证集的划分,并提取图像的特征信息。由于题目给出的数据集过少,传统网络模型易出现过拟合现象,会消耗大量计算资源和时间,故本文选用经典的VGG16、DenseNet-121、GoogLeNet和ResNet-50 模型分别训练,对四种模型从多角度分析评估,得到DenseNet-121模型的准确率达到99.34%,平均迭代时间为16.02s,综合评价为四种模型中最佳,故选用 DenseNet-121 模型进行后续的训练与预测。在建立DenseNet-121模型时,首先引入随机种子,加载训练好的参数,对图像进行数据增强处理,以提高模型的泛化能力;冻结模型的权重,以防止预训练的权重被破坏,并添加一个具有128个神经元和ReLU激活函数的全连接层进行二分任务,完成DenseNet-121 模型的建立。
针对问题二,对问题一建立的DenseNet-121模型进行训练和评估。本文从准确率、损失函数、训练速度和鲁棒性等维度进行训练评估。首先测试模型的准确性,将训练好的模型对训练集进行预测,得到了99.34%的准确率,绘制并观察ROC曲线,得到AUC面积为0.98,模型性能良好;之后为测试模型的泛化能力,我们下载了新的681张图片进行预测,发现对于新的数据集模型仍可达到 96.34%的准确率;记录模型的训练耗时信息,得到平均迭代时间16.02s;最后,对图像数据加入扰动,对比其扰动前和扰动后模型的损失率和准确率,发现在50 次的迭代次数下仍可快速的趋于稳定,模型鲁棒性较高,具有识别率高、速度快、分类准确的特点。
针对问题三,将新的数据集同样统一处理为224×224的像素大小,在处理中,发现名为guy7iodk.jpg 的图像无法识别,将其剔除。之后进行特征提取并利用问题二中训练好的模型进行检测,检测过程中生成随机16张图像与检测结果作为可视化示例,将结果存储到test-result.csv 文件中,通过统计发现共有 1256 张图像检测为正常道路,其余3685 张图像为坑洼道路。
模型假设:
为确保构建更为精确的模型,本文依据实际情况对模型做出如下合理的假设:
(1)假设训练数据集中提供的图像数据均是真实有效的。
(2)假设图像中轮廓、纹理、形态等坑洼特征可以通过合适的特征提取方法进行有效捕获。
(3)假设模型在训练过程中,运行环境始终保持稳定。
(4)假设模型的训练结果不受主机显卡等硬件因素的影响。
问题分析:
问题一的分析
针对问题一,首先对题目给出的301 张图像数据集进行了数据清洗和标签化处理,采用CNN卷积神经网络中的预训练模型进行训练和测试。针对数据量小的情况,为确保模型具有高学习效率,且避免过拟合,本文选择预训练模型对测试集进行训练,选取了四个代表性的预训练模型,并按照7:3的比例划分数据集为训练集和验证集,并对比各个模型的不同指标,最终选择最优的模型进行建立并用于图像识别任务。
问题二的分析
针对问题二,本文基于问题一中确定的模型,从不同维度对其进行训练和评估。本文分别从准确率、损失函数、训练速度和鲁棒性评估等方面,通过生成训练集的准确率和损失函数的图像以及对ROC曲线和AUC面积进行分析和评价,判断模型是否有过拟合现象;引入新数据集,评估模型准确率和泛化能力,计算训练耗时与其他模型对比;对训练数据加入扰动,评估其鲁棒性。
问题三的分析
针对问题三,本文首先对题目给出的新的数据集观察分析并进行数据预处理,统一像素大小,保证输入的图像符合模型的需求,之后进行图像数据的特征提取并同问题一,问题二的步骤,对新的数据集进行检测,将检测结果保存在test-result.csv文件中,对检测结果进行可视化展示,展示不同道路类型的数量和占比。
模型的建立与求解整体论文缩略图
全部论文及程序请见下方“ 只会建模 QQ名片” 点击QQ名片即可
程序代码:
程序如下:
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
import h5py
np.random.seed(42)
tf.random.set_seed(42)
data_dir = 'E:\Acode\AAAA\\test_v2.0'
image_height = 224
image_width = 224
batch_size = 16
# 创建DenseNet121模型
base_model = keras.applications.DenseNet121(
weights='imagenet',
include_top=False,
input_shape=(image_height, image_width, 3)
)
# 冻结DenseNet121模型的权重
base_model.trainable = False
# 创建新的模型架构
model = keras.Sequential([
base_model,
keras.layers.GlobalAveragePooling2D(),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
model.summary()
# 数据集划分为训练集和验证集
train_data = ImageDataGenerator(
rescale=1. / 255,
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
validation_split=0.3
)
train_generator = train_data.flow_from_directory(
data_dir,
target_size=(image_height, image_width),
batch_size=batch_size,
class_mode='binary',
shuffle=True,
subset='training',
classes=['normal', 'potholes']
)
validation_generator = train_data.flow_from_directory(
data_dir,
target_size=(image_height, image_width),
batch_size=batch_size,
class_mode='binary',
shuffle=True,
subset='validation',
classes=['normal', 'potholes']
)
epochs = 50
history = model.fit(
train_generator,
steps_per_epoch=len(train_generator),
epochs=epochs,
validation_data=validation_generator,
validation_steps=len(validation_generator)
)
h5_file = 'E:\Acode\AAAA\Lineh5\DenseNet121.h5'
with h5py.File(h5_file, 'w') as f:
for key, value in history.history.items():
f.create_dataset(key, data=value)
def plot_model_performance(history):
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(history.history['accuracy'], label='Train Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
plot_model_performance(history)
# 保存训练好的模型
model.save('E:\Acode\AAAA\\trained_model_DenseNet121.h5')
print("训练好的模型保存完毕。")