小目标Trick | Detectron2、MMDetection、YOLOv5都通用的小目标检测解决方案

简介: 小目标Trick | Detectron2、MMDetection、YOLOv5都通用的小目标检测解决方案

1简介


近年来,目标检测在人脸检测、视频目标检测、视频监控、自动驾驶汽车等不同应用领域得到了广泛的研究。在这一领域,深度学习架构的采用导致产生了高度精确的方法,如Faster R-CNN、RetinaNet,进一步发展为Cascade R-CNN、VarifocalNet和变体。

所有这些最近的检测器都是在著名的数据集上进行训练和评估的,如ImageNet、PascalVOC12、MSCOCO。这些数据集大多涉及低分辨率图像(640×480),包括相当大的像素覆盖的相当大的目标(平均覆盖图像高度的60%)。虽然训练后的模型对这些类型的输入数据具有成功的检测性能,但在高端无人机和监视摄像机生成的高分辨率图像中,它们对小目标检测任务的精度明显较低。

无人机、4K摄像机和深度学习研究的最新进展使远程目标检测成为可能,符合检测、观察、识别和DORI标准。DORI标准定义了不同任务对象的最小像素高度:10%的图像高度需要检测,20%的图像需要识别物体(全高清视频中的108像素)。相对较小的像素覆盖推动了基于CNN的目标检测方法的局限性,此外,高分辨率图像在计算和内存需求方面需要更大的需求。

在本文中提出了一种基于切片辅助推理和微调的通用解决方案,用于高分辨率图像上的小目标检测,同时保持较低的复杂度和内存需求。图1显示了Visdrone测试集样本图像上小目标检测的改进。


2相关工作


最近的基于学习的目标检测技术可分为两种主要类型。单级探测器,如SSD、YOLO、RetinaNet,直接预测物体的位置,而没有一个明确的建议阶段。两阶段区域建议的方法,如Fast R-CNN、Faster R-CNN、Cascade R-CNN,涉及区域建议阶段。然后对这些建议框进行细化,以定义目标的位置和大小。通常,单阶段方法比两阶段方法更快,而后者具有更高的精度。

最近,Anchor-Free检测器开始引起人们的注意。他们消除了Anchor box的使用,并将特征金字塔上的每个点分类为前景或背景,并直接预测从前景点到GT边界框的距离,从而产生检测。FCOS是第一个目标检测器,消除了预定义Anchor box集的需要,并需要计算需要。VarifocalNet(VFNet)学习预测IoU-aware classification score,它将目标存在的置信度和定位精度混合在一起,作为一个边界框的检测分数。学习是由基于一个新的星形边界框特征表示所提出的Varifocal Loss(VFL)监督的。TOOD以基于学习的方式将2个任务(目标分类和定位)明确对齐,通过设计的样本分配方案和任务对齐损失,在学习任务交互和任务特定特征和任务对齐学习之间提供了更好的平衡。

针对一般目标检测的算法在包含小而密集目标的高分辨率图像上表现不佳,导致了针对小目标检测的特定方法。有研究采用基于粒子群优化(PSO)和细菌觅食优化(BFO)的学习策略(PBLS)对分类器和损失函数进行优化。然而,这些对原始模型的重大修改阻止了从预训练的权重进行微调,需要从头开始训练。

此外,由于不寻常的优化步骤,它们很难适应目前的检测器。该方法对具有小目标的图像进行过采样,并通过复制多个小目标对其进行扩充。然而,这种增强需要分割注释,因此,它与目标检测数据集不兼容。有方法可以从原始图像中截取放大区域,从中学习到更丰富的小目标特征。额外的特征对检测性能有积极的贡献,但要扩大的区域的选择带来了计算负担。

也有研究提出了一种用于小目标检测的全卷积网络,该网络包含了一种早期的视觉注意力机制,用来选择最有希望的包含小目标及其上下文的区域。还有研究提出了一种基于切片的技术,但其实现并不通用,仅适用于特定的目标检测器。也有研究提出了一种新型的小型行人检测网络(JCS-Net),该网络将分类任务和超分辨率任务整合在一个统一的框架中。

