YOLO26 OBB实战:从原理到部署的无人机船舶检测指南
1. 项目概述从YOLO26与OBB说起最近在搞无人机航拍图像的目标检测特别是针对港口、河道里的船舶发现一个挺头疼的问题。传统的水平框检测比如标准的YOLOv8或者YOLO26框出来的矩形框会包含大量背景尤其是当船舶是倾斜的、长条状的时候那个框简直没法看背景干扰严重后续想做精确的测距、靠泊分析或者行为识别误差就太大了。这时候方向包围框Oriented Bounding Box, OBB就成了刚需。它不仅能框住目标还能用带角度的矩形更贴合物体的实际朝向对于船舶、车辆、飞机这类有明显方向性的目标效果提升不是一点半点。YOLO26作为YOLO系列的最新成员之一继承了其家族在速度和精度上的平衡优势并且社区生态活跃对OBB任务的支持也越来越完善。这个项目就是要把“用YOLO26训练自己的OBB数据集”这套流程彻底跑通并且以无人机航拍船舶为具体案例把原理、代码、结构还有我踩过的那些坑都掰开揉碎了讲清楚。无论你是刚接触OBB的新手还是想将YOLO26应用到特定领域的开发者这篇从数据准备到模型部署的完整指南应该都能给你提供一条清晰的路径。2. 核心原理OBB究竟是什么为何优于HBB在深入代码之前我们必须先搞清楚OBB和普通水平框Horizontal Bounding Box, HBB的根本区别以及YOLO26是如何处理OBB的。这决定了我们后续标注数据、理解损失函数和评估结果的方式。2.1 HBB的局限性与OBB的优势想象一下用手机给一艘斜停在江边的货轮拍照。用一个水平的矩形框去框它会发生什么这个矩形为了能完全包住船头和船尾必然会在船身两侧框进大量的江水、码头或其它船舶。这个框的“纯度”很低。HBB水平框由中心点(cx, cy)、宽度w和高度h定义。它总是与图像坐标轴平行。OBB方向框在HBB的基础上增加了一个旋转角度θ。通常它由中心点(cx, cy)、宽度w、高度h和角度θ定义。这里的宽度和高度是沿着框自身的主轴和次轴定义的。对于船舶检测OBB的优势立刻显现更紧密的贴合框体与船舶主轴对齐背景冗余最小化。朝向信息角度θ直接提供了船舶的航向对于海事监控、轨迹预测至关重要。更准确的IoU计算在评估模型性能或进行NMS非极大值抑制时计算两个OBB之间的交并比IoU比用HBB更符合视觉感知能更好地处理密集、倾斜的目标。2.2 YOLO26中OBB的表示与损失函数YOLO系列的核心是回归目标框的坐标。对于OBB任务YOLO26以及其前身YOLOv8-OBB通常采用一种称为“旋转框的五点表示法”或“四参数表示法”。1. 四参数表示法主流 这是目前YOLO-OBB中更常见的方式。模型直接回归中心点(cx, cy)、宽度w、高度h和角度θ。其中角度θ的定义需要统一约定常见的是定义为框的长边w与x轴正方向的夹角范围在[-π/2, π/2)或[0, π)弧度之间。这种表示直观但回归角度存在周期性边界问题比如 -π/2 和 π/2 表示的是同一个框。2. 五点表示法更稳定 模型不直接回归角度而是回归旋转框的四个顶点(x1, y1), (x2, y2), (x3, y3), (x4, y4)相对于中心点的偏移。由于一个矩形只需要四个点回归八个值每个点x,y存在过参数化。更常见的优化是回归外接水平矩形的左上右下点再加上一个角度或者通过其他变换得到。在YOLO中为了与现有架构兼容常采用四参数法。损失函数 YOLO26的OBB损失通常是在原有HBB损失如CIoU基础上的扩展。核心是旋转IoURotated IoU, RIoU的计算。计算两个旋转矩形的IoU比水平矩形复杂得多不能直接用轴对齐的坐标计算。常见的解决方案有基于多边形相交的精确计算使用shapely库或cv2的旋转矩形函数将旋转矩形转化为多边形再计算多边形交集面积。精度高但计算量稍大。近似计算如使用SkewIoU或将旋转框投影到轴上计算速度更快但可能略有误差。 YOLO26的损失函数RIoU Loss会基于计算出的RIoU值结合距离、纵横比等因子构成最终的回归损失。分类损失和对象性损失则与标准YOLO一致。注意角度回归的损失需要特殊处理。直接使用L1/L2损失会因周期性如179度与-179度而产生巨大误差。因此通常会对角度损失进行归一化例如使用Smooth L1 Loss结合角度差的最小周期补角。2.3 数据标注格式关键的第一步你的数据集格式必须与模型训练代码的读取方式匹配。YOLO-OBB常用的标注格式是DOTA数据集格式的变种。DOTA格式 每张图片对应一个.txt标注文件。文件中的每一行代表一个目标物体格式为x1 y1 x2 y2 x3 y3 x4 y4 category difficultx1, y1, ..., x4, y4物体四个顶点的坐标通常按顺时针或逆时针顺序。category物体类别名称或ID。difficult是否为难例0或1。YOLO-OBB格式转化后 为了适配YOLO训练通常需要将DOTA格式转化为一个更紧凑的格式。一个常见的YOLO-OBB格式是class_id cx cy w h angleclass_id类别索引从0开始。cx, cy旋转框中心点的归一化坐标除以图像宽高。w, h旋转框的宽度和高度归一化后的值。注意这里的w和h是旋转框自身坐标系下的长边和短边不是外接水平矩形的宽高。angle旋转角度弧度制。需要与模型约定的角度定义一致例如长边与x轴夹角范围[-π/2, π/2)。无人机航拍船舶案例的特殊性小目标与密集目标高空航拍船舶可能只占几十个像素且码头区域船舶密集。大纵横比船舶通常是长条形的w和h差异巨大。角度多样性船舶朝向360度都有但通常在水面运动角度分布有一定规律。背景复杂水面反光、波浪、桥梁阴影、港口设施等干扰多。这些特点决定了我们在数据增强、模型设计如注意力机制、更小的检测头和评估指标上需要做针对性调整。3. 环境配置与数据准备工欲善其事必先利其器。一套稳定、兼容的环境是成功训练的基础。这里我推荐使用Conda来管理Python环境避免包冲突。3.1 基础环境搭建# 1. 创建并激活conda环境 conda create -n yolo26_obb python3.8 -y conda activate yolo26_obb # 2. 安装PyTorch请根据你的CUDA版本访问PyTorch官网获取对应命令 # 例如对于CUDA 11.8 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 3. 克隆YOLO26仓库这里以Ultralytics的YOLOv8仓库为例它支持OBB且与YOLO26架构相似 # 实际上截至我的知识截止日期“YOLO26”可能指代社区基于YOLO架构的某个版本或改进。 # 我们以最成熟且支持OBB的Ultralytics YOLOv8-OBB作为实践基础其方法论完全通用。 git clone https://github.com/ultralytics/ultralytics.git cd ultralytics pip install -e . # 以可编辑模式安装 # 4. 安装其他依赖 pip install opencv-python pillow matplotlib seaborn tqbd pandas pyyaml # 用于OBB标注可视化和评估 pip install shapely scikit-learn实操心得PyTorch版本与CUDA版本的匹配是关键。先用nvidia-smi查看驱动支持的CUDA最高版本然后去PyTorch官网找对应命令。如果训练时出现“CUDA out of memory”除了减小批次大小还要检查是否是Torch版本不对导致的内存泄漏。3.2 准备无人机船舶OBB数据集假设你已经通过无人机采集了一批港口、河道的影像并用标注工具如LabelImg的OBB分支、roLabelImg或CVAT完成了OBB标注导出了DOTA格式的标注文件。我们的目标是将原始数据组织成YOLO-OBB训练所需的格式。目录结构如下datasets/ └── ship_obb/ ├── images/ │ ├── train/ │ │ ├── drone_001.jpg │ │ └── ... │ └── val/ │ ├── drone_101.jpg │ └── ... └── labels/ ├── train/ │ ├── drone_001.txt │ └── ... └── val/ ├── drone_101.txt └── ...关键步骤格式转换脚本你需要一个脚本将DOTA格式的(x1,y1,x2,y2,x3,y3,x4,y4)转换为YOLO-OBB格式的(cls, cx, cy, w, h, angle)。下面是一个核心转换函数import numpy as np from shapely.geometry import Polygon def dota_to_yolo_obb(dota_box, img_width, img_height): 将DOTA格式的四边形框转换为YOLO-OBB格式。 dota_box: list of 8 floats [x1,y1,x2,y2,x3,y3,x4,y4] 返回: (cls, cx_norm, cy_norm, w_norm, h_norm, angle) 角度定义为旋转矩形长边与x轴正方向的夹角范围[-pi/2, pi/2)。 # 将四个点组成多边形 points np.array(dota_box).reshape(4, 2) poly Polygon(points) # 获取最小外接旋转矩形 rect poly.minimum_rotated_rectangle rect_coords np.array(rect.exterior.coords)[:4] # 获取四个顶点 # 计算旋转矩形中心、宽、高和角度 # 找到长边向量 edge1 rect_coords[1] - rect_coords[0] edge2 rect_coords[2] - rect_coords[1] # 确定长边 length1 np.linalg.norm(edge1) length2 np.linalg.norm(edge2) if length1 length2: long_edge edge1 short_edge edge2 width, height length1, length2 else: long_edge edge2 short_edge edge1 width, height length2, length1 # 计算角度长边与x轴夹角 angle np.arctan2(long_edge[1], long_edge[0]) # 弧度制 # 将角度规范到 [-pi/2, pi/2) 区间 # 这是因为一个旋转矩形将其长边旋转90度宽高互换角度加减pi/2表示的是同一个框。 # 我们约定用长边作为宽度角度在[-pi/2, pi/2)内。 if angle np.pi / 2: angle - np.pi elif angle -np.pi / 2: angle np.pi # 确保宽度是长边高度是短边 if width height: width, height height, width angle np.pi / 2 # 再次规范化角度 if angle np.pi / 2: angle - np.pi elif angle -np.pi / 2: angle np.pi # 计算中心点使用原始多边形中心或旋转矩形中心 center rect.centroid cx, cy center.x, center.y # 归一化 cx_norm cx / img_width cy_norm cy / img_height w_norm width / img_width h_norm height / img_height # 假设类别ID为0‘ship’ cls_id 0 return cls_id, cx_norm, cy_norm, w_norm, h_norm, angle注意事项角度规范化是OBB数据处理中最容易出错的一环。不同的库和模型对角度的定义可能不同例如OpenCV的cv2.minAreaRect返回的角度范围是[-90, 0)。务必确保你的转换脚本与模型训练代码的角度定义完全一致否则训练会完全失败。一个验证方法是用转换后的数据画回原图看框是否与物体对齐。3.3 创建数据集配置文件在ultralytics目录下或你的项目根目录创建一个数据集YAML文件例如ship_obb.yaml# ship_obb.yaml path: /path/to/your/datasets/ship_obb # 数据集根目录 train: images/train # 训练集图像路径相对于path val: images/val # 验证集图像路径相对于path # test: images/test # 可选测试集 # 类别列表 names: 0: ship4. 模型训练与调参实战环境数据就绪进入核心的训练环节。我们将使用Ultralytics框架来训练一个YOLOv8-OBB模型其训练流程与YOLO26 OBB完全相通。4.1 启动基础训练创建一个Python训练脚本train_obb.pyfrom ultralytics import YOLO # 加载一个预训练的OBB模型例如YOLOv8n-obb model YOLO(yolov8n-obb.pt) # 训练模型 results model.train( dataship_obb.yaml, # 数据集配置文件路径 epochs100, # 训练轮数 imgsz640, # 输入图像大小 batch16, # 批次大小根据GPU内存调整 device0, # GPU设备如0或cuda workers4, # 数据加载线程数 projectruns/train, # 结果保存目录 nameship_obb_exp1, # 实验名称 pretrainedTrue, # 使用预训练权重 optimizerAdamW, # 优化器 lr00.001, # 初始学习率 cos_lrTrue, # 使用余弦退火学习率调度 label_smoothing0.1, # 标签平滑防止过拟合 save_period10, # 每10个epoch保存一次检查点 # OBB相关特定参数 degrees0.0, # 图像随机旋转角度范围对于OBB谨慎使用或设为0 translate0.1, # 图像随机平移 scale0.5, # 图像随机缩放 shear0.0, # 图像随机剪切对于OBB谨慎使用 perspective0.0, # 图像随机透视变换对于OBB谨慎使用 flipud0.0, # 上下翻转概率对于航拍可适当开启 fliplr0.5, # 左右翻转概率对于无方向要求的OBB可开启 mosaic1.0, # Mosaic数据增强概率 mixup0.0, # MixUp增强概率OBB任务建议先关闭因其会混合角度 copy_paste0.0, # 复制粘贴增强概率 )关键参数解析imgsz: 无人机图像通常分辨率很高如4000x3000直接下采样到640会丢失小目标细节。可以尝试增大到1024或1280但会显著增加显存消耗和训练时间。一个折中方案是先将原始图像裁剪成瓦片tiling再进行训练。degrees/shear/perspective:对于OBB任务这些涉及图像几何形变的增强需要极其谨慎。因为图像旋转后标注框的角度也需要相应旋转如果处理不当会导致角度标签错误。Ultralytics框架内部应该已经为OBB任务正确处理了这些变换但建议初始训练时先将它们设为0稳定后再尝试小幅度增加。fliplr: 左右翻转对于船舶这类对称性不强的物体可能会改变其合理朝向如船头从左向右变成从右向左。但在数据量不足时开启它可以增加多样性模型需要学习“船头方向可以改变”这一先验。可以根据实际情况调整。mixup/copy_paste: 这类混合图像内容的增强在OBB任务中容易产生不合理的旋转框例如半艘船是30度半艘是-30度。初期建议关闭。4.2 针对无人机船舶数据的调优策略默认训练可能不够我们需要一些针对性的技巧。1. 小目标检测增强多尺度训练在model.train()参数中设置multi_scaleTrue让模型在不同尺度下学习增强对小目标的鲁棒性。更小的锚框Anchor或Anchor-FreeYOLOv8默认是Anchor-Free的这简化了流程。但如果你的船舶尺寸非常集中可以尝试在模型配置文件中自定义先验框尺寸对于Anchor-Based的变体。特征金字塔优化关注小目标主要依赖浅层高分辨率特征图。确保模型结构如PANet能充分融合浅层特征。2. 处理大纵横比和密集目标损失函数权重调整在OBB损失中角度回归的权重可能需要调整。虽然框架自动调参但如果发现角度预测不准可以查看源码中bbox_loss的构成看是否有角度损失的独立权重参数。NMS后处理推理时使用旋转NMSRotated NMS而非标准NMS。Ultralytics在OBB模式下会自动调用旋转NMS。其IoU阈值iou_thres可能需要调低如0.3因为密集的倾斜框重叠计算方式不同。3. 数据增强的针对性设计 除了框架内置的可以自定义增强模拟天气添加雾气、水面反光、雨滴噪声提升模型在恶劣天气下的鲁棒性。运动模糊模拟无人机快速移动时的模糊效果。色域扰动调整色调、饱和度和亮度适应不同时间清晨、黄昏的拍摄条件。# 一个自定义增强的例子集成到训练流程中可能需要修改dataloader import albumentations as A def get_augmentation_pipeline(): return A.Compose([ A.RandomBrightnessContrast(p0.3), A.HueSaturationValue(p0.3), A.ISONoise(p0.2), # 模拟ISO噪声 # 谨慎使用几何变换 # A.Affine(scale(0.9, 1.1), translate_percent0.1, rotate0, shear0, p0.5, modecv2.BORDER_CONSTANT), ], bbox_paramsA.BboxParams(formatyolo, label_fields[class_labels, angles], min_visibility0.1))注意使用Albumentations等库时必须确保其支持OBB框的变换或者将OBB框转换为多边形进行变换后再转回。4.3 训练过程监控与评估训练开始后监控以下指标损失曲线关注box_loss包含RIoU损失和角度损失和cls_loss是否平稳下降。验证集指标mAP50-95: 在不同IoU阈值0.5到0.95步长0.05下的平均精度均值是核心评估指标。mAP50: IoU阈值为0.5时的平均精度。precision和recall: 查准率和查全率。OBB特定指标关注模型预测框的角度准确性。可以自定义一个角度误差平均绝对角度差在验证集上计算。使用TensorBoard或Ultralytics内置的日志工具可视化训练过程。如果发现验证集指标早早就停止上升甚至下降可能是过拟合需要增加数据增强、使用早停patience参数或减少模型复杂度。5. 模型推理与部署应用训练完成后我们得到最好的模型权重通常是runs/train/ship_obb_exp1/weights/best.pt。接下来就是用它来推理新的无人机图像。5.1 单张图像/批量图像推理from ultralytics import YOLO import cv2 # 加载训练好的模型 model YOLO(runs/train/ship_obb_exp1/weights/best.pt) # 单张图像推理 results model(path/to/new_drone_image.jpg, imgsz1024, conf0.25, iou0.45) # 可视化结果 for r in results: im_array r.plot() # 绘制边界框和标签的BGR numpy数组 cv2.imwrite(result.jpg, im_array) # 也可以获取详细的预测信息 boxes r.obb # 获取OBB信息 if boxes is not None: for box in boxes: # box.data 可能包含 [x_center, y_center, width, height, angle, conf, cls] print(fClass: {model.names[int(box.cls)]}, Confidence: {box.conf:.2f}) print(fBox: cx{box.xywhr[0]}, cy{box.xywhr[1]}, w{box.xywhr[2]}, h{box.xywhr[3]}, angle{box.xywhr[4]:.2f} rad)推理参数说明imgsz: 推理时输入图像的大小。可以与训练时不同但会影响速度和精度。通常使用与训练相同的尺寸或更大尺寸以获得更好精度特别是小目标。conf: 置信度阈值。高于此值的检测框才会被保留。根据你的应用场景调整高精度需求调高高召回需求调低。iou: NMS的IoU阈值。用于合并重叠框。对于密集的船舶可能需要适当降低如0.4以防止误删真阳性目标。5.2 处理大尺寸航拍图像瓦片推理无人机原图往往很大直接缩放到模型输入尺寸会丢失细节。标准的做法是滑动窗口瓦片推理。def tile_inference(model, large_img_path, tile_size640, overlap0.2): 对大图像进行滑动窗口推理并合并结果。 注意需要处理瓦片边缘被切割的目标以及合并重叠区域的重复检测框。 import numpy as np large_img cv2.imread(large_img_path) h, w large_img.shape[:2] stride int(tile_size * (1 - overlap)) # 滑动步长 all_boxes [] for y in range(0, h - tile_size 1, stride): for x in range(0, w - tile_size 1, stride): # 裁剪瓦片 tile large_img[y:ytile_size, x:xtile_size] # 推理 results model(tile, imgsztile_size, conf0.25, iou0.5, verboseFalse)[0] if results.obb is not None: boxes results.obb.data.cpu().numpy() # 将瓦片坐标转换回原图坐标 boxes[:, [0, 2]] x # cx, w? 注意OBB框的cx,cy是中心点转换时是cx, cy直接加偏移 boxes[:, [1, 3]] y # cy, h? # 更严谨的做法对于OBB需要将四个顶点坐标分别偏移或者将中心点(cx,cy)偏移。 # 这里假设results.obb.xyxy或results.obb.xywhr格式便于转换 # 实际应根据ultralytics输出格式调整。通常obb.xywhr 包含 [cx, cy, w, h, angle, conf, cls] # 我们只需要更新cx, cy all_boxes.append(boxes) if all_boxes: all_boxes np.vstack(all_boxes) # 对转换回原图坐标的所有框进行旋转NMS去重 # 这里需要调用旋转NMS函数例如使用cv2.dnn.NMSBoxesRotated或shapely计算RIoU # 这是一个简化示例实际合并逻辑更复杂 final_boxes rotated_nms(all_boxes, iou_threshold0.4) return final_boxes return []踩坑实录瓦片推理最大的挑战是边缘目标处理和重复框合并。一个目标被多个瓦片检测到会产生多个框。简单的做法是保留置信度最高的但更好的方法是使用加权框融合Weighted Boxes Fusion, WBF的旋转框版本或者使用旋转NMS时设置一个较低的IoU阈值。此外瓦片重叠率overlap需要设置得当太小会漏掉跨瓦片的目标太大会增加计算量。对于船舶这种大目标重叠率0.2-0.3通常是个起点。5.3 模型轻量化与部署训练出的.pt模型是PyTorch格式部署到边缘设备如无人机机载电脑Jetson系列、RK3588等需要转换。导出为ONNXyolo export modelbest.pt formatonnx imgsz640 simplifyTrue添加opset12或更高版本以确保更好的兼容性。导出后用Netron工具打开检查模型结构是否正确特别是输出层是否符合OBB格式。转换为TensorRT针对NVIDIA Jetson# 在Jetson上安装TensorRT # 使用trtexec或Python的torch2trt进行转换 # 注意需要确保TensorRT支持模型中的所有算子如旋转框解码转换后能获得数倍甚至数十倍的推理加速。转换为RKNN针对瑞芯微RK3588# 使用RKNN-Toolkit2进行转换 # 这是一个专门针对瑞芯微NPU的转换工具需要仔细配置量化参数注意事项部署到边缘设备时最大的挑战是算子支持。旋转框的后处理如旋转NMS可能在目标平台的推理引擎中没有高效实现。一种常见的策略是将模型输出改为水平框HBB加上角度预测然后在CPU上进行简单的后处理生成OBB但这会损失一些精度。另一种策略是寻找或自定义插件实现旋转NMS。6. 项目结构框图与工作流梳理为了让整个项目的脉络更清晰这里用一个结构框图来概括从数据到应用的全流程[无人机航拍原始图像] | v [数据标注与清洗] -- 使用LabelImg/CVAT进行OBB标注 | v [格式转换与数据集划分] -- DOTA格式 - YOLO-OBB格式 (脚本转换) | v [环境配置与模型选择] -- Conda环境, PyTorch, Ultralytics YOLO | v [模型训练与调优] -- 基础训练 - 针对小目标/密集/大纵横比调优 | | |-- [数据增强策略] -- (Mosaic, MixUp, 自定义增强) | v [模型验证与评估] -- mAP, Precision, Recall, 角度误差分析 | v [模型导出与部署] -- ONNX - TensorRT / RKNN / 其他推理引擎 | v [应用推理与后处理] -- 单图/视频流推理 - 瓦片处理 - 旋转NMS - 结果可视化 | v [集成到业务系统] -- 船舶计数、航向分析、靠泊监控、异常行为检测核心模块解读数据流水线最基础也最耗时标注质量直接决定模型上限。对于OBB标注的一致性顶点顺序、角度定义至关重要。训练调优环这是一个迭代过程。根据验证集表现反复调整数据增强、模型超参数甚至模型结构如更换检测头、添加注意力模块。部署适配环实验室的模型到实际场景往往有差距。需要考虑推理速度、资源消耗、环境适应性光照、天气并进行必要的量化、剪枝等优化。7. 常见问题与排查技巧实录在实际操作中你肯定会遇到各种报错和效果不佳的情况。这里记录一些典型问题及我的解决思路。7.1 训练阶段问题Q1: 损失不下降mAP始终为0或极低。检查数据标注这是最常见的原因。用可视化脚本将YOLO-OBB格式的标签画到图像上确保每个框都准确包围目标且角度正确。特别注意角度规范化是否与模型定义一致。检查数据集配置确保data.yaml中的路径正确train和val列表没有错误。可以用几行代码读一下看能否正常加载图片和标签。检查类别ID确认你的标注文件中类别ID是从0开始的连续整数且与data.yaml中的names列表顺序匹配。学习率问题初始学习率lr0可能太大或太小。尝试使用默认值或者使用lr_finder工具寻找合适的学习率。模型初始化如果是从头训练pretrainedFalse收敛会慢很多。务必使用预训练权重。Q2: 角度预测混乱框是水平的或者角度完全不对。角度损失权重可能是角度回归任务的损失权重太小模型不重视。检查损失函数实现看是否有独立的angle_loss及其权重。数据增强干扰检查是否开启了过强的几何增强如大角度的degrees。先关闭所有旋转、剪切、透视变换看角度学习是否正常。角度周期性边界如前所述角度回归存在周期性。确保损失函数正确处理了这一点例如计算角度差时使用diff min(abs(a-b), 2*pi - abs(a-b))。Q3: 小船舶检测不到漏检率高。增大输入分辨率将imgsz从640提高到1024或1280。使用更小的下采样倍数修改模型配置文件中的stride参数较复杂或者使用专门的小目标检测层。数据增强增加小目标复制粘贴Copy-Paste增强但要注意OBB的角度一致性。正样本匹配阈值调整正样本匹配的IoU阈值让更多小目标锚框被匹配为正样本。7.2 推理阶段问题Q4: 推理速度慢。减小imgsz这是最直接有效的方法但会牺牲精度尤其是小目标。模型剪枝与量化使用模型压缩技术如通道剪枝、INT8量化TensorRT/PyTorch Quantization。优化后处理旋转NMS的计算复杂度比标准NMS高。尝试优化其实现或尝试使用更快的近似算法。使用更快的模型从yolov8l-obb换到yolov8n-obb或yolov8s-obb。Q5: 瓦片推理时同一个目标被检测多次。调整NMS阈值降低旋转NMS的iou_thres让重叠度高的框合并得更激进。使用WBF实现旋转框版本的加权框融合它通常比NMS保留更多信息效果更好。优化瓦片重叠率增加overlap可以减少目标被切割在边缘的情况但会增加重复检测。需要在速度和精度间权衡。Q6: 部署到边缘设备后精度下降明显。量化误差INT8量化会引入误差。尝试使用量化感知训练QAT或在精度损失可接受的范围内调整量化参数。算子不支持检查模型中是否有边缘设备推理引擎不支持的算子如某些特殊的激活函数或自定义层。可能需要修改模型结构或寻找替代实现。输入预处理不一致确保部署时的图像预处理归一化、通道顺序、尺寸缩放与训练时完全一致。7.3 性能提升技巧集成测试时增强TTA在推理时对图像进行多尺度、多翻转的预测并集成结果能稳定提升mAP 1-3个百分点但会成倍增加推理时间。results model(image.jpg, imgsz640, augmentTrue) # 开启TTA模型集成训练多个不同初始化或不同数据子集的模型在推理时平均它们的预测结果。伪标签用训练好的模型对大量未标注数据进行推理将高置信度的预测结果作为伪标签加入训练集进行第二轮训练。焦点难例挖掘分析验证集中哪些样本预测错误对这些难例进行针对性数据增强或重新标注。最后我想说的是OBB检测是一个比HBB更精细但也更复杂的任务。从数据标注的规范性到角度表示的一致性再到训练和部署中的各种细节每一步都需要格外小心。以无人机船舶检测为例它完美体现了OBB的价值。整个过程走下来你会发现最大的收获不仅仅是调好了一个模型更是对旋转目标检测整个技术栈的深刻理解。当你看到模型准确地框出每一艘船的轮廓和航向时那种成就感是对所有调试时间的最好回报。在实际项目中不妨先从一个小规模、高质量的数据集开始快速跑通整个Pipeline然后再逐步迭代优化数据和模型这样能更高效地逼近理想的检测效果。