【2023年MathorCup高校数学建模挑战赛-大数据竞赛】赛道A:基于计算机视觉的坑洼道路检测和识别 python 代码解析

news2024/11/25 11:35:01

【2023年MathorCup高校数学建模挑战赛-大数据竞赛】赛道A:基于计算机视觉的坑洼道路检测和识别 python 代码解析

1 题目

坑洼道路检测和识别是一种计算机视觉任务,旨在通过数字图像(通常是地表坑洼图像)识别出存在坑洼的道路。这对于地.质勘探、航天科学和自然灾害等领域的研究和应用具有重要意义。例如,它可以帮助在地球轨道上识别坑洼,以及分析和模拟地球表面的形态。

在坑洼道路检测任务中,传统的分类算法往往不能取得很好的效果,因为坑洼图像的特征往往是非常复杂和多变的。然而,近年来深度学习技术的发展,为坑洼道路检测提供了新的解决方案。

深度学习具有很强的特征提取和表示能力,可以从图像中自动提取出最重要的特征。在坑洼图像分类任务中,利用深度学习可以提取到坑洼的轮廓、纹理和形态等特征,并将其转换为更容易分类的表示形式。同时,还可以通过迁移学习和知识蒸馏等技术进一步提升分类性能。例如,一些研究者使用基于深度学习的方法对路图像进行分类,将其分为正常、坑洼两类;另外,一些研究者还使用基于迁移学习的方法,从通用的预训练模型中学习坑洼图像的特征,并利用这些特征来分类坑洼图像。

本赛题希望通过对已标记的道路图像进行分析、特征提取与建模,从而对于一张新的道路图像能够自动识别坑洼状态。具体任务如下:
初赛问题
问题1: 结合给出的图像文件,提取图像特征,建立一个识别率高、速度快、分类准确的模型,用于识别图像中的道路是正常或者坑洼。
问題2: 对问题1中构建的模型进行训练,并从不同维度进行模型评估。
问题3: 利用已训练的模型识别测试集中的坑洼图像,并将识别结果放在“test_result.csv’'中。(注:测试集将在竞赛结束前48小时公布下载链接,请及时关注报名网站)

附件说明:
附件1:data.zip;
训练数据集,文件中共包含301张图片。
文件名中包含“normal’'字符表示正常道路,否则为坑洼道路。

在这里插入图片描述

图1:正常道路示例

在这里插入图片描述

图2:坑洼道路示例

附件2:test_result.csv;
测试结果提交文件,文件中表头保持不变,数据仅做示例,提交的时候删除后重新填写,字段描述见下表。
表1:test_result表字段说明

字段说明
fnames测试图片的文件名
label分类标识:填写 1 和 0,1 表示正常道路 ;0 表示坑洼道路

附件3:test_data.zip

测试数据集,文件中包含几千张图片,具体数量以公布的数据为准。

测试数据集在竞赛结束前48小时公布下载链接,请及时关注报名网站。

2 思路分析

首先,训练集只有301张图片,说明这个一个小样本问题。按照以下流程去建立baseline,之后再在每个部分,逐步优化。

(1)数据预处理:

  • 对图像进行尺寸调整:由于深度学习模型对输入图像尺寸要求较为严格,可以使用图像处理算法(如OpenCV库中的resize函数)将图像统一缩放到固定的尺寸。以下例子,统一大小 为224*224。
  • 数据增强:可以使用图像增强算法(如OpenCV库中的平移、旋转、翻转等函数)对图像进行增强,以扩充样本数量和增加数据多样性。

(2)特征提取:

  • 基于传统计算机视觉算法的特征提取:可以使用传统的图像特征提取算法(如SIFT、HOG、LBP等)来提取图像的局部或全局特征,用于训练深度学习模型。
  • 基于深度学习模型的特征提取:可以使用预训练的卷积神经网络(如VGG、ResNet、Inception等)提取图像的高层特征,将这些特征作为输入,用于训练深度学习模型。以下是VGG提取特征为例,见3.3部分。

(3)可视化分析数据集:

  • 使用图像处理算法(如OpenCV库中的imshow函数)显示图像:可以随机选择一些正常道路和坑洼道路的样本图像,并使用图像处理算法将它们可视化显示出来,以了解数据集的特点和难点。
  • 绘制直方图、散点图等统计图表:可以通过统计学手段,如绘制正常道路和坑洼道路图像像素的直方图、颜色特征的散点图等,来观察数据集的分布情况,判断图像特征是否有区分度。

