深度学习之目标检测小目标增强(SAHI)

环境搭建

pip install sahi -i https://pypi.tuna.tsinghua.edu.cn/simple

小目标增强方法1:

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

小目标增强方法2:

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

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

切片推理3

在推理过程中,应用切片间25%的重叠,会增加小/中物体AP和整体AP,但略微降低大物体AP。增加是由切片预测的额外小目标真阳性引起,减少是由匹配大GT框的切片预测的假阳性引起。小目标检测AP以SF最佳,SI次之,大目标检测AP以SF最佳,FI次之,证实了FI对大目标检测的贡献。

检测小目标和远程目标检测是监控应用中的一个主要挑战。这些物体由图像中少量的像素表示,缺乏足够的细节,使得传统的检测器难以检测。在这项工作中,提出了一个名为切片辅助超推理(SAHI)的开源框架,该框架为小目标检测提供了一个通用的切片辅助推理和微调管道。所提出的技术是通用的,因为它可以应用在任何可用的目标检测器之上,而不需要进行任何微调。

利用Visdrone和xView空中目标检测数据集上的目标检测Baseline的实验评估表明,该推理方法可将FCOS、VFNet和TOOD检测器的目标检测AP分别提高6.8%、5.1%和5.3%。此外,通过切片辅助微调可以进一步提高检测精度,从而按相同的顺序累计增加了12.7%、13.4%和14.5%的AP。

所提出的技术已与Detectron2、MMDetection和YOLOv5模型完成集成。

开源地址:https://github.com/obss/sahi

4、切片推理的代码解析

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

  • 5
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值