有学者提出了一种利用生成式对抗网络(GAN)从模糊的小人脸直接生成清晰的高分辨率人脸的算法。然而,由于这些技术提出了新的检测器体系结构,它们需要从头开始用大型数据集进行预训练,这是昂贵的。


3本文方法


为了解决小目标检测问题,作者提出了一个在微调和推理阶段基于切片的通用框架。将输入图像划分为重叠的切片,对于小目标相对于输入网络的图像产生相对较大的像素区域。

3.1 Slicing Aided Fine-tuning(SF)

image.png

图2 Slicing Aided Fine-tuning(SF)

广泛使用的目标检测框架,如Detectron2、MMDetection和YOLOv5,在ImageNet和MSCOCO等数据集上提供预训练的权重。这允许使用更小的数据集和更短的训练跨度来对模型进行微调,而不是使用大数据集从头开始进行训练。

这些常见的数据集大多涉及低分辨率的图像(640×480),它们具有相当大的目标和较大的像素覆盖(平均覆盖图像高度的60%)。使用这些数据集进行预训练的模型为相似的输入提供了非常成功的检测性能。另一方面,在由高端无人机和监视摄像头生成的高分辨率图像中,它们对小目标检测任务的精度明显较低。

为了克服这个问题,作者通过从图像微调数据集中提取patch来增强数据集,如图2所示。每幅图像、、...、被分割成重叠的patch 、、…在预定义范围和内选择N和N的被视为超参数。然后在微调过程中,通过保留高宽比来调整patch的大小,使图像宽度在800~1333像素之间,以获得增强图像、、...、,因此相对的目标大小比原始图像更大。

这些图像、、...、,以及原始图像、、...、(便于检测大物体),在微调过程中被利用。需要注意的是,随着patch size的减小,较大的物体可能不适合一个切片和交叉区域,这可能导致对较大物体的检测性能较差。

3.2 Slicing Aided Hyper Inference(SAHI)

图3 Slicing Aided Hyper Inference(SAHI)

在推理步骤中也使用了切片方法,如图3所示。首先,将原始查询图像I分割成1个M×N个重叠的patch 、、……。然后,在保持高宽比的同时,调整每个patch的大小。然后,对每个重叠的patch都独立地应用目标检测正向传递。使用原始图像的一个可选的全推理(FI)可以用于检测较大的目标。最后,重叠的预测结果,如果使用,FI结果使用NMS合并回原始大小。在NMS过程中,具有比预定义匹配阈值Tm的Union(IoU)比值更高的box被匹配,并且对于每个匹配,具有检测概率低于的检测被删除。