(4)建立深度学习模型:

  • baseline使用卷积神经网络(如VGG、ResNet、Inception等)、自编码器、循环神经网络等,并根据数据集的特点进行微调或迁移学习。
  • 其他前沿的图像分类技术包括
    • 迁移学习:将在大规模数据集上训练好的模型(如ImageNet)迁移到小样本问题上,通过微调或特征提取来解决分类问题。
    • 数据增强:使用图像增强算法(如旋转、平移、翻转、裁剪等)对样本进行扩充,增加样本数量和多样性。
    • 生成对抗网络(GAN):通过合成样本数据来增加样本数量,用GAN生成器生成逼真的样本来扩充数据。
    • 元学习(Meta Learning):学习如何从有限样本中较快地学习和泛化,通过学习到的先验知识来优化样本的利用效率。
    • 半监督学习:利用少量的有标签样本和大量的无标签样本进行训练,提升分类准确率。
    • 主动学习(Active Learning):利用主动选择和标注关键样本,以降低标注成本并提高模型性能。
    • 小样本学习方法:针对小样本问题提出专门的算法和方法,如Few-shot Learning、One-shot Learning、Zero-shot Learning等。
    • 增量学习(Incremental Learning):逐步学习和增量更新模型,以适应新样本的引入和旧样本的遗忘。
    • 模型压缩和量化:通过模型剪枝、量化和蒸馏等技术,减少模型参数和计算量,使其适应小样本问题。
    • 集成学习:将多个分类器的结果进行结合,提高分类准确率和鲁棒性,如bagging、boosting等。

(5)模型评估和优化:

  • 采用交叉验证方法对模型进行评估:可以使用k折交叉验证等方法对模型进行评估,得到准确率、召回率等指标,从而判断模型的性能。
  • 对模型进行调参和优化:可以尝试不同的损失函数、优化器、学习率等超参数,以及增加数据集规模、减少模型复杂度等方式来优化深度学习模型。

3 python代码实现

3.1 数据预处理

import os
import numpy as np
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Activation, Dropout, Flatten, Dense
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.layers import Convolution2D, MaxPooling2D, ZeroPadding2D
from tensorflow.keras import optimizers
from tensorflow.keras import applications
from tensorflow.keras.models import Model
from IPython.display import Image
from tensorflow.keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
import os
from sklearn.model_selection import train_test_split
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import pandas as pd
from PIL import Image
import os

# 将图片统一像素格式,并分别存储到文件夹中

# 创建文件夹
processed_normal_dir = "data/processed_normal"
processed_wavy_dir = "data/processed_wavy"
os.makedirs(processed_normal_dir, exist_ok=True)
os.makedirs(processed_wavy_dir, exist_ok=True)

# 处理图像
data_dir = "data"
for filename in os.listdir(data_dir):
    img_path = os.path.join(data_dir, filename)
    img = Image.open(img_path)
    
    # 对图像进行缩放
    img = img.resize((224, 224))
    
    # 决定图像应该存储在哪个文件夹中
    if "normal" in filename:
        save_dir = processed_normal_dir
    else:
        save_dir = processed_wavy_dir
    # 保存图像
    save_path = os.path.join(save_dir, filename)
    img.save(save_path)

(2)数据加载

总共301张图片,选择30张图片作为测试集,1张图片单独拿出来测试,否则不好整数划分。

img_width, img_height = 224, 224
num_classes = 2
batch_size = 10

datagen = ImageDataGenerator(rescale=1./255)

X = []
y = []
normal_dir = "data/processed_normal"
wavy_dir = "data/processed_wavy"

for img_name in os.listdir(normal_dir):
    img_path = os.path.join(normal_dir, img_name)
    X.append(img_path)
    y.append('0')
for img_name in os.listdir(wavy_dir):
    img_path = os.path.join(wavy_dir, img_name)
    X.append(img_path)
    y.append('1')

X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.1, random_state=42)
train_df = pd.DataFrame(data={'filename': X_train, 'class': y_train})
val_df = pd.DataFrame(data={'filename': X_val, 'class': y_val})

