2025年3月21日 星期五 甲辰(龙)年 月廿 夜 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > 人工智能

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

时间:02-27来源:作者:点击数:11

前言

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

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

NWPU VHR-10 dataset.rar

数据集一共有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/ultralytics库可以通过pip命令进行安装,不过为了方便后续对代码的修改,建议下载ultralytics库的源码,源码可以通过下面的链接下载。

GitHub - ultralytics/ultralytics: Ultralytics YOLO11 🚀https://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。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