0 赛事背景说明

澳大利亚令人惊叹的美丽大堡礁是世界上最大的珊瑚礁,拥有 1,500 种鱼类、400 种珊瑚、130 种鲨鱼、鳐鱼和种类繁多的其他海洋生物。

不幸的是,珊瑚礁正受到威胁,部分原因是一种特定的海星——以珊瑚为食的棘冠海星(简称COTS)的数量过剩。科学家、旅游经营者和珊瑚礁管理者建立了一个大规模的干预计划,将COTS的爆发控制在生态可持续的水平。

为了知道COTS在哪里,一种传统的珊瑚礁调查方法,称为“蝠鲼拖曳”,由浮潜潜水员执行。在被船拖曳时,他们目视评估珊瑚礁,停下来记录每200米观察到的变量。虽然这种方法通常有效,但面临明显的局限性,包括操作可扩展性、数据分辨率、可靠性和可追溯性。

大堡礁基金会建立了一个创新计划,以开发新的调查和干预方法,以提供COTS控制的阶梯式变化。水下摄像机将收集数千张珊瑚礁图像,人工智能技术可以大大提高珊瑚礁管理者检测和控制COTS爆发的效率和规模。

为了扩大基于视频的测量系统,澳大利亚国家科学机构CSIRO与谷歌合作开发创新的机器学习技术,可以准确,高效,近乎实时地分析大型图像数据集。

1 赛题任务

赛题链接

赛题介绍视频(YouTube)

本次比赛的目标是通过构建在珊瑚礁水下视频上训练的物体检测模型,实时准确地识别海星。

您的工作将帮助研究人员识别威胁澳大利亚大堡礁的物种,并采取明智的行动为子孙后代保护珊瑚礁。

2 数据集介绍

下面给出数据集中六幅例图:

训练数据文件结构

将提供用于训练的图像数据和识别标签,文件夹结构:

|-- kaggle_dataset/train2017 # 存放训练图像数据,jpg编码图像文件

|-- kaggle_dataset/val2017 # 存放训练图像数据,jpg编码图像文件

|-- kaggle_dataset/annotations # 存放属性标签标注数据

数据标注文件的结构上,属于coco格式标注。

#设立随机种子
import random
random.seed(2)
#先解压数据集
!unzip data/data179179/kaggle_dataset.zip
#下载PaddleDetection
!git clone https://gitee.com/PaddlePaddle/PaddleDetection.git #从gitee上下载速度会快一些
#安装PaddleDetection相关依赖
!pip install -r PaddleDetection/requirements.txt
!python  PaddleDetection/setup.py install

3可视化

