一文学会YOLO系列算法(从V3到11)实现遥感图像目标检测

目录

前言

数据集介绍

数据集转换

YOLO代码的下载

YOLO的配置

1.数据集的配置

2.模型的配置

YOLO11模型的训练

其它版本YOLO的训练


前言

遥感技术的快速发展,特别是在高分辨率遥感图像的获取能力上的显著提升,已经大大拓宽了遥感数据在环境监测、灾害评估、城市规划及军事侦察等领域的应用范围。在这些应用中,遥感目标检测作为一项基础而关键的技术,其研究和发展受到了广泛关注。遥感目标检测旨在从遥感图像中自动识别并定位地表特定目标,其挑战在于需要处理大尺寸、高复杂度的图像,并且需要在多变的环境条件下保持高准确率和鲁棒性。随着深度学习技术的快速进步,基于深度学习的目标检测算法,尤其是YOLO系列算法,已经成为遥感目标检测领域研究的热点。YOLO算法以其快速、准确的特点,在实时目标检测领域展现出了显著的优势,而其后续版本的不断优化和改进,进一步提升了在遥感图像上的适用性和性能。

数据集介绍

我们使用NWPU VHR-10数据集实现实现遥感图像目标检测。

NWPU VHR-10数据集是一个专为遥感图像目标检测任务设计的高分辨率(Very High Resolution, VHR)遥感图像数据集。它由西北工业大学遥感图像研究团队(NWPU)发布,广泛用于目标检测与相关研究。数据集图像是从谷歌地球和Vaihingen数据集中裁剪出来的,然后由专家手动注释。Vaihingen数据由德国摄影测量、遥感和地理信息学会(DGPF)提供:http://www.ifp.uni-stuttgart.de/dgpf/DKEPAllg.html.

数据集GitHub链接如下:

GitHub - Gaoshuaikun/NWPU-VHR-10: NWPU VHR-10 datasethttps://github.com/Gaoshuaikun/NWPU-VHR-10?tab=readme-ov-filehttps://github.com/Gaoshuaikun/NWPU-VHR-10?tab=readme-ov-filehttps://github.com/Gaoshuaikun/NWPU-VHR-10?tab=readme-ov-filehttps://github.com/Gaoshuaikun/NWPU-VHR-10?tab=readme-ov-file

也可以通过下面的链接直接下载:

NWPU VHR-10 dataset.rar_免费高速下载|百度网盘-分享无限制https://pan.baidu.com/s/1DWibgMXGbC1V5aAuN54JUA?from=init&pwd=1234https://pan.baidu.com/s/1DWibgMXGbC1V5aAuN54JUA?from=init&pwd=1234https://pan.baidu.com/s/1DWibgMXGbC1V5aAuN54JUA?from=init&pwd=1234https://pan.baidu.com/s/1DWibgMXGbC1V5aAuN54JUA?from=init&pwd=1234

数据集一共有10个类别:

airplane飞机
ship
storage tank储罐
baseball diamond棒球场
tennis court网球场
basketball court篮球场
ground track field地面田径场
harbor港口
bridge
vehicle车辆

 该数据集目录如下:

其中,ground truth目录内是每张图像的标签,negative image set是无标签的图像,我们可以将其用作测试,positive image set是有标签的图像,与ground truth内的txt文件按照文件名一一对应。

标签格式如下:

(575,114),(635,162),1 
( 72,305),(133,369),1 
(210,317),(273,384),1 
(306,374),(344,420),1 
(447,531),(535,632),1 
(546,605),(625,707),1 
(632,680),(720,790),1 

每一行都代表一个目标。每一行的格式如下:

(x1,y1),(x2,y2),a

x1,y1表示检测框左上角点的坐标,x2,y2表示右下角点的坐标。a表示类别序号(1-10分别对应飞机-车辆)。

我们可以通过下面的代码,对标签与图像进行可视化。

【代码】show_data.py

from pathlib import Path
import cv2
import numpy as np
import matplotlib.cm as cm


def generate_colors(n, colormap_name='hsv'):
    colormap = cm.get_cmap(colormap_name, n)
    colors = colormap(np.linspace(0, 1, n))
    colors = (colors[:, :3] * 255).astype(np.uint8)  # 将颜色值转换为0到255的整数
    return colors


