『SAHI』大图片小目标检测切片辅助超推理库
# 前言
目前我们课题组中涉及到了超大图片的小目标识别。图片除了像素尺寸超大之外,长宽比也是极度失衡(像素 20000 x 1000),所以正常思路我们就需要先对图片进行切图,否则训练时输入图片直接 resize 成等边矩形,很容易丢失和扭曲关键语义信息
注意:正常情况下 20000x1000 的图片可以沿着长边裁剪出多张 1000x1000 小图片,设置 overlap 为 0.25
然后我们使用切图后的小图片数据集训练,训练好之后,进行推理预测时,假设输入的图片分辨率为 20000x1000,我们同样需要进行切图,切成多张 1000x1000 的图,分别进行推理,然后再将这多张1000x1000图的推理结果合并成 20000x1000 的推理结果图片
但是手动进行上述操作太过麻烦,下面我将要介绍可以完美解决上述难题的开源工具
# SAHI
SAHI
是一款用于超大图片中对小目标检测的切片辅助超推理库,本文将会使用 YOLOv8 作为目标检测算法模型
SAHI CLI 命令行官方文档:sahi/docs/cli.md at main · obss/sahi (github.com) (opens new window)
YOLOv8 SAHI 官方文档地址:SAHI Tiled Inference - Ultralytics YOLOv8 Docs (opens new window)
# 算法特点
无缝集成:SAHI 毫不费力地与 YOLO 模型集成,这意味着您无需修改大量代码即可开始切片和检测。
资源效率:通过将大图像分解为较小的部分,SAHI 优化了内存使用,允许您在资源有限的硬件上运行高质量的检测。
高精度:SAHI通过在拼接过程中采用智能算法合并重叠的检测框来保持检测精度
# 切片推理
**切片推理(Sliced Inference)**是指将大型或高分辨率图像细分为较小的片段(切片),对这些切片进行对象检测,然后重新编译切片以重建原始图像上的对象位置的做法。在计算资源有限的情况下,或者在处理可能导致内存问题的极高分辨率图像的情况下,此技术非常宝贵。
简述整个流程就是,通过滑动窗口将图像切分成若干区域,各个区域分别进行预测,同时也对整张图片进行推理。然后将各个区域的预测结果和整张图片的预测结果合并,最后用NMS(非极大值抑制)进行过滤。用动图表示该识别过程如下
# 小目标定义
对象检测是迄今为止计算机视觉中最重要的应用领域。然而,小物体的检测和大图像的推理仍然是实际使用中的主要问题,这是因为小目标物体有效特征少,覆盖范围少。
小目标物体的定义通常有两种方式。一种是绝对尺度定义,即以物体的像素尺寸来判断是否为小目标,如在COCO数据集中,尺寸小于32×32像素的目标被判定为小目标。另外一种是相对尺度定义,即以物体在图像中的占比面积比例来判断是否为小目标,例如国际光学工程学会SPIE定义,若目标尺寸小于原图的0.12%则可以判定成小目标。
# 安装配置
注意:默认您已经安装配置好了 YOLOv8
下面将会主要使用 sahi cli 命令行作为示例
安装 sahi
pip install sahi
首先我们需要将图片标注,标志之后我们就可以使用 sahi slice 功能切片给定的图像和对应的标注文件
注意:sahi 默认使用 coco 数据集
# 转换数据集
首先我们需要将 yolo txt 格式数据集转换为 coco 格式数据集
推荐仓库:DeepLearning/others/label_convert at master · KKKSQJ/DeepLearning (github.com) (opens new window)
但是上面的仓库是一个集成的全面的工具库,可能有很多大家不需要的功能,博主单独给数据集转换的下载下来单独上传到 Github,大家只是使用数据集转换的话可以直接使用这个仓库:ReturnTmp/label-convert: voc coco yolo 数据集标注转换脚本 (github.com) (opens new window)
警告:上面仓库使用过程中出现问题,推荐使用下面的仓库
仓库地址:Weifeng-Chen/dl_scripts (github.com) (opens new window)
# 开始转换
# 原仓库转换方式(已废弃)
警告:由于上面的仓库出现问题,导致本方法 yolo 转换 coco 数据集失败,请不要使用此章节的方法,请直接跳转新仓库转换方式章节
下载脚本
git clone git@github.com:ReturnTmp/label-convert.git
转化数据集(yolo2coco)
python ./yolo2coco.py -ap ../yolo/ -s ../coco/ --image-path ../yolo/
切分 coco 数据集
sahi coco slice --image_dir ./yolo/ --dataset_json_path ./coco/train.json --slice_size 512 --overlap_ratio 0.2
最后我们看到切分之后的数据集导出到了当前目录的 runs/slice_coco
然后我们就可以将切分之后的 coco 数据集导出为 yolo 数据集
cd runs/slice_coco
sahi coco yolov5 --image_dir ./train_images_512_02/ --dataset_json_path ./train_512_02.json --train_split 0.9
2
然后导出到了 runs/coco2yolov5/exp
我们可以看到里面划分为了 train 和 val 文件夹,然后我们就可以投喂给 YOLOv8 进行训练
然后我们就可以使用 sahi cli 命令行来用 yolo 训练好的模型文件来进行预测
sahi predict --source image/file/or/folder --model_path path/to/model --model_config_path path/to/config
# 新仓库转换方式
仓库目录格式排列如下
└── $ROOT_PATH
├── classes.txt
├── images
└──labels
2
3
4
数据集转换
注:转换之后当前目录就会生成 annotations 文件夹,里面就会有生成的 train.json 文件
# 下载脚本
git clone git@github.com:Weifeng-Chen/dl_scripts.git
# 转换
python dl_scripts/detection/yolo2coco.py --root_dir ./
2
3
4
数据集切分
sahi coco slice --image_dir ./yolo/ --dataset_json_path ./coco/train.json --slice_size 512 --overlap_ratio 0.2
注:其他与 sahi 的可以直接参考上面的旧仓库部分,此处不赘述
# 个人记录
注:本章为博主个人项目中使用的常用命令,便于自身查找,读者可酌情阅读
# 数据集转换(yolo2coco)
python ./datasets/label-convert/yolo2coco.py -ap ./datasets/TVDSDataSet/labels -s ./datasets/TVDSDataSet/json --image-path ./datasets/TVDSDataSet/images
# 切分图片
sahi coco slice --image_dir ./datasets/TVDSDataSet/images/ --dataset_json_path ./datasets/TVDSDataSet/json/train.json --slice_size 512 --overlap_ratio 0.2
# 数据集转换及划分(coco2yolo)
注意:这里我直接使用的 yolov5 ,但是不清楚 yolov8 可不可以,我没有试,按理来说 2023 年 sahi 加入了 yolov8 模型,应该可以
sahi coco yolov5 --image_dir ./runs/slice_coco/train_images_512_02/ --dataset_json_path ./runs/slice_coco/train_512_02.json --train_split 0.9
# YOLOv8 训练(nohup)
yolo train data=runs/coco2yolov5/exp/data.yml model=yolov8x.pt epochs=20 lr0=0.01 batch=8 device=0,1,2,3
时间比较久可以使用 nohup 后台运行
nohup yolo train data=runs/coco2yolov5/exp/data.yml model=yolov8x.pt epochs=20 lr0=0.01 batch=8 device=0,1,2,3 &
注意:但是使用 nohup 在使用多块 GPU 并行处理 pytorch 时容易出现问题
torch.distributed.elastic.multiprocessing.api.SignalException: Process 652386 got signal: 1
,可以使用 tmux 代替,关于 tmux 的使用可以搜索博主的相关文章,下面是示例命令
# YOLOv8 训练(tmux)
# 新建会话
tmux new -s sahi-yolo
# 开始训练
yolo train data=runs/coco2yolov5/exp/data.yml model=yolov8x.pt epochs=20 lr0=0.01 batch=8 device=0,1,2,3
# 会话分离
Ctrl+b d
# 重新连接会话
tmux attach-session -t sahi-yolo
2
3
4
5
6
7
8
# sahi yolov8 模型预测
sahi predict --slice_width 512 --slice_height 512 --overlap_height_ratio 0.2 --overlap_width_ratio 0.2 --model_confidence_threshold 0.25 --source ultralytics/assets/tvds --model_path runs/detect/train24/weights/best.pt --model_type yolov8
这里需要说下我在执行上面命令的时候出现错误 segmentation fault
,这个我暂时还没方法,只能退而求其次暂时使用 yolo 原生命令行预测
yolo predict model=runs/detect/train24/weights/best.pt source=ultralytics/assets/tvds save_txt=True save_crop=True
如果中间断开训练使用如下命令继续训练
yolo train resume model=runs/detect/train24/weights/last.pt
注意:yolov8 模型是 2023 年新加入的,所以 sahi 需要下载最新版
# 出现问题
本章节仅作记录问题,请大家酌情跳过
注意:使用
yolo2coco.py
脚本转换之后得到的是标准coco json
格式文件,但是和labelme json
文件格式是有差异的,不能直接导入,需要进行转换
然后使用 labelme 打开对应 json 标注文件之后,容易出现 Error opening file 'imageData'
问题,下面是解决方案
可以直接在命令行关闭该功能
labelme --nodata data_annotated/
或是图形化界面中左上角 File ,然后关闭 Save With image Data
即可
或者是修改 ~/.labelmerc
(推荐)
store_data: false
注意:开启保存 imageData ,也就是默认您训练的时候图像信息将会直接从 json 文件的 imageData 属性中读取,可能导致您的 json 文件非常大
# 参考文章
资源分享 | SAHI:超大图片中对小目标检测的切片辅助超推理库 - 知乎 (zhihu.com) (opens new window)
【目标检测】SAHI: 切片辅助推理和微调小目标检测-腾讯云开发者社区-腾讯云 (tencent.com) (opens new window)
【SAHI】即插即用| SAHI操作可有效解决小目标检测过程中的难点!实现涨点 - 掘金 (juejin.cn) (opens new window)
[深度学习] 基于切片辅助超推理库SAHI优化小目标识别_落痕的寒假的博客-CSDN博客 (opens new window)
Labelme json 文件与 Coco目标检测标注json 文件格式分析与转换 (opens new window)