# 调用一些需要的第三方库
import numpy as np
import pandas as pd
import shutil
import json
import os
import cv2
import glob
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import seaborn as sns
from matplotlib.font_manager import FontProperties
from PIL import Image
import random
###解决中文画图问题
myfont = FontProperties(fname=r"NotoSansCJKsc-Medium.otf", size=12)
plt.rcParams['figure.figsize'] = (12, 12)
plt.rcParams['font.family']= myfont.get_family()
plt.rcParams['font.sans-serif'] = myfont.get_name()
plt.rcParams['axes.unicode_minus'] = False
# 加载训练集路径
TRAIN_DIR = 'kaggle_dataset/train2017/'
TRAIN_CSV_PATH = 'TRAIN_CSV_PATH = kaggle_dataset/annotations/train.json'
# 加载训练集图片目录
train_fns = glob.glob(TRAIN_DIR + '*')
print('数据集图片数量: {}'.format(len(train_fns)))
数据集图片数量: 3974
def generate_anno_result(dataset_path, anno_file):with open(os.path.join(dataset_path, anno_file)) as f:anno = json.load(f)    total=[]for img in anno['images']:hw = (img['height'],img['width'])total.append(hw)unique = set(total)ids=[]images_id=[]for i in anno['annotations']:ids.append(i['id'])images_id.append(i['image_id'])# 创建类别标签字典category_dic=dict([(i['id'],i['name']) for i in anno['categories']])counts_label=dict([(i['name'],0) for i in anno['categories']])for i in anno['annotations']:counts_label[category_dic[i['category_id']]] += 1label_list = counts_label.keys()    # 各部分标签size = counts_label.values()    # 各部分大小train_fig = pd.DataFrame(anno['images'])train_anno = pd.DataFrame(anno['annotations'])df_train = pd.merge(left=train_fig, right=train_anno, how='inner', left_on='id', right_on='image_id')df_train['bbox_xmin'] = df_train['bbox'].apply(lambda x: x[0])df_train['bbox_ymin'] = df_train['bbox'].apply(lambda x: x[1])df_train['bbox_w'] = df_train['bbox'].apply(lambda x: x[2])df_train['bbox_h'] = df_train['bbox'].apply(lambda x: x[3])df_train['bbox_xcenter'] = df_train['bbox'].apply(lambda x: (x[0]+0.5*x[2]))df_train['bbox_ycenter'] = df_train['bbox'].apply(lambda x: (x[1]+0.5*x[3]))print('最小目标面积(像素):', min(df_train.area))balanced = ''small_object = ''densely = ''# 判断样本是否均衡,给出结论if max(size) > 5 * min(size):print('样本不均衡')balanced = 'c11'else:print('样本均衡')balanced = 'c10'# 判断样本是否存在小目标,给出结论if min(df_train.area) < 900:print('存在小目标')small_object = 'c21'else:print('不存在小目标')small_object = 'c20'arr1=[]arr2=[]x=[]y=[]w=[]h=[]for index, row in df_train.iterrows():if index < 1000:# 获取并记录坐标点x.append(row['bbox_xcenter'])y.append(row['bbox_ycenter'])w.append(row['bbox_w'])h.append(row['bbox_h'])for i in range(len(x)):l = np.sqrt(w[i]**2+h[i]**2)arr2.append(l)for j in range(len(x)):a=np.sqrt((x[i]-x[j])**2+(y[i]-y[j])**2)if a != 0:arr1.append(a)arr1=np.matrix(arr1)# print(arr1.min())# print(np.mean(arr2))# 判断是否密集型目标,具体逻辑还需优化if arr1.min() <  np.mean(arr2):print('密集型目标')densely = 'c31'else:print('非密集型目标')densely = 'c30'return balanced, small_object, densely
# 分析训练集数据
generate_anno_result('kaggle_dataset', 'annotations/train.json')
最小目标面积(像素): 288
样本均衡
存在小目标
密集型目标('c10', 'c21', 'c31')

图片大小分布

# 读取训练集标注文件
with open('kaggle_dataset/annotations/train.json', 'r', encoding='utf-8') as f:train_data = json.load(f)
train_fig = pd.DataFrame(train_data['images'])
train_fig.head()
id license file_name height width date_captured
0 285 1 0-878.jpg 720 1280 2021-11-30T15:01:26+00:00
1 286 1 0-879.jpg 720 1280 2021-11-30T15:01:26+00:00
2 287 1 0-880.jpg 720 1280 2021-11-30T15:01:26+00:00
3 288 1 0-881.jpg 720 1280 2021-11-30T15:01:26+00:00
4 289 1 0-882.jpg 720 1280 2021-11-30T15:01:26+00:00
ps = np.zeros(len(train_fig))
for i in range(len(train_fig)):ps[i]=train_fig['width'][i] * train_fig['height'][i]/1e6
plt.title('训练集图片大小分布', fontproperties=myfont)
sns.distplot(ps, bins=21,kde=False)
<matplotlib.axes._subplots.AxesSubplot at 0x7f3819e35290>/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/font_manager.py:1331: UserWarning: findfont: Font family ['sans-serif'] not found. Falling back to DejaVu Sans(prop.get_family(), self.defaultFamily[fontext]))

可以看出,所有图片大小都相同,都为720*1280

训练集目标大小分布

!python box_distribution.py --json_path kaggle_dataset/annotations/train.json
Median of ratio_w is 0.0341796875
Median of ratio_h is 0.055
all_img with box:  3974
all_ann:  10589
Distribution saved as box_distribution.jpg
Figure(640x480)

注意:

  • 当原始数据集全部有标注框的图片中,有1/2以上的图片标注框的平均宽高与原图宽高比例小于0.04时,建议进行切图训练。

所以根据上面的说明,海星检测这个数据集其实介于“可切可不切”之间。当然,我们可以继续试验下,看看切图是否可以取得更加优秀的效果