def slice_image(
    image: Union[str, Image.Image],
    coco_annotation_list: Optional[CocoAnnotation] = None,
    output_file_name: Optional[str] = None,
    output_dir: Optional[str] = None,
    slice_height: int = 512,
    slice_width: int = 512,
    overlap_height_ratio: float = 0.2,
    overlap_width_ratio: float = 0.2,
    min_area_ratio: float = 0.1,
    out_ext: Optional[str] = None,
    verbose: bool = False,
) -> SliceImageResult:
    # define verboseprint
    verboselog = logger.info if verbose else lambda *a, **k: None
    def _export_single_slice(image: np.ndarray, output_dir: str, slice_file_name: str):
        image_pil = read_image_as_pil(image)
        slice_file_path = str(Path(output_dir) / slice_file_name)
        # export sliced image
        image_pil.save(slice_file_path)
        verboselog("sliced image path: " + slice_file_path)
    # create outdir if not present
    if output_dir is not None:
        Path(output_dir).mkdir(parents=True, exist_ok=True)
    # read image
    image_pil = read_image_as_pil(image)
    verboselog("image.shape: " + str(image_pil.size))
    image_width, image_height = image_pil.size
    if not (image_width != 0 and image_height != 0):
        raise RuntimeError(f"invalid image size: {image_pil.size} for 'slice_image'.")
    slice_bboxes = get_slice_bboxes(
        image_height=image_height,
        image_width=image_width,
        slice_height=slice_height,
        slice_width=slice_width,
        overlap_height_ratio=overlap_height_ratio,
        overlap_width_ratio=overlap_width_ratio,
    )
    t0 = time.time()
    n_ims = 0
    # init images and annotations lists
    sliced_image_result = SliceImageResult(original_image_size=[image_height, image_width], image_dir=output_dir)
    # iterate over slices
    for slice_bbox in slice_bboxes:
        n_ims += 1
        # extract image
        image_pil_slice = image_pil.crop(slice_bbox)
        # process annotations if coco_annotations is given
        if coco_annotation_list is not None:
            sliced_coco_annotation_list = process_coco_annotations(coco_annotation_list, slice_bbox, min_area_ratio)
        # set image file suffixes
        slice_suffixes = "_".join(map(str, slice_bbox))
        if out_ext:
            suffix = out_ext
        else:
            try:
                suffix = Path(image_pil.filename).suffix
            except AttributeError:
                suffix = ".jpg"
        # set image file name and path
        slice_file_name = f"{output_file_name}_{slice_suffixes}{suffix}"
        # create coco image
        slice_width = slice_bbox[2] - slice_bbox[0]
        slice_height = slice_bbox[3] - slice_bbox[1]
        coco_image = CocoImage(file_name=slice_file_name, height=slice_height, width=slice_width)
        # append coco annotations (if present) to coco image
        if coco_annotation_list:
            for coco_annotation in sliced_coco_annotation_list:
                coco_image.add_annotation(coco_annotation)
        # create sliced image and append to sliced_image_result
        sliced_image = SlicedImage(image=np.asarray(image_pil_slice), coco_image=coco_image, starting_pixel=[slice_bbox[0], slice_bbox[1]],)
        sliced_image_result.add_sliced_image(sliced_image)
    # export slices if output directory is provided
    if output_file_name and output_dir:
        conc_exec = concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS)
        conc_exec.map(_export_single_slice, sliced_image_result.images, [output_dir] * len(sliced_image_result), sliced_image_result.filenames,)
    verboselog("Num slices: " + str(n_ims) + " slice_height: " + str(slice_height) + " slice_width: " + str(slice_width),)
    return sliced_image_result


4实验结果


本文采用了MS COCO评估协议进行评估,包括总体和尺寸方面的AP50评分。具体来说,AP50在所有类别的单个IoU阈值0.5处计算,最大检测数设置为500。

在表1和表2对原始图像的常规推理中,以FI(Full inference)作为Baseline。SF(切片辅助微调)是在表1和表2中patch大小分别为480-640和300-500的增强数据集上进行微调的模型。

SAHI(切片辅助Hyper Inference)是指表1和表2中patch大小分别为640×640和400×400的推理。OP(Overlap Patch)表示切片推理过程中Patch之间有25%的重叠。

表1

从表1可以看出,SAHI使目标检测AP分别提高了6.8%、5.1%和5.3%。SF可进一步提高检测精度,FCOS、VFNet和tod检测器的累计AP分别提高12.7%、13.4%和14.5%。在推理过程中,应用切片间25%的重叠,会增加小/中物体AP和整体AP,但略微降低大物体AP。增加是由切片预测的额外小目标真阳性引起,减少是由匹配大GT框的切片预测的假阳性引起。小目标检测AP以SF最佳,SI次之,大目标检测AP以SF最佳,FI次之,证实了FI对大目标检测的贡献。

表2

xView数据集的结果如表2所示。由于xView目标非常小,经常使用原始图像进行训练,检测性能较差,SF大大提高了结果。FI的集成使大目标AP增加了3.0%,但导致小型/中型目标AP略有下降,这是预期的,因为一些较大的目标可能无法从较小的切片中检测到。切片间25%的重叠可以增加2.9%的检测AP。