# 数据集路径
dataset = Path('NWPU VHR-10 dataset')
# 图像路径
images_dir = dataset / 'positive image set'
# 标签路径
ground_truth_dir = dataset / 'ground truth'

# 标签框的颜色
colors = generate_colors(10)[:, ::-1].tolist()
# 标签名
names = ['airplane', 'ship', 'storage tank', 'baseball diamond', 'tennis court', 'basketball court', 'ground track field', 'harbor', 'bridge', 'vehicle']

for image_path in images_dir.glob('*.jpg'):
    image = cv2.imread(str(image_path))
    ground_truth = ground_truth_dir / (image_path.stem + '.txt')

    # 读取标签
    labels = []
    for line in ground_truth.open('r').readlines():
        line = line.replace('\n', '')
        if line:
            labels.append(eval(line))

    # 遍历所有标签
    for (x1, y1), (x2, y2), cls in labels:
        cv2.rectangle(image, (x1, y1), (x2, y2), tuple(colors[cls - 1]), 2)
        cv2.putText(image, names[cls - 1], (x1, y1), cv2.FONT_HERSHEY_SIMPLEX, 0.75, colors[cls - 1], 2)

    cv2.imshow('image', image)
    cv2.waitKey(0)

可视化结果如下:

数据集转换

数据集转换的目的有两个:

  1. 划分数据集。在有标签的数据中划分出训练集与验证集。
  2. 转化标签格式。将标签转化为YOLO能够读取的格式。

(1)数据集划分 

数据集可划分为训练集与验证集。训练集用于训练模型,验证集用于评估模型。通常来说,训练集与测试集数量的比例为7:3,在训练集数据量较小时,可适当调整为8:2。

(2)转化数据集格式

首先说明YOLO数据集的文件结构:

├─images
│  ├─train
│  └─val
└─labels
    ├─train
    └─val

images目录下分为train目录与val目录,分别存放训练集的图像与验证集的图像;labels目录下同样包含train目录与val目录。我们需要把数据集转换为这样的文件结构

图像支持jpg、jpeg、png、bmp等常见格式,标签为txt格式,图像与标签按照文件名一一对应,例如001.jpg的标签为001.txt。

txt文件中,,一行表示一个标签。每个检测框检测框需要由5个信息确定,格式要求如下:

c x y w h

c表示类别,x表示检测框中心点的横坐标,y表示检测框中心点的纵坐标,w表示检测框的宽,h表示检测框的高。五个信息之间用空格分隔。

需要注意的是,x、y、w、h都是归一化之后的值。即若图像的宽高为800, 600,中心点的坐标为(400, 300),检测框的宽为80像素,高为60像素,则

x=400/800=0.5

y=300/600=0.5

w=80/800=0.1

h=60/600=0.1

接下来,我们可以通过以下代码,完成数据集的转换。

【代码】mkdata.py

from pathlib import Path
import random
import cv2
import shutil

# 设置随机数种子
random.seed(0)

# 数据集路径
ground_truth_dir = Path('NWPU VHR-10 dataset/ground truth')
# 图像路径
positive_image_set = Path('NWPU VHR-10 dataset/positive image set')

# 创建一个data目录,用于保存数据
data_dir = Path('data')
data_dir.mkdir(exist_ok=True)

# 创建图像与标签目录
images_dir = data_dir / 'images'
images_dir.mkdir(exist_ok=True)

labels_dir = data_dir / 'labels'
labels_dir.mkdir(exist_ok=True)

# 创建训练集与验证集目录
for set_name in ['train', 'val']:
    (images_dir / set_name).mkdir(exist_ok=True)
    (labels_dir / set_name).mkdir(exist_ok=True)

# 所有图像
image_paths = list(positive_image_set.glob('*.jpg'))
# 所有标签
labels = []
for image_path in image_paths:
    # 读取图像
    image = cv2.imread(str(image_path))
    ground_truth = ground_truth_dir / (image_path.stem + '.txt')
    # 获取图像宽高
    im_h, im_w = image.shape[:2]

    # 读取标签
    lines = []
    for line in ground_truth.open('r').readlines():
        line = line.replace('\n', '')
        if line:
            (x1, y1), (x2, y2), c = eval(line)
            # 计算中心点和宽高
            x = (x1 + x2) / 2
            y = (y1 + y2) / 2
            w = abs(x2 - x1)
            h = abs(y2 - y1)

            # 归一化
            x = x / im_w
            y = y / im_h
            w = w / im_w
            h = h / im_h

            # 把序号变为索引
            c -= 1
            lines.append(f'{c} {x} {y} {w} {h}\n')

    # 保存标签
    labels.append(lines)

