ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

YOLO 航拍目标检测数据准备实战:ultralytics.data.split_dota 切分工具完整解析

YOLO 航拍目标检测数据准备实战:ultralytics.data.split_dota 切分工具完整解析 YOLO 航拍目标检测数据准备实战ultralytics.data.split_dota 切分工具完整解析【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10导读DOTA 是面向航拍图像的目标检测基准数据集其原始图像尺寸从 800×800 到 20,000×20,000 像素不等远超常规检测模型的输入分辨率无法直接送入 YOLO 训练。本文以仓库中 split_dota.py 为对象完整解析其 8 个核心函数从滑动窗口生成、IOF 交叠率计算、目标归属判定到图像裁剪与标签坐标重写再到 train/val/test 的切分入口。读完本文你将能够独立使用该工具把任意 DOTA 目录结构切分为可直接喂给 YOLOv8-obb / YOLOv10 训练的 1024×1024 多尺度子图数据集并理解每个参数背后的实现原理。一、为什么 DOTA 需要切分DOTAA Detailed Oriented Text Annotation数据集专门面向航拍图像中的定向目标检测Oriented Bounding Box, OBB。它由多源传感器与平台采集单张图像尺寸跨度极大最大可达 20000×20000 像素。若直接将其 resize 到模型输入尺寸小目标如飞机、车辆、集装箱吊车会因下采样而丢失若整图送入网络内存与显存开销也无法接受。因此官方与 Ultralytics 的做法一致先将原始大图按滑动窗口切分为固定尺寸的子图默认 1024×1024同时把落在窗口内的目标标注随窗口裁剪、重写坐标再以切分后的子图训练。仓库 docs/en/datasets/obb/dota-v2.md 中的 Split DOTA images 一节即示范了这一流程。切分后的数据通过 DOTAv1.yaml 或轻量级 dota8.yaml 配置即可接入yolo obb train训练管线。二、模块概览与依赖split_dota.py位于 ultralytics/data/split_dota.py顶层自动执行check_requirements(shapely)校验依赖缺失时会提示安装。其余依赖包括opencv-pythoncv2图像读取与裁剪写盘numpy窗口坐标、标签矩阵的向量化运算PILImage读取原始图尺寸shapelyPolygon 多边形求交与面积计算用于 IOFtqdm切分进度条ultralytics.data.utils中的exif_size与img2label_paths。模块共导出 8 个函数形成一条清晰的流水线函数职责bbox_iof计算旋转多边形标注与水平窗口之间的交叠率IOFload_yolo_dota按 DOTA 目录结构加载某 split 的图像与标签get_windows依据图像尺寸生成滑动窗口坐标get_window_obj判定每个窗口内包含哪些目标crop_and_save裁剪子图并写出新标签split_images_and_labels组合上述步骤切分单个 splitsplit_trainval切分 train val 两个 split多尺度入口split_test切分无标签的 test 集三、核心函数逐个解析3.1 bbox_iof旋转框与窗口的交叠率def bbox_iof(polygon1, bbox2, eps1e-6): Calculate iofs between bbox1 and bbox2.polygon1形状为(n, 8)的数组每行是 8 个坐标值即四边形的 4 个角点DOTA 标注为 8 自由度任意四边形而非普通旋转矩形bbox2形状为(m, 4)的水平边界框即滑动窗口格式[x1, y1, x2, y2]返回值(n, m)矩阵第(i, j)项为第i个多边形与第j个窗口的交叠率。实现上分两步首先用np.min/np.max把旋转多边形约简为水平包围框用向量化方式快速筛出与窗口可能有交叠的候选对交叠面积h_overlaps大于 0再对候选对用 shapely 的Polygon.intersection(...).area计算精确的旋转四边形交集面积除以多边形自身面积得到 IOF。分子是交集面积分母是对象自身面积这正是 Intersection over Foreground 的定义——它衡量目标有多少比例落在窗口内而非传统的 IoU交并比。eps用于避免除零。3.2 load_yolo_dota按 YOLO 格式加载 DOTA 标注def load_yolo_dota(data_root, splittrain): Load DOTA dataset.要求split只能是train或val并假定如下目录结构data_root ├── images │ ├── train │ └── val └── labels ├── train └── val函数通过glob枚举images/split/*下的全部图像再调用 img2label_paths该工具函数将路径中的/images/段替换为/labels/并把扩展名换为.txt得到对应标签路径。随后用 exif_size 读取 EXIF 校正后的原始尺寸(w, h)将每行class_id x1 y1 x2 y2 ...的标签解析为 float32 矩阵。最终返回列表每项为字典{ori_size: (h, w), label: np.ndarray, filepath: str}注意此时标签仍是 DOTA 原始格式——前两列是归一化到图像宽高的坐标1、3 列除以 w2、4 列除以 h与训练阶段 YOLO OBB 标签的存储约定一致。3.3 get_windows滑动窗口坐标生成def get_windows(im_size, crop_sizes[1024], gaps[200], im_rate_thr0.6, eps0.01):im_size原始图像尺寸(h, w)crop_sizes窗口边长列表支持多尺度如[1024]或[2048, 1024]gaps相邻窗口重叠区的宽度步长 crop_size - gapim_rate_thr窗口在图像内的有效面积占比阈值默认 0.6返回(k, 4)的 int64 数组每行为[x1, y1, x2, y2]。核心逻辑逐对遍历crop_sizes与gaps断言crop_size gap否则报错invalid crop_size gap pair计算step crop_size - gap分别求出 x、y 方向的切分数量ceil((w - crop_size) / step 1)图像小于窗口时取 1用itertools.product生成网格起点起点加边长得到终点构成[x1, y1, x2, y2]对越界窗口做坐标裁剪计算窗口有效面积占比im_rates剔除占比低于阈值的边缘窗口若所有窗口都低于阈值则保留有效面积最大的窗口容差eps。这一阈值机制保证了切分出的子图不会因大面积落在图像之外而浪费训练样本。3.4 get_window_obj目标归属判定def get_window_obj(anno, windows, iof_thr0.7):annoload_yolo_dota返回的单张图字典windowsget_windows产生的窗口坐标iof_thr目标保留阈值默认 0.7。实现上先将归一化标签坐标还原为像素坐标label[:, 1::2] * w、label[:, 2::2] * h即第 1、3、5、7 列乘宽第 2、4、6、8 列乘高随后调用bbox_iof得到每个目标与每个窗口的 IOF 矩阵。iofs[:, i] iof_thr选出与第 i 个窗口交叠率达到 70%的目标作为该窗口的子标签。若某图没有任何标注则为每个窗口返回(0, 9)的空矩阵——9 列对应class_id 8 个坐标。3.5 crop_and_save裁剪子图并重写标签def crop_and_save(anno, windows, window_objs, im_dir, lb_dir):对每个窗口执行用cv2.imread读入原图按im[y_start:y_stop, x_start:x_stop]裁剪子图按如下约定命名保证可从文件名反推出在原图中的位置{原图stem}__{窗口宽}__{x_start}___{y_start}.jpg例如P0003__1024__0___0.jpg将窗口内目标的像素坐标相对窗口左上角平移label[:, 1::2] - x_start、label[:, 2::2] - y_start再除以子图宽高pw/ph重新归一化以{:.6g}格式化坐标写入同名.txt标签文件每行格式class_id x1 y1 x2 y2 x3 y3 x4 y4。空窗口只写图像、跳过标签文件保证标签与图像一一对应。3.6 split_images_and_labels单 split 完整切分def split_images_and_labels(data_root, save_dir, splittrain, crop_sizes[1024], gaps[200]):在save_dir下创建images/split与labels/split目录依次对每张图执行load_yolo_dota → get_windows → get_window_obj → crop_and_save并用 tqdm 显示进度。输出目录结构与输入完全同构save_dir ├── images │ └── split └── labels └── split四、多尺度切分与 train/val/test 入口4.1 split_trainval带标签的 train/val 切分def split_trainval(data_root, save_dir, crop_size1024, gap200, rates[1.0]):rates用于生成多尺度窗口对每个比例r实际窗口为crop_size / r、间隙为gap / r。例如 DOTA 官方文档 dota-v2.md 中的示例from ultralytics.data.split_dota import split_trainval, split_test # split train and val set, with labels. split_trainval( data_rootpath/to/DOTAv1.0/, save_dirpath/to/DOTAv1.0-split/, rates[0.5, 1.0, 1.5], # multiscale gap500 ) # split test set, without labels. split_test( data_rootpath/to/DOTAv1.0/, save_dirpath/to/DOTAv1.0-split/, rates[0.5, 1.0, 1.5], # multiscale gap500 )rates[0.5, 1.0, 1.5]会依次生成边长 2048、1024、约 683 的三种窗口尺度使模型对不同尺度目标都更鲁棒随后对train与val两个 split 分别调用split_images_and_labels。4.2 split_test无标签的 test 切分def split_test(data_root, save_dir, crop_size1024, gap200, rates[1.0]):测试集不提供公开标签因此只切图像假定输入结构为data_root/images/test输出为save_dir/images/test对每张图用exif_size读取尺寸、get_windows生成窗口然后cv2.imwrite写出子图命名规则与crop_and_save一致不含标签文件。4.3 命令行入口脚本底部__main__展示了直接运行方式默认参数 1024×1024、gap200、单尺度python ultralytics/data/split_dota.py等价于对DOTAv2目录执行split_trainval(data_rootDOTAv2, save_dirDOTAv2-split)与split_test(data_rootDOTAv2, save_dirDOTAv2-split)得到DOTAv2-split/目录。实际使用时请把data_root与save_dir替换为自己的路径。五、切分结果的接入方式切分完成后数据布局恰好满足 YOLO 数据集配置的默认约定。以 DOTAv1.yaml 为例path: ../datasets/DOTAv1 # 切分后的根目录 train: images/train # 1411 张 val: images/val # 458 张 test: images/test # 可选937 张 names: 0: plane 1: ship 2: storage tank 3: baseball diamond 4: tennis court 5: basketball court 6: ground track field 7: harbor 8: bridge 9: large vehicle 10: small vehicle 11: helicopter 12: roundabout 13: soccer ball field 14: swimming pool随后即可启动 OBB 训练from ultralytics import YOLO # 加载 YOLOv8n-OBB 预训练模型并训练 model YOLO(yolov8n-obb.pt) results model.train(dataDOTAv1.yaml, epochs100, imgsz640)或使用 CLIyolo obb train dataDOTAv1.yaml modelyolov8n-obb.pt epochs100 imgsz640对于快速验证切分工具与训练管线是否正确可使用仓库自带的 dota8.yaml——它由切分后的 DOTAv1 中取出前 8 张图train/val 各 4 张构成1MB 体积适合作为冒烟测试数据集。六、关键实现细节与使用建议坐标约定get_window_obj在还原像素坐标时把标签第 1、3、5、7 列乘图像宽w第 2、4、6、8 列乘图像高h这与 YOLO OBB 标签归一化到各自维度的格式严格对应切分后的重归一化同样按pw/ph分别进行坐标语义自洽。目标归属阈值iof_thr0.7意味着目标至少 70% 的面积落入窗口才会被保留。该值偏大会漏掉横跨窗口边缘的目标偏小则同一目标在多个窗口中重复出现DOTA 切分工具的设计意图正是通过重叠窗口与阈值折中保证目标完整性优先于去重。重叠与多尺度gap决定相邻窗口重叠宽度默认 200 像素gap越大同一目标被多个窗口捕获的概率越高子图总数也随之增加。多尺度rates会成倍放大输出数据量建议先在小数据集如 dota8上验证再对全量 DOTA 执行。依赖要求模块运行时强制校验shapely在 CPU 密集的航拍数据集上切分耗时较长但全程有 tqdm 进度条反馈若遇到 Cant find ... please check your data root 断言报错请确认data_root下确实存在images/split目录。七、总结ultralytics.data.split_dota是 DOTA 航拍数据集接入 YOLO OBB 训练管线的关键前置工具。它通过get_windows生成多尺度滑动窗口、bbox_iofget_window_obj精确判定目标归属、crop_and_save同步重写子图与归一化标签最终以与输入同构的目录结构输出切分结果。理解其参数语义crop_size、gap、rates、iof_thr、im_rate_thr后你可以灵活定制任意航拍大图的切分策略并配合 DOTAv1.yaml、dota8.yaml 直接进入训练环节。相关数据集背景与训练示例可进一步参阅 dota-v2.md 与 dota8.md。【免费下载链接】yolov10YOLOv10: Real-Time End-to-End Object Detection [NeurIPS 2024]项目地址: https://gitcode.com/GitHub_Trending/yo/yolov10创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表