图3

xView包含高度不平衡的60个目标类别,尽管FCOS是一个较老的,据说较弱的检测器,但对于这个数据集,FCOS比VFNet有更好的性能。这一观察结果证实了FCOS中Focal Loss的有效性,该方法旨在处理类别失衡。TOOD在训练过程中也受益于Focal Loss,在3种检测器中检测效果最好。tod检测器在Visdrone和xView数据集上的误差分析结果分别如图3和图4所示。

图4


5参考


[1].SLICING AIDED HYPER INFERENCE AND FINE-TUNING FOR SMALL OBJECT DETECTION

相关文章
|
7月前
|
编解码 缓存 计算机视觉
改进的yolov5目标检测-yolov5替换骨干网络-yolo剪枝(TensorRT及NCNN部署)-1
改进的yolov5目标检测-yolov5替换骨干网络-yolo剪枝(TensorRT及NCNN部署)-1
|
7月前
|
算法 PyTorch 计算机视觉
改进的yolov5目标检测-yolov5替换骨干网络-yolo剪枝(TensorRT及NCNN部署)-2
改进的yolov5目标检测-yolov5替换骨干网络-yolo剪枝(TensorRT及NCNN部署)-2
改进的yolov5目标检测-yolov5替换骨干网络-yolo剪枝(TensorRT及NCNN部署)-2
|
2月前
|
PyTorch 算法框架/工具 计算机视觉
目标检测实战(二):YoloV4-Tiny训练、测试、评估完整步骤
本文介绍了使用YOLOv4-Tiny进行目标检测的完整流程,包括模型介绍、代码下载、数据集处理、网络训练、预测和评估。
182 2
目标检测实战(二):YoloV4-Tiny训练、测试、评估完整步骤
|
2月前
|
计算机视觉
目标检测笔记(二):测试YOLOv5各模块的推理速度
这篇文章是关于如何测试YOLOv5中不同模块(如SPP和SPPF)的推理速度,并通过代码示例展示了如何进行性能分析。
132 3
|
4月前
|
机器学习/深度学习 算法 计算机视觉
5.2 单阶段目标检测模型YOLOv3
这篇文章详细介绍了单阶段目标检测模型YOLOv3的基本原理和网络结构,包括如何生成候选区域、锚框的设计、预测框的生成以及如何对这些候选区域进行标注,并通过卷积神经网络进行特征提取和预测。
|
6月前
|
机器学习/深度学习 分布式计算 并行计算
基于YOLO和Darknet预训练模型的对象检测
【6月更文挑战第6天】基于YOLO和Darknet预训练模型的对象检测。
64 2
|
6月前
|
固态存储
【YOLO系列】YOLOv10模型结构详解与推理部署实现
【YOLO系列】YOLOv10模型结构详解与推理部署实现
1145 0
|
7月前
|
机器学习/深度学习 网络架构
YOLOv8改进 | 2023主干篇 | 利用RT-DETR特征提取网络PPHGNetV2改进YOLOv8(超级轻量化精度更高)
YOLOv8改进 | 2023主干篇 | 利用RT-DETR特征提取网络PPHGNetV2改进YOLOv8(超级轻量化精度更高)
514 1
|
7月前
|
并行计算 计算机视觉
YOLOv8太卷啦 | YOLOv8官方仓库正式支持RT-DETR训练、测试以及推理
YOLOv8太卷啦 | YOLOv8官方仓库正式支持RT-DETR训练、测试以及推理
551 0
|
编解码 自然语言处理 并行计算
【经典论文解读】YOLACT 实例分割(YOLOv5、YOLOv8实例分割的基础)
 YOLACT是经典的单阶段、实时、实例分割方法,在YOLOv5和YOLOv8中的实例分割,也是基于 YOLACT实现的,有必要理解一下它的模型结构和设计思路。
1937 0