# 合并图像路径与标签
data_pairs = list(zip(image_paths, labels))
# 打乱数据
random.shuffle(data_pairs)

# 取80%的数据为训练集,剩下的为测试集
train_size = int(len(data_pairs) * 0.8)
train_set = data_pairs[:train_size]
val_set = data_pairs[train_size:]

# 遍历训练集与测试集
for set_name, dataset in zip(['train', 'val'], [train_set, val_set]):
    # 遍历每张图像与标签
    for image_path, label in dataset:
        # 复制图像到新的文件夹
        shutil.copy2(image_path, images_dir / set_name / image_path.name)
        # 生成标签到新的文件夹
        with open(labels_dir / set_name / (image_path.stem + '.txt'), 'w') as f:
            f.writelines(label)

 运行代码后,项目的目录结构如下:

通过运行代码,生成了data目录,data目录就是YOLO要求的数据集格式。data目录下有images与labels,images用于存放训练集与验证集的图片,labels用于存放训练集与验证集的标签。

YOLO代码的下载

YOLO代码的调用主要依赖于Ultralytics团队开源的ultralytics库。可以通过下面的链接访问ultralytics官网,官网中提供了使用说明与代码案例。通过使用ultralytics库,仅使用几行代码就可以完成YOLO模型的构建。ultralytics库中支持YOLOv3-YOLOv11算法的训练,除了标准的目标检测外,还支持关键点检测、旋转框检测、实例分割等任务。

Home - Ultralytics YOLO Docshttps://docs.ultralytics.com/https://docs.ultralytics.com/https://docs.ultralytics.com/https://docs.ultralytics.com/ultralytics库可以通过pip命令进行安装,不过为了方便后续对代码的修改,建议下载ultralytics库的源码,源码可以通过下面的链接下载。

GitHub - ultralytics/ultralytics: Ultralytics YOLO11 🚀https://github.com/ultralytics/ultralyticshttps://github.com/ultralytics/ultralyticshttps://github.com/ultralytics/ultralyticshttps://github.com/ultralytics/ultralytics若没有加载Git,可以直接点击Download ZIP下载源码

我们打开下载后的代码只有ultralytics这一个目录是我们需要的,其它文件和目录都不需要,我们可以将ultralytics目录复制到项目目录中。

 

YOLO的配置

使用ultralytics的核心是“配置”。

通过对数据的配置,能够将整理好的数据集应用于训练;

同时,通过对模型的配置,能够实现使用不同的YOLO算法进行训练。

1.数据集的配置

首先要建立一个yaml文件,我们可以将其命名为dataset.yaml,yaml文件可以放置在ultralytics的同级目录下。yaml文件内容如下:

path: D:/Projects/Python/work/VHR-10/data
train: images/train
val: images/val
test:

# Classes
names:
  0: airplane
  1: ship
  2: storage tank
  3: baseball diamond
  4: tennis court
  5: basketball court
  6: ground track field
  7: harbor
  8: bridge
  9: vehicle

yaml文件分为5个重要的组成部分:

path数据集的绝对路径
train训练集的图像目录
val验证集的图像目录
test测试集的图像目录
names标签索引与标签名

path为数据集的绝对路径,程序会自动在path路径下寻找images目录与labels目录。

trian为训练集的图像目录,val为验证集的图像目录,这两个目录都是相对于path的路径。程序同时会自动在labels目录中匹配训练集与验证集的标签。

test是测试集的目录,测试集不是必须的,若没有测试集,此项可以置空。

names是索引与标签的对应。此处的索引对应标签格式中的 c(类别)。

至此,数据集的配置完成。

2.模型的配置

ultralytics支持YOLOv3至YOLO11的大多数模型,需要注意的是,YOLOv4与YOLOv7虽然给出了介绍,但实际上并不支持模型的训练。此外,YOLO的第11个版本的命名。并不是“YOLOv11”,而是去掉中间的“v”,命名为YOLO11。