train_generator = datagen.flow_from_dataframe(
        ...略

validation_generator = datagen.flow_from_dataframe(
        ...

Found 270 validated image filenames belonging to 2 classes.
Found 30 validated image filenames belonging to 2 classes.

3.2 卷积模型训练

(1)定义卷积网络

model = Sequential()
model.add(Convolution2D(32, (3, 3), input_shape=(img_width, img_height,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Convolution2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Convolution2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

(2)模型训练

epochs = 20
train_samples = 270
validation_samples = 30
batch_size =10
model.fit_generator(
        train_generator,
        steps_per_epoch=train_samples // batch_size,
        epochs=epochs,
        validation_data=validation_generator,
        validation_steps=validation_samples// batch_size,)

model.save_weights('models/basic_cnn_20_epochs.h5')
model.load_weights('models_trained/basic_cnn_30_epochs.h5')

在这里插入图片描述

(3)模型验证

# 将多余出来的一张图片拿出来预测
img = load_img('data/normal1.jpg')
x = img_to_array(img)
prediction = model.predict(x.reshape((1,img_width, img_height,3)),batch_size=10, verbose=0)
print(prediction)

0

model.evaluate_generator(validation_generator, validation_samples)

[0.7280968427658081, 0.8999999761581421]

3.3 数据增强训练

(1)数据增强

通过对训练集应用随机变换,用新的未见过的图像人为地增强了的数据集。减少过拟合,并为我们的网络提供更好的泛化能力。

train_datagen_augmented = ImageDataGenerator(
        rescale=1./255,        # normalize pixel values to [0,1]
        shear_range=0.2,       # randomly applies shearing transformation
        zoom_range=0.2,        # randomly applies shearing transformation
        horizontal_flip=True)  # randomly flip the images

train_generator_augmented = train_datagen_augmented.flow_from_dataframe(
       ...

(2)模型训练

model.fit_generator(
        train_generator_augmented,
        steps_per_epoch=train_samples // batch_size,
        epochs=epochs,
        validation_data=validation_generator,
        validation_steps=validation_samples // batch_size,)

在这里插入图片描述

(3)模型评估

model.save_weights('models/augmented_20_epochs.h5')
#model.load_weights('models_trained/augmented_30_epochs.h5')

model.evaluate_generator(validation_generator, validation_samples)

[0.2453145980834961, 0.8666666746139526]

3.4 预训练模型

通过使用通用的、预训练的图像分类器,可以在性能和效率方面超越以前的模型。这个例子使用了VGG16,一个在ImageNet数据集上训练的模型,该数据集包含了被分类为1000个类别的数百万张图像。

(1)加载VGG模型的权重

model_vgg =

train_generator_bottleneck = datagen.flow_from_dataframe(
        dataframe=train_df,
        directory=None,
        x_col='filename',
        y_col='class',
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='binary')

validation_generator_bottleneck = datagen.flow_from_dataframe(
        dataframe=val_df,
        directory=None,
        x_col='filename',
        y_col='class',
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='binary')

(2)用模型提取特征

bottleneck_features_train = model_vgg.predict_generator(train_generator_bottleneck, train_samples // batch_size)
np.save(open('models/bottleneck_features_train.npy', 'wb'), bottleneck_features_train)

bottleneck_features_validation = model_vgg.predict_generator(validation_generator_bottleneck, validation_samples // batch_size)
np.save(open('models/bottleneck_features_validation.npy', 'wb'), bottleneck_features_validation)

(3)读取预处理的数据

train_data = np.load(open('models/bottleneck_features_train.npy', 'rb'))
train_labels = np.array([0] * (train_samples // 2) + [1] * (train_samples // 2))

validation_data = np.load(open('models/bottleneck_features_validation.npy', 'rb'))
validation_labels = np.array([0] * (validation_samples // 2) + [1] * (validation_samples // 2))

(4)全连接网络模型训练

model_top = Sequential()
model_top.add(Flatten(input_shape=train_data.shape[1:]))
model_top.add(Dense(256, activation='relu'))
model_top.add(Dropout(0.5))
model_top.add(Dense(1, activation='sigmoid'))

model_top.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])

model_top.fit(train_data, train_labels,
        epochs=epochs, 
        batch_size=batch_size,
        validation_data=(validation_data, validation_labels))

model_top.save_weights('models/bottleneck_20_epochs.h5')

在这里插入图片描述

(5)模型评估

model_top.evaluate(validation_data, validation_labels)

[2.3494818210601807, 0.4333333373069763]

3.5 微调预训练模型

在卷积模型之上建立一个分类器模型。为了进行微调,从一个经过充分训练的分类器开始。将使用早期模型中的权重。然后把这个模型加到卷积基上

weights_path = 'weight/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'
model_vgg = applications.VGG16(include_top=False, weights=weights_path, input_shape=(224, 224, 3))

top_model = Sequential()
top_model.add(Flatten(input_shape=model_vgg.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(1, activation='sigmoid'))

top_model.load_weights('models/bottleneck_20_epochs.h5')

#model_vgg.add(top_model)
model = Model(inputs = model_vgg.input, outputs = top_model(model_vgg.output))
# 微调,只需要训练几层。这一行将设置前25层(直到conv块)为不可训练的。

for layer in model_vgg.layers[:15]:
    layer.trainable = False
    
model.compile(loss='binary_crossentropy',
              optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
              metrics=['accuracy'])

数据增强

# 数据增强
train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1./255)


train_generator = datagen.flow_from_dataframe(
      ...略

validation_generator = datagen.flow_from_dataframe(
        ...

模型微调

# 微调模型
model.fit_generator(
    train_generator,
    steps_per_epoch=train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=validation_samples // batch_size)

model.save_weights('models/finetuning_20epochs_vgg.h5')
model.load_weights('models/finetuning_20epochs_vgg.h5')

在这里插入图片描述

模型评估

model.evaluate_generator(validation_generator, validation_samples)

[nan, 0.8666666746139526]

最后这种方式模型不收敛,说明这个网络设置过程中存在不合理的地方,比如冻结参数的层数,使用的网络模型,是否需要数据增强等因素都会影响。提供这种方式,有待同学们去改进。

4 下载完整程序

以上代码是不完整的,需要完整的请下载后源文件
包括训练好的模型和权重文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1161420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是Babel?它的主要作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

随想录一刷·数组part2

你好&#xff0c;我是安然无虞。 文章目录 1. 有序数组的平方2. 长度最小的最数组3. 螺旋数组II 1. 有序数组的平方 有序数组的平方 class Solution { public:vector<int> sortedSquares(vector<int>& nums) {int n nums.size();// 以0为分割线的话&#xff…

GoLang忽略文件夹

一、忽略 在使用GoLang开发的过程中&#xff0c;我们可能在搜索查找时&#xff0c;需要屏蔽一些日志文件或者编译文件&#xff0c;基于这样的需求&#xff0c;我们可以在GoLang编辑器中右键选择对应的文件夹-》Mark Directory as-》Ecluded。 这样就可以忽略掉对应的文件夹。 …

Django中的FBV和CBV

一、两者的区别 1、在我们日常学习Django中&#xff0c;都是用的FBV&#xff08;function base views&#xff09;方式&#xff0c;就是在视图中用函数处理各种请求。而CBV&#xff08;class base view&#xff09;则是通过类来处理请求。 2、Python是一个面向对象的编程语言…

【Linux】Linux项目部署及更改访问端口号和jdk、tomcat、MySQL环境搭建的配置安装

目录 一、作用 二、配置 1、上传安装包 2、jdk 2.1、解压对应安装包 2.2、环境变量搭建 3、tomcat 3.1、解压对应安装包 3.2、启动 3.3、设置防火墙 3.4、设置开发端口 4、MySQL 三、后端部署 四、Linux部署项目 1、单体项目 五、修改端口访问 1、进入目录 2…

IOS渲染流程之RenderServer处理图层信息

先来回顾一下Android的渲染史&#xff1a; Android的渲染史&#xff1a; Android4.0之前绘制是在主线程执行的&#xff0c;4.0之后除了引入Vsync和双缓冲还引入了单独处理绘制的RenderServer线程。在draw中保存记录绘制指令&#xff0c;稍后RenderServer会取出绘制指令进行调…

MySQL数据库——存储过程-介绍以及基本语法(特点、创建、调用、查看、删除、示例)

目录 介绍 特点 基本语法 创建 调用 查看 删除 示例 介绍 存储过程是事先经过编译并存储在数据库中的一段 SQL 语句的集合&#xff0c;调用存储过程可以简化应用开发人员的很多工作&#xff0c;减少数据在数据库和应用服务器之间的传输&#xff0c;对于提高数据处理…

快速入手maven

文章目录 Maven介绍Maven安装和配置基于IDEA的Maven工程创建梳理Maven工程GAVP属性Idea构建Maven JavaSE工程Idea构建Maven JavaEE工程1. 手动创建2. 插件方式创建 Maven工程项目结构说明Maven核心功能依赖和构建管理依赖传递和冲突依赖导入失败场景和解决方案扩展构建管理和插…

只需 4 个简单步骤即可为您的 ML 系统充电

使用 DALL 生成的图像。D-R型 一、说明 这篇文章将带您了解我通过 4 个简单步骤优化任何 ML 系统以进行闪电般快速的训练和推理的过程。 想象一下&#xff1a;你终于被安排在一个很酷的新ML项目中&#xff0c;你正在训练你的经纪人计算一张照片中有多少只热狗&#xff0c;它的成…

任正非说:人家问我:“你怎么一天到晚游手好闲?”我说我是管长江的堤坝的。

你好&#xff01;这是华研荟【任正非说】系列的第26篇文章&#xff0c;让我们聆听任正非先生的真知灼见&#xff0c;学习华为的管理思想和管理理念。 一、我们不是靠人来领导这个公司&#xff0c;我们用规则的确定性来对付结果的不确定。人家问我&#xff1a;“你怎么一天到晚游…

NEWSTART2022 web week1

01HTTP flag{f1cb35f5-05de-4559-8f99-28e1f11df403} 02Head?Header! 或者xxf头:localhost 03我真的会谢 这个题目比之前有意思多了 可知是vim缓存&#xff0c;利用vim缓存知识&#xff1a; 使用vim时会创建临时缓存文件&#xff0c;关闭vim时缓存文件则会被删除。vim异常…

亚马逊云科技:让生成式AI真正走向普惠

伴随着ChatGPT的横空出世&#xff0c;生成式AI&#xff08;Artificial Intelligence Generated Content&#xff0c;也称AIGC&#xff09;大潮也以锐不可当之势席卷全球。从各行各业的商业领袖&#xff0c;到千千万万的程序员和开发者&#xff0c;都在思考如何借助生成式AI技术…

Leetcode刷题详解——两两交换链表中的节点

1. 题目链接&#xff1a;24. 两两交换链表中的节点 2. 题目描述&#xff1a; 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 …

vue自定义组件:中线分割拖动盘

在GitHub上可以找到类似的组件&#xff0c;比如4年前发布的vue2版本的 Vue Split Pane&#xff0c; 但是我还是自己写了一个类似的&#xff1a; 组件效果&#xff1a; 特点&#xff1a; 不是照抄别人的。同时支持vue2、vue3&#xff08;组件内部使用选项式API风格&#xff09…

【JavaScript保姆级教程】switch分支与while循环

文章目录 前言一、Switch分支1.1 switch基本结构1.2 break语句1.3 default标签1.4 下面是几个Switch分支的示例代码&#xff1a;示例1: 根据星期数输出对应的中文星期名称示例2: 根据用户输入的颜色选择执行不同的操作 二、While循环&#xff1a;2.1 while循环基本格式2.2 cont…

学习性能测试线路图

性能测试学习线路图(建议) 1、概览 纵向划分3颗子树:vugen,controller,monitor。优先学习vugen脚本开发以及调试。 横向划分为2层&#xff1a;基础知识以及高级应用。 2、基础知识 2.1、Loadrunner工具使用 2.1.1、建议学习路径 Vugen开发脚本&#xff08;函数使用&#x…

2.2 - 网络协议 - IP协议,IP地址划分,报文格式,数据分片,抓包实战

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 IP协议 1、IP地址划分2、IP协议报文格式3、IP协议数…

Git(七).git 文件夹瘦身,GitLab 永久删除文件

目录 一、问题背景二、问题复现2.1 新建项目2.2 上传大文件2.3 上传结果 三、解决方案3.1 GitLab备份与还原1&#xff09;备份2&#xff09;还原 3.2 删除方式一&#xff1a;git filter-repo 命令【推荐】1&#xff09;安装2&#xff09;删除本地仓库文件3&#xff09;重新关联…

图的广度优先遍历的单源路径、无权图的最短路径问题、BFS性质附Java代码

目录 使用BFS求解单源路径问题 BFS重要性质 无权图的最短路径问题 使用BFS求解单源路径问题 import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.Queue;public class SingleSourcePath {private Graph G;private i…

Greenplum管理和监控工具-gpcc-web介绍

Greenplum管理和监控工具-gpcc-web介绍 1. gpcc-web简介 ​ gpcc&#xff08;Greenplum Command Center&#xff09;的Web用户界面是一个强大的工具&#xff0c;它可以帮助用户管理Greenplum数据库集群&#xff0c;提高效率&#xff0c;优化性能&#xff0c;并确保数据的安全…