train_anno = pd.DataFrame(train_data['annotations'])
df_train = pd.merge(left=train_fig, right=train_anno, how='inner', left_on='id', right_on='image_id')
df_train['bbox_xmin'] = df_train['bbox'].apply(lambda x: x[0])
df_train['bbox_ymin'] = df_train['bbox'].apply(lambda x: x[1])
df_train['bbox_w'] = df_train['bbox'].apply(lambda x: x[2])
df_train['bbox_h'] = df_train['bbox'].apply(lambda x: x[3])
df_train['bbox_xcenter'] = df_train['bbox'].apply(lambda x: (x[0]+0.5*x[2]))
df_train['bbox_ycenter'] = df_train['bbox'].apply(lambda x: (x[1]+0.5*x[3]))
df_train['bbox_w'].max(),df_train['bbox_h'].max()
(243, 222)
ps = np.zeros(len(df_train))
for i in range(len(df_train)):ps[i]=df_train['area'][i]/1e6ps = np.zeros(len(df_train))
plt.title('训练集目标大小分布', fontproperties=myfont)
sns.distplot(ps, bins=21,kde=True)
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/seaborn/distributions.py:288: UserWarning: Data must have variance to compute a kernel density estimate.warnings.warn(msg, UserWarning)<matplotlib.axes._subplots.AxesSubplot at 0x7f3819ce2290>

各类别目标形状分布

# 各类别目标形状分布
sns.set(rc={'figure.figsize':(12,6)})
sns.relplot(x="bbox_w", y="bbox_h", hue="category_id", col="category_id", data=df_train[0:1000])
<seaborn.axisgrid.FacetGrid at 0x7f3d8bb6f350>

各类别目标中心点形状分布

# 各类别目标中心点形状分布
sns.set(rc={'figure.figsize':(12,6)})
sns.relplot(x="bbox_xcenter", y="bbox_ycenter", hue="category_id", col="category_id", data=df_train[0:1000]);

# 训练集目标大小统计结果
df_train.area.describe()
count    10589.000000
mean      2169.974974
std       1897.813611
min        288.000000
25%       1152.000000
50%       1728.000000
75%       2850.000000
max      52170.000000
Name: area, dtype: float64

训练集目标个数分布

df_train['bbox_count'] = df_train.apply(lambda row: 1 if any(row.bbox) else 0, axis=1)
train_images_count = df_train.groupby('file_name').sum().reset_index()
plt.title('训练集目标个数分布', fontproperties=myfont)
sns.distplot(train_images_count['bbox_count'], bins=21,kde=True)
<matplotlib.axes._subplots.AxesSubplot at 0x7f3d8b493a90>

分析结论:海星检测的数据集图片分辨率相同,均为1280*720、小目标占比相当大。

总的来说,这是个比较典型的小目标检测场景。

4 方案

本项目使用飞桨目标检测开发套件PaddleDetection,它可以端到端地完成从训练到部署的全流程目标检测应用。

具体方案

算法选择

由于本项目是典型的小目标检测,所以选取针对小目标优化的PP-YOLOE-SOD模型,并采取切图方法

相比PP-YOLOE模型,PP-YOLOE-SOD改进点主要包括在neck中引入 Transformer全局注意力机制 以及在回归分支中使用 基于向量的DFL 。

数据增强

- RandomExpand: {fill_value: [123.675, 116.28, 103.53]}
- GridMask: {}
- Mixup: {}
- Cutmix: {}
- RandomCrop: {}
- RandomFlip: {}
# 安装`sahi`库,用来切图
!pip install sahi
# 对训练集标注进行切图
!python PaddleDetection/tools/slice_image.py --image_dir kaggle_dataset/train2017\--json_path kaggle_dataset/annotations/train.json --output_dir kaggle_dataset/train2017_400_sliced --slice_size 400 --overlap_ratio 0.25
# 对验证集标注进行切图
!python PaddleDetection/tools/slice_image.py --image_dir kaggle_dataset/val2017\--json_path kaggle_dataset/annotations/valid.json --output_dir kaggle_dataset/val2017_400_sliced --slice_size 400 --overlap_ratio 0.25
####参数说明
#image_dir 原始数据集图片文件夹的路径
#json_path coco标注数据文件地址
#output_dir 切图结果所在文件位置
#slice_size 切图大小(默认为正方形)
#overlap_ratio 切分时的子图之间的重叠率

模型训练

直接使用PaddleDetection进行模型训练的过程可以很简单,改改配置文件就好了。详细说明可查看PaddleDetection模型参数配置教程。
本项目使用的模型是ppyoloe_p2_crn_l_80e_sliced_xview_400_025.yml,相关配置文件如下:

  • configs/ppyoloe/_base_/xview_sliced_400_025_detection.yml

    • 数据配置文件

configs/smalldet/ppyoloe_p2_crn_l_80e_sliced_xview_400_025.yml
- sniper模型配置文件

  • configs/runtime.yml

    • 运行时配置文件
  • configs/ppyoloe/_base_/ppyoloe_crn.yml
    • 模型配置文件
  • configs/ppyoloe/_base_/optimizer_300e.yml
    • 优化器配置文件
  • configs/ppyoloe/_base_/ppyoloe_reader.yml
    • 数据读取配置文件

在使用配置文件,尤其是数据配置文件时,读者请注意尽量使用绝对路径配置数据集,可以避免不少报错。

毫无疑问,切图后模型的训练是要基于切图数据集的,配置如下:

metric: COCO
num_classes: 1TrainDataset:!COCODataSetimage_dir: train_images_400_025anno_path: train_400_025.jsondataset_dir: kaggle_dataset/train2017_400_sliceddata_fields: ['image', 'gt_bbox', 'gt_class', 'is_crowd']EvalDataset:!COCODataSetimage_dir: valid_images_400_025anno_path: valid_400_025.jsondataset_dir: kaggle_dataset/val2017_400_sliced
# 开始训练,训练环境为单卡V100(32G)
!python PaddleDetection/tools/train.py -c configs/ppyoloe_p2_crn_l_80e_sliced_xview_400_025.yml --use_vdl=True -o worker_num=8 --eval

训练时间较长,一个epoch大约九分钟,评估需要约三分半钟,可以提交后台任务执行。相关设置可参考:后台任务使用说明。

然后再将后台任务的输出加载回项目中,继续进行评估操作。

模型评估

训练过程可以点击左侧的可视化按钮查看趋势:

#模型评估
!python PaddleDetection/tools/eval.py -c configs/ppyoloe_p2_crn_l_80e_sliced_xview_400_025.yml
W1205 12:10:58.174906 17614 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 8.0, Driver API Version: 11.2, Runtime API Version: 11.2
W1205 12:10:58.178177 17614 gpu_resources.cc:91] device: 0, cuDNN Version: 8.2.
loading annotations into memory...
Done (t=0.09s)
creating index...
index created!
[12/05 12:11:03] ppdet.utils.checkpoint INFO: Finish loading model weights: bestmodel/best_model.pdparams
[12/05 12:11:05] ppdet.engine INFO: Eval iter: 0
[12/05 12:11:54] ppdet.engine INFO: Eval iter: 100
[12/05 12:13:01] ppdet.metrics.metrics INFO: The bbox result is saved to bbox.json.
loading annotations into memory...
Done (t=0.02s)
creating index...
index created!
[12/05 12:13:01] ppdet.metrics.coco_utils INFO: Start evaluate...
Loading and preparing results...
DONE (t=11.11s)
creating index...
index created!
Running per image evaluation...
Evaluate annotation type *bbox*
DONE (t=15.44s).
Accumulating evaluation results...
DONE (t=2.56s).Average Precision  (AP) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.502Average Precision  (AP) @[ IoU=0.50      | area=   all | maxDets=100 ] = 0.810Average Precision  (AP) @[ IoU=0.75      | area=   all | maxDets=100 ] = 0.574Average Precision  (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.172Average Precision  (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.574Average Precision  (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.760Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=  1 ] = 0.499Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets= 10 ] = 0.591Average Recall     (AR) @[ IoU=0.50:0.95 | area=   all | maxDets=100 ] = 0.619Average Recall     (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = 0.408Average Recall     (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.670Average Recall     (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.800
[12/05 12:13:32] ppdet.engine INFO: Total sample number: 2663, averge FPS: 26.871781479080514

sample number: 2663, averge FPS: 26.871781479080514

训练结果





方案效果对比

方案 ap @[ IoU=0.50:0.95]
ppyoloe 0.315
切图+ppyoloe-sod 0.490
切图+ppyoloe-sod +数据增强 0.502

进一步改进的方向

  • 采用多模型融合的策略
  • 使用更大的backbone,如convnext
  • 可以尝试使用two_stage算法
  • 进一步扩展数据增强

5总结

本项目是一个典型的小目标检测场景,直接用yolo算法做简单的finetune并不能取得很好的结果,在本项目只取得了ap为0.315的成绩。
所以针对此场景,采用切图的方法,并选取了针对小目标场景优化后的算法,效果得到明显改善,ap达到了0.490。进一步采取数据增强的方式,模型ap值提高到0.502。
同时,本项目仍然有很大的优化空间。

关于作者

项目作者: 姓名:李灿 AI Studio昵称: Nefelibata0 个人主页

飞桨导师: 姓名:韩磊 AI Studio昵称: ninetailskim 个人主页

PS:本人菜鸟一只,欢迎互相关注


此文章为搬运
原项目链接

基于ppyoloe-sod海星目标检测相关推荐

  1. 基于深度学习的目标检测论文综述Paper Reading:A Survey of Deep Learning-based Object Detection(中文)

    摘要 介绍了文章的大致思路和结构: 1.介绍,经典的目标检测算法,数据集 2.分析比对,各种目标检测算法,包括一阶段和两阶段的 3.介绍,传统和新的应用,以及一些目标检测的其他分支 4.讨论,用目前这 ...

  2. 【lidar】基于YOLO的3D目标检测(激光雷达点云)课程设计

    基于YOLO的3D目标检测(激光雷达点云)课程设计 代码+数据集下载地址:下载地址

  3. 基于深度学习的目标检测综述

    基于深度学习的目标检测算法归类和总结 整体框架 目标检测算法 主要包括:[两阶段]目标检测算法.[多阶段]目标检测算法.[单阶段]目标检测算法 什么是两阶段目标检测算法,与单阶段目标检测有什么区别? ...

  4. 病虫害模型算法_基于深度学习的目标检测算法综述

    sigai 基于深度学习的目标检测算法综述 导言 目标检测的任务是找出图像中所有感兴趣的目标(物体),确定它们的位置和大小,是机器视觉领域的核心问题之一.由于各类物体有不同的外观,形状,姿态,加上成像 ...

  5. 综述 | 基于深度学习的目标检测算法

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:计算机视觉life 导读:目标检测(Object Det ...

  6. CaDDN:基于单目的3D目标检测新方法(CVPR2021)

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨元气满满的打工人 来源丨CV研习社 文章导读 导读:在自动驾驶的技术中,3D目标检测能够提更加丰 ...

  7. 致敬YOLO!华科提出YOLOS:基于视觉Transformer的目标检测

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 导读 本文是华科&地平线关于Transformer的迁移学习.泛化性能方面的深度思考.重点揭示 ...

  8. 基于深度学习的目标检测的研究进展2

    普通的深度学习监督算法主要是用来做分类,如图1(1)所示,分类的目标是要识别出图中所示是一只猫.而在ILSVRC(ImageNet Large Scale Visual Recognition Cha ...

  9. 基于深度学习的目标检测研究进展

    前言 开始本文内容之前,我们先来看一下上边左侧的这张图,从图中你看到了什么物体?他们在什么位置?这还不简单,图中有一个猫和一个人,具体的位置就是上图右侧图像两个边框(bounding-box)所在的位 ...

  10. 基于深度学习的目标检测算法综述(从R-CNN到Mask R-CNN)

    深度学习目标检测模型全面综述:Faster R-CNN.R-FCN和SSD 从RCNN到SSD,这应该是最全的一份目标检测算法盘点 基于深度学习的目标检测算法综述(一) 基于深度学习的目标检测算法综述 ...

最新文章

  1. asp.net core上使用redis探索(1)
  2. has invalid type class 'numpy.ndarray', must be a string or Tensor
  3. 小程序接收json_微信推出QQ小程序,但只能接收消息无法回复!网友:鸡肋
  4. LCD1602液晶显示模块的单片机驱动深入详解之硬件篇
  5. 2.7.3 ecshop php7.1_ECshop 迁移到 PHP7版本时遇到的兼容性问题
  6. Spark SQL之queryExecution运行流程解析Logical Plan(三)
  7. UDLD(Unidirectional Link Detection)
  8. Spring实战(十三)Spring事务
  9. 读写分离设计:复制延迟?其实是你用错了
  10. Echarts关系图(使用重力图)
  11. 雷林鹏分享Node.js Buffer(缓冲区)
  12. sql注入 java_JAVA实现sql注入点检测
  13. 基于TI Davinci架构的双核嵌入式应用处理器OMAPL138开发入门
  14. Linux系统之热插拨事件uevent
  15. PS按照图片大小调整画布大小
  16. spring-boot-maven-plugin爆红
  17. 【环境配置】ceres solver安装
  18. leetcode剑指offer4
  19. C# WinForm创建Excel文件
  20. 远程登录Linux服务器

热门文章

  1. 前端学习笔记(五):VUE基础学习笔记
  2. 底包和基带是什么?刷机前有必要先刷它们吗?
  3. 相爱相杀六年,Elastic终与AWS就商标问题达成共识
  4. 女人最让男人伤心的10句话
  5. 1到n的阶乘之和公式c语言,n的阶乘(1到n的阶乘之和公式)
  6. 单元测试的框架Hamcrest
  7. 如何成为一个Python培训老师
  8. Latex论文表格画法
  9. linux rm文件恢复总结
  10. Handlebar嵌套遍历数据