第一步,选择适合的模型并下载预训练权重。

我们以YOLO11为例,点击YOLO11的详情页,向下翻可以找到这样一个表格。

表格记录了YOLO11 5种规格模型的具体信息,模型规模从小到大依次为:n、s、m、l、s。

表格种还提供了模型在COCO数据集中的验证集指标(mAP,越高越好),以及推理时间、参数量、计算量等。我们可以选择合适的模型进行训练,为了实现遥感目标检测,我们使用规格最小的YOLO11n作为演示。

点击YOLO11n的蓝色模型名,即可下载模型的预训练权重,使用预训练权重有助于提升检测精度与收敛速度。

我们可以将下载好的预训练权重放置在ultralytics的同级目录下

第二步,设置训练代码。

在ultralytics的同级目录下,创建文件train.py。此时,代码目录如下:

train.py中,只需要四行代码,就可以完成YOLO模型的训练。代码如下:

【代码】train.py

from ultralytics import YOLO

if __name__ == '__main__':
    yolo = YOLO('yolo11n.yaml')
    yolo.train(data='dataset.yaml', epochs=100, batch=3)

yolo11的配置文件在ultralytics/cfg/models/11/yolo11.yaml中,但我们输入的是yolo11n.yaml,系统将会自动在yolo11.yaml解析规格为n的配置,加载YOLO11n模型。同理,若想使用YOLO11s模型,则指定yolo = YOLO('yolo11s.yaml')即可。

使用此代码进行训练,将自动加载先前下载的yolo11n.pt作为预训练权重,若更改模型,还需要下载其它规格的预训练权重。

YOLO11模型的训练

运行train.py文件,即可开始训练模型。

出现如下界面后,即为训练成功。

等待模型训练完成,得到结果如下: 

从图中我们可以看出,最终所有类别的平均mAP50为0.757,mAP50-95为0.422。

我们也可以看到其它类别的指标,mAP50最高的为地面田径场(ground track field),mAP最低的为篮球场(basketball court)。

训练时,模型会自动生成一个runs目录,我们训练的结果将会保存在runs目录中。

runs目录下会生成一个detect目录与一个mlflow目录,mlflow目录是利用mlflow平台进行训练过程的可视化,我们暂时先不关注这个目录。

detect目录内保存了检测任务的所有训练结果,第一次训练命名为“train”,第二次训练命名为“train2”,以此类推。我们需要找到最后一次训练的目录,查看结果。也可以在训练时控制台的输出中,找到相应的结果目录。

其中,labels.jpg是对标签的统计。

results.png是训练过程中各个指标的记录。

val_batch*_labels.jpg与val_batch*_pred.jpg分别表示验证集的某个batch最终的真实标签与预测结果。

真实标签:

预测结果:

我们可以发现,在245.jpg中,有三个网球场没有识别出来,且误识别了一个飞机;

574.jpg中,误识别了一些飞机;

547.jpg中,桥的识别出现了重叠的情况;

等等。

我们可以根据预测的情况来分析模型的状况,通过观察上面的结果,我们发现模型还有很大的改进空间。

其它版本YOLO的训练

接下来,我们尝试通过YOLOv5算法来实现。

首先打开YOLOv5模型详情页,下载yolov5n模型的权重,并将下载后的权重放置在train.py的同级目录下。

模型修改如下:

【代码】train.py

from ultralytics import YOLO

if __name__ == '__main__':
    # yolo = YOLO('yolo11n.yaml')
    yolo = YOLO('yolov5n.yaml')
    yolo.train(data='dataset.yaml', epochs=100, close_mosaic=0, batch=3)

仅需要将yolo11n.yaml改为yolov5n.yaml,就能实现算法的替换。YOLOv5训练结果如下:

最终的mAP50为0.751,mAP50-95为0.415,略逊于YOLO11。

最后推荐一本书,这本书内集成了YOLO算法应用在内的基于MATLAB实现的将近30个计算机视觉案例,涵盖了计算机视觉的许多实际应用场景,包括图像去雾、答题卡识别、医学影像分割、图像检索等。也可尝试通过PyTorch实现此书内的案例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

G.E.N.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值