大赛背景
在全球人工智能发展和治理广受关注的大趋势下,由中国图象图形学学会、蚂蚁集团、云安全联盟CSA大中华区主办,广泛联合学界、机构共同组织发起全球AI攻防挑战赛。本次比赛包含攻防两大赛道,分别聚焦大模型自身安全和大模型生成内容的防伪检测,涉及信用成长、凭证审核、商家入驻、智能助理等多个业务场景,覆盖机器学习、图像处理与计算机视觉、数据处理等多个算法领域,旨在聚合行业及学界力量共同守护AI及大模型的安全,共同推动AI安全可信技术的发展。
任务说明
金融领域交互式自证业务中涵盖用户开户、商家入驻、职业认证、商户解限等多种应用场景,通常都需要用户提交一定的材料(即凭证)用于证明身份信息、所有权信息、交易信息、资质信息等,而凭证的真实性一直是困扰金融场景自动化审核的一大难题。随着数字媒体编辑技术的发展,越来越多的AI手段和工具能够轻易对凭证材料进行篡改,大量的黑产团伙也逐渐掌握PS、AIGC等工具制作逼真的凭证样本,并对金融审核带来巨大挑战。
为此,开设AI核身-金融凭证篡改检测赛道。将会发布大规模的凭证篡改数据集,参赛队伍在给定的大规模篡改数据集上进行模型研发,同时给出对应的测试集用于评估算法模型的有效性。
比赛任务
在本任务中,要求参赛者设计算法,找出凭证图像中的被篡改的区域。
数据集介绍
特别说明:参赛选手不允许使用额外数据
本次比赛将发布超大规模自研光鉴凭证数据集,该数据集整合了大量开源的图像数据和内部的业务数据。数据的构建方式为在原始图像数据上针对文字区域采用copy move,splicing,removal,局部AIGC等方式进行数字篡改编辑。
模型的泛化性也将是此次比赛重要的衡量指标,因此本次的测试集将比训练集包含更多的凭证类型和篡改编辑手法。
数据集格式如下:
训练集数据总量为100w,提供篡改后的凭证图像及其对应的篡改位置标注,标注文件以csv格式给出,csv文件中包括两列,内容示例如下:
PathPolygon9/9082eccbddd7077bc8288bdd7773d464.jpg[[[143, 359], [432, 359], [437, 423], [141, 427]]]测试集分为A榜和B榜,分别包含10w测试数据。测试集中数据格式与训练集中一致,但不包含标注文件。
语义分割与实例分割模型
语义分割和实例分割都是计算机视觉领域中的对象识别任务,它们的目标是识别并理解图像中的内容。简单来说,语义分割关注的是“这是什么”,而实例分割关注的是“这是什么”以及“这是哪一件”。实例分割比语义分割更复杂,因为它需要更多的上下文信息来区分不同的实例。
- 语义分割(Semantic Segmentation):将图像中的每个像素分配给一个类别标签,从而识别出图像中所有对象的类别。
- 实例分割(Instance Segmentation):不仅要识别图像中的对象类别,还要区分同一类别中的不同实例。
解题思路
赛题是一个典型的计算机视觉问题,涉及到图像处理和模式识别。赛题需要识别和定位图像中被篡改的区域。
- 物体检测模型:可以将篡改区域视为需要检测的“物体”。使用像Faster R-CNN或YOLO这样的物体检测模型,可以定位图像中的不同区域,并判断这些区域是否被篡改。
- 语义分割模型:语义分割模型可以将图像中的每个像素分配给一个类别,这可以用来识别图像中的篡改区域。U-Net、DeepLab或Mask R-CNN是常用的语义分割模型。
赛题提交要求
训练集数据总量为100w,提供篡改后的凭证图像及其对应的篡改位置标注,标注文件以csv格式给出,csv文件中包括两列,内容示例如下:
PathPolygon9/9082eccbddd7077bc8288bdd7773d464.jpg[[[143, 359], [432, 359], [437, 423], [141, 427]]]测试集分为A榜和B榜,分别包含10w测试数据。测试集中数据格式与训练集中一致,但不包含标注文件。
比赛期间,参赛队伍通过天池平台下载数据,本地调试算法,在线提交结果,结果文件命名为"参赛队名称-result.csv",包含"Path"和"Polygon"列,"Polygon"列中采用轮廓点的方式存储每个篡改区域的位置,每个区域包含[左上,右上,右下,左下]4个点的坐标。例如:
PathPolygon0/0aeaefa50ac1e39ecf5f02e4fa58a6a2.jpg[[[139, 48], [181, 48], [181, 66], [139, 66]]]
YOLO 模型介绍
YOLO 模型介绍
物体检测是计算机视觉领域的一个重要任务,它的目标是在图像或视频帧中识别和定位感兴趣的物体。物体检测算法不仅要识别图像中的对象属于哪个类别,还要确定它们在图像中的具体位置,通常以边界框(bounding box)的形式表示。以下是物体检测的一些关键概念和步骤:
- 输入:物体检测算法的输入通常是一张图像或视频帧。
- 特征提取:算法使用深度学习模型(如卷积神经网络CNN)来提取图像的特征。这些特征捕捉了图像中的视觉信息,为后续的物体识别和定位提供基础。
- 候选区域生成:在某些检测算法中,如基于区域的卷积神经网络(R-CNN)及其变体,首先需要生成图像中的候选区域,这些区域可能包含感兴趣的物体。
- 区域分类和边界框回归:对于每个候选区域,算法需要判断它是否包含特定类别的物体,并预测物体的边界框。这通常涉及到分类任务和回归任务的结合。
- 非极大值抑制(NMS):在检测过程中,可能会产生多个重叠的边界框,用于表示同一物体。NMS是一种常用的技术,用于选择最佳的边界框并去除多余的框。
YOLO,全称为"You Only Look Once",是一种流行的实时目标检测算法,由Joseph Redmon等人于2015年首次提出。YOLO的核心思想是将目标检测任务视为一个单一的回归问题,直接从图像像素到边界框坐标和类别概率的映射。这种设计使得YOLO能够以非常快的速度进行目标检测,同时保持较高的精度,特别适合需要实时处理的应用场景。
- YOLO算法的一个显著特点是它在单个网络评估中同时预测多个边界框和类别概率,而不是像传统的滑动窗口方法那样多次评估。
- YOLO使用一个卷积神经网络(CNN)来提取图像特征,然后使用这些特征来预测边界框和类别概率。YOLO的网络结构通常包括多个卷积层和池化层。
- YOLO为每个边界框预测一个置信度,这个置信度反映了边界框包含目标的概率以及预测的类别。置信度的计算公式是:
Pr(Object) * IOU(pred, truth)
,其中Pr(Object)
表示格子中存在目标的概率,IOU(pred, truth)
表示预测框和真实框的交并比。
YOLO(You Only Look Once)是一种革命性的目标检测算法,以其快速和高效的性能而闻名。自2015年YOLOv1的首次推出以来,YOLO系列已经经历了多次迭代,每一次迭代都在速度、准确性和计算效率方面做出了显著的贡献。
版本号
年份
主要贡献与特点
YOLOv1
2015
实时端到端物体检测,将检测视为回归问题,单次网络评估预测位置和类别。
YOLOv2
2016
引入批量归一化,高分辨率分类器,全卷积网络,能检测超过9000个类别。
YOLOv3
2018
使用更深的Darknet-53网络,引入特征金字塔网络提高多尺度目标检测能力。
YOLOv4
2020
结合CSPNet、PANet、SAM等技术,提高特征提取和检测效率。
YOLOv5
2020
使用Pytorch框架,不同大小模型版本适应不同环境,易用性和性能显著改进。
YOLOv6
2021
多种不同尺寸模型适应工业应用,继续在YOLO系列基础上改进。
YOLOv7
2022
架构变化和一系列免费包提高准确率,保持实时性。
YOLOv8
2023
新功能和改进,包括新的骨干网络、Anchor-Free检测头和新损失函数,提升性能和灵活性。
YOLOv9
2023
引入可编程梯度信息(PGI)和基于梯度路径规划的通用高效层聚合网络(GELAN)架构。
YOLOv10
2024
通过消除非最大抑制(NMS-Free)和优化各种模型组件,实现了最先进的性能。
YOLOv1至YOLOv3主要由Joseph Redmon及其合作者提出,而后续版本则由不同的研究者和团队负责开发。YOLOv4之后的版本,尤其是YOLOv5和YOLOv8,由Ultralytics公司开发和维护。YOLOv5和YOLOv8也是现在比较流行的版本。
YOLO 数据集格式
YOLO算法的标注格式主要使用
.txt
文件来存储图像中物体的标注信息。每个图像都有一个对应的
.txt
文件,文件中的每行表示一个物体的标注,包括物体的类别索引和边界框(bounding box)的坐标。以下是YOLO标注格式的详细介绍:
- 类别索引:每个物体的类别由一个整数索引表示,索引对应于预先定义的类别列表。
- 边界框坐标:边界框由其中心点坐标
(x_center, y_center)
和宽度width
、高度height
组成。这些值通常是归一化到图像宽度和高度的比例值,范围在0到1之间。 - 坐标格式:边界框坐标通常按照
[class_index x_center y_center width height]
的格式记录,其中class_index
是类别索引,x_center
和y_center
是边界框中心点的x和y坐标,width
和height
是边界框的宽度和高度。
在YOLO的训练过程中,这样的配置文件允许用户轻松地指定数据集的位置和类别信息,从而无需硬编码在训练脚本中。具体来说,这段配置的含义如下:
path
: 指定了数据集的根目录路径,即所有数据子文件夹的上级目录。这里的路径是相对于当前配置文件的路径或者相对于执行训练脚本的工作目录。train
: 定义了训练集图像的相对路径。在训练模型时,程序会在指定的路径下查找图像文件。val
: 定义了验证集图像的相对路径。验证集用于在训练过程中评估模型性能,避免过拟合。nc
: 表示类别的数量,这里设置为2,意味着数据集中有两类物体需要被识别。names
: 是一个列表,包含了每个类别的名称。这里有两个类别,名称分别是"0"和"1"。这些名称在训练和测试过程中用于引用特定的类别。
# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: ../dataset/ # dataset root dir
train: images/train/ # train images (relative to 'path') 128 images
val: images/val/ # train images (relative to 'path') 128 images
# Classes
nc: 2 # number of classes
names: ["0", '1'] # class names
YOLO 训练日志
在使用YOLO进行训练时,生成的
exp/detect/train
类型的文件夹是训练过程中的一个关键组成部分。
- 模型权重 (
.pt
或.pth
文件): 训练过程中保存的模型权重,可以用于后续的测试或继续训练。 - 日志文件 (
.log
文件): 包含训练过程中的所有输出信息,如损失值、精度、速度等。 - 配置文件 (
.yaml
或.cfg
文件): 训练时使用的配置文件副本,记录了数据路径、类别名、模型架构等设置。 - 图表和可视化: 有时YOLO会生成训练过程中的性能图表,如损失曲线、精度曲线等。
- 测试结果: 如果训练过程中包括了测试阶段,可能会有测试结果的保存,如检测结果的图片或统计数据。
- F1_curve.png, PR_curve.png, P_curve.png, R_curve.png: 包含模型性能的不同评估指标曲线图,如F1分数(
F1_curve.png
)、精确率-召回率曲线(PR_curve.png
)、精确率(P_curve.png
)和召回率(R_curve.png
)。 - results.csv: 一个CSV文件,包含模型训练或测试的结果数据。
- results.png: 包含训练结果的汇总图表或图像。
- train_batch***.jpg**: 包含训练过程中不同批次的图像和它们的标注。
- val_batch0_labels.jpg, val_batch0_pred.jpg: 验证集批次的图像,可能包含真实标签(
labels
)和模型预测(pred
)的可视化。 - weights/: 一个目录,通常包含模型训练过程中保存的权重文件,如
.pt
或.pth
文件。
在训练过程中和训练完成后,都可以查看训练日志。可以优先查看results.png,图像的内容类似如下。从验证集上的损失 (
val/box_loss
,
val/cls_loss
,
val/dfl_loss
) 和性能指标可以评估模型在未见数据上的泛化能力。在下面的训练日志中,我们发现模型在验证集发生了过拟合。
缩写作用描述epoch表示模型在整个训练数据集上进行了一次前向和后向传播的完整周期。train/box_loss衡量模型预测的边界框与真实边界框之间差异的损失值。train/cls_loss衡量模型预测的类别与真实类别之间差异的损失值。train/dfl_loss衡量模型对难分类样本的关注程度,减少易分类样本的影响。metrics/precision(B)在训练过程中,预测为正类别中实际为正类别的比例。metrics/recall(B)在训练过程中,所有实际正类别中被模型正确预测为正类别的比例。metrics/mAP50(B)在50%的IoU阈值下计算,衡量模型的整体性能。metrics/mAP50-95(B)在0.5到0.95的IoU阈值范围内计算,提供更全面的模型性能评估。val/box_loss模型在未见过的验证集上的边界框损失,用于监控模型的泛化能力。val/cls_loss模型在验证集上的分类损失,用于监控模型的泛化能力。val/dfl_loss模型在验证集上的难易样本平衡损失。
YOLO分割原理
https://github.com/ultralytics/ultralytics/blob/main/ultralytics/utils/loss.py#L264
YOLO分割模型模型在 YOLOv8 的基础上,针对实例分割问题,定义了一个包含多部分的损失函数,其中包括:
- 边界框损失(box loss):用于计算预测的边界框和真实边界框之间的差异。
- 分类损失(class loss):用于计算预测的分类分数与真实类别之间的差异。
- 分割损失(segmentation loss):用于计算实例掩码(masks)之间的差异。
- 距离分布损失(distribution focal loss, DFL):用于增强预测边界框的精确性。
在前向传播中,该模型会接受网络的预测输出
preds
以及一个批次的真实标签
batch
:
preds
通常包括三个部分:feats
(特征图)、pred_masks
(预测掩码系数)、proto
(原型掩码)。- 特征图
feats
包含用于解码边界框和分类标签的特征;pred_masks
和proto
共同用于生成预测掩码。
在处理实例掩码时,模型考虑了是否存在掩码重叠的情况:
- 无重叠时,每个目标的掩码是单独的,直接与预测的掩码进行匹配。
- 存在重叠时,掩码值表示不同目标的索引,模型会处理多个目标之间的重叠关系。
YOLO结果分析
yolov8模型训练结果分析以及如何评估yolov8模型训练的效果_yolov8训练结果分析-CSDN博客
Baseline 进阶思路
如果想要在原有代码上提高模型思路,可以有如下操作:
1、使用所有的数据集训练模型,从比赛页面下载所有的图片。
全球AI攻防挑战赛—赛道二:AI核身之金融场景凭证篡改检测_算法大赛_赛题与数据_天池大赛-阿里云天池的赛题与数据 (aliyun.com)
2、切换不同的模型预训练权重。
BASELINE讲解:
在jupyter nootbook中打开
复制下列命令,回车执行:
git lfs install
git clone https://www.modelscope.cn/datasets/Datawhale/dw_AI_defense_track2.git
步骤一:读取数据集
!apt update > /dev/null; apt install aria2 git-lfs axel -y > /dev/null
!pip install ultralytics==8.2.0 numpy pandas opencv-python Pillow matplotlib > /dev/null
!axel -n 12 -a http://mirror.coggle.club/seg_risky_testing_data.zip; unzip -q seg_risky_testing_data.zip
!axel -n 12 -a http://mirror.coggle.club/seg_risky_training_data_00.zip; unzip -q seg_risky_training_data_00.zip
!apt update > /dev/null
: 更新软件包列表,但将输出重定向到/dev/null
,因此不会显示在屏幕上。apt install aria2 git-lfs axel -y > /dev/null
: 安装aria2
、git-lfs
和axel
软件包,并自动确认安装(-y
),输出同样被重定向到/dev/null
。!pip install ultralytics==8.2.0 numpy pandas opencv-python Pillow matplotlib > /dev/null
: 使用pip
安装 Python 包ultralytics
、numpy
、pandas
、opencv-python
、Pillow
和matplotlib
,指定ultralytics
版本为 8.2.0,输出重定向到/dev/null
。!axel -n 12 -a http://mirror.coggle.club/seg_risky_testing_data.zip
: 使用axel
下载seg_risky_testing_data.zip
文件,使用 12 个连接以加快下载速度。unzip -q seg_risky_testing_data.zip
: 解压下载的seg_risky_testing_data.zip
文件,-q
选项用于静默模式,不显示解压过程。!axel -n 12 -a http://mirror.coggle.club/seg_risky_training_data_00.zip
: 同样使用axel
下载seg_risky_training_data_00.zip
文件。unzip -q seg_risky_training_data_00.zip
: 解压下载的seg_risky_training_data_00.zip
文件,同样使用静默模式。
总体来说,这段代码的目的是安装必要的软件和 Python 包,然后下载并解压数据集文件。
import os, shutil
import cv2
import glob
import json
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
training_anno = pd.read_csv('http://mirror.coggle.club/seg_risky_training_anno.csv')
train_jpgs = [x.replace('./', '') for x in glob.glob('./0/*.jpg')]
training_anno = training_anno[training_anno['Path'].isin(train_jpgs)]
training_anno['Polygons'] = training_anno['Polygons'].apply(json.loads)
training_anno.head()
- 导入库:-
os
,shutil
: 用于文件和目录操作。-cv2
: OpenCV库,用于图像处理。-glob
: 用于文件路径模式匹配。-json
: 用于处理 JSON 格式的数据。-pandas as pd
: 用于数据分析和操作。-numpy as np
: 用于数值计算。-matplotlib.pyplot as plt
: 用于数据可视化。 - 读取 CSV 文件:-
training_anno = pd.read_csv('http://mirror.coggle.club/seg_risky_training_anno.csv')
: 从给定的 URL 读取 CSV 文件到一个 Pandas DataFrame 中,包含训练数据的注释信息。 - 获取图像文件列表:-
train_jpgs = [x.replace('./', '') for x in glob.glob('./0/*.jpg')]
: 使用glob
查找当前目录下的0
文件夹中的所有.jpg
文件,并去掉路径中的./
前缀。 - 过滤注释数据:-
training_anno = training_anno[training_anno['Path'].isin(train_jpgs)]
: 过滤training_anno
DataFrame,仅保留路径在train_jpgs
列表中的记录。 - 解析多边形数据:-
training_anno['Polygons'] = training_anno['Polygons'].apply(json.loads)
: 将Polygons
列中的 JSON 字符串解析为 Python 对象。 - 显示数据:-
training_anno.head()
: 显示 DataFrame 的前几行,帮助检查数据是否正确加载和处理。
总体来说,这段代码的目的是读取图像注释数据,并确保这些注释与实际存在的图像文件相匹配,然后解析多边形注释信息,以便后续进行图像处理或分析。
training_anno.shape
training_anno.shape
返回一个元组,表示
training_anno
DataFrame 的维度。具体来说,它包含两部分:
- 第一个值是行数,表示有多少条记录。
- 第二个值是列数,表示有多少个字段或特征。
这一步用于快速了解数据集的大小和结构。
np.array(training_anno['Polygons'].iloc[4], dtype=np.int32)
这行代码将
training_anno
DataFrame 中第五个(索引为 4)记录的
Polygons
列转换为一个 NumPy 数组。具体步骤如下:
training_anno['Polygons'].iloc[4]
: 获取Polygons
列中索引为 4 的元素。这是一个解析后的 Python 对象(通常是列表),表示多边形的坐标。np.array(..., dtype=np.int32)
: 将该对象转换为一个 NumPy 数组,并指定数据类型为int32
,确保坐标是整数格式。
这一步通常用于准备数据以便在图像处理或计算中使用。
idx = 23
img = cv2.imread(training_anno['Path'].iloc[idx])
plt.figure(figsize=(12, 6))
plt.subplot(121)
plt.imshow(img)
plt.title("Original Image")
plt.axis('off')
plt.subplot(122)
img = cv2.imread(training_anno['Path'].iloc[idx])
polygon_coords = np.array(training_anno['Polygons'].iloc[idx], dtype=np.int32)
for polygon_coord in polygon_coords:
cv2.polylines(img, np.expand_dims(polygon_coord, 0), isClosed=True, color=(0, 255, 0), thickness=2)
img= cv2.fillPoly(img, np.expand_dims(polygon_coord, 0), color=(255, 0, 0, 0.5))
plt.imshow(img)
plt.title("Image with Polygons")
plt.axis('off')
- 读取图像:-
idx = 23
: 选择要处理的图像索引。-img = cv2.imread(training_anno['Path'].iloc[idx])
: 使用 OpenCV 读取图像文件。 - 显示原始图像:-
plt.figure(figsize=(12, 6))
: 创建一个大小为 12x6 的图形。-plt.subplot(121)
: 创建第一个子图。-plt.imshow(img)
: 显示原始图像。-plt.title("Original Image")
: 添加标题。-plt.axis('off')
: 隐藏坐标轴。 - 绘制多边形:-
plt.subplot(122)
: 创建第二个子图。-img = cv2.imread(training_anno['Path'].iloc[idx])
: 再次读取图像,确保是未修改的原始图像。-polygon_coords = np.array(training_anno['Polygons'].iloc[idx], dtype=np.int32)
: 获取并转换多边形坐标。 - 在图像上绘制和填充多边形:-
for polygon_coord in polygon_coords
: 遍历每个多边形坐标。-cv2.polylines(img, np.expand_dims(polygon_coord, 0), isClosed=True, color=(0, 255, 0), thickness=2)
: 绘制多边形边框,绿色,厚度为 2。-img = cv2.fillPoly(img, np.expand_dims(polygon_coord, 0), color=(255, 0, 0, 0.5))
: 填充多边形,红色。 - 显示带多边形的图像:-
plt.imshow(img)
: 显示处理后的图像。-plt.title("Image with Polygons")
: 添加标题。-plt.axis('off')
: 隐藏坐标轴。
这段代码的目的是将图像与其对应的多边形注释可视化。
步骤二:构建YOLO数据集
training_anno.info()
training_anno.info()
用于显示 DataFrame 的概况信息,包括:
- 索引范围:显示行数。
- 列信息:列名、数据类型、非空值数量。
- 内存使用情况:显示 DataFrame 占用的内存大小。
这有助于了解数据集的结构和内容,便于后续处理。
if os.path.exists('yolo_seg_dataset'):
shutil.rmtree('yolo_seg_dataset')
os.makedirs('yolo_seg_dataset/train')
os.makedirs('yolo_seg_dataset/valid')
这段代码用于准备 YOLO 数据集的目录结构:
- 检查并删除现有目录:-
if os.path.exists('yolo_seg_dataset')
: 检查yolo_seg_dataset
目录是否存在。-shutil.rmtree('yolo_seg_dataset')
: 如果存在,删除整个目录及其内容。 - 创建目录结构:-
os.makedirs('yolo_seg_dataset/train')
: 创建用于存放训练数据的目录。-os.makedirs('yolo_seg_dataset/valid')
: 创建用于存放验证数据的目录。
这确保了数据集目录是干净的,并为存放数据做好准备。
def normalize_polygon(polygon, img_width, img_height):
return [(x / img_width, y / img_height) for x, y in polygon]
for row in training_anno.iloc[:10000].iterrows():
shutil.copy(row[1].Path, 'yolo_seg_dataset/train')
img = cv2.imread(row[1].Path)
img_height, img_width = img.shape[:2]
txt_filename = os.path.join('yolo_seg_dataset/train/' + row[1].Path.split('/')[-1][:-4] + '.txt')
with open(txt_filename, 'w') as up:
for polygon in row[1].Polygons:
normalized_polygon = normalize_polygon(polygon, img_width, img_height)
normalized_coords = ' '.join([f'{coord[0]:.3f} {coord[1]:.3f}' for coord in normalized_polygon])
up.write(f'0 {normalized_coords}\n')
这段代码用于将数据准备为 YOLO 格式的标注文件。以下是详细步骤:
- 定义函数:-
normalize_polygon(polygon, img_width, img_height)
: 将多边形坐标归一化到图像的宽度和高度范围内。 - 遍历数据集:-
for row in training_anno.iloc[:10000].iterrows()
: 遍历前 10,000 条记录。 - 复制图像:-
shutil.copy(row[1].Path, 'yolo_seg_dataset/train')
: 将图像复制到训练目录。 - 读取图像尺寸:-
img = cv2.imread(row[1].Path)
: 读取图像。-img_height, img_width = img.shape[:2]
: 获取图像的高度和宽度。 - 创建标注文件:-
txt_filename = os.path.join('yolo_seg_dataset/train/' + row[1].Path.split('/')[-1][:-4] + '.txt')
: 创建与图像对应的标注文件路径。 - 写入标注数据:-
with open(txt_filename, 'w') as up
: 打开标注文件进行写入。-for polygon in row[1].Polygons
: 遍历每个多边形。-normalized_polygon = normalize_polygon(polygon, img_width, img_height)
: 归一化多边形坐标。-normalized_coords = ' '.join([f'{coord[0]:.3f} {coord[1]:.3f}' for coord in normalized_polygon])
: 格式化归一化坐标。-up.write(f'0 {normalized_coords}\n')
: 写入标注文件,0
表示类别标签。
这段代码的目的是将图像和其对应的多边形标注转换为 YOLO 格式,便于训练目标检测模型。
for row in training_anno.iloc[10000:10150].iterrows():
shutil.copy(row[1].Path, 'yolo_seg_dataset/valid')
img = cv2.imread(row[1].Path)
img_height, img_width = img.shape[:2]
txt_filename = os.path.join('yolo_seg_dataset/valid/' + row[1].Path.split('/')[-1][:-4] + '.txt')
with open(txt_filename, 'w') as up:
for polygon in row[1].Polygons:
normalized_polygon = normalize_polygon(polygon, img_width, img_height)
normalized_coords = ' '.join([f'{coord[0]:.3f} {coord[1]:.3f}' for coord in normalized_polygon])
up.write(f'0 {normalized_coords}\n')
这段代码将数据集的一部分准备为 YOLO 格式的验证集。具体步骤如下:
- 遍历验证集数据:-
for row in training_anno.iloc[10000:10150].iterrows()
: 遍历第 10,000 到 10,149 条记录。 - 复制图像到验证目录:-
shutil.copy(row[1].Path, 'yolo_seg_dataset/valid')
: 将图像复制到验证目录。 - 读取图像尺寸:-
img = cv2.imread(row[1].Path)
: 读取图像。-img_height, img_width = img.shape[:2]
: 获取图像的高度和宽度。 - 创建标注文件:-
txt_filename = os.path.join('yolo_seg_dataset/valid/' + row[1].Path.split('/')[-1][:-4] + '.txt')
: 创建与图像对应的标注文件路径。 - 写入标注数据:-
with open(txt_filename, 'w') as up
: 打开标注文件进行写入。-for polygon in row[1].Polygons
: 遍历每个多边形。-normalized_polygon = normalize_polygon(polygon, img_width, img_height)
: 归一化多边形坐标。-normalized_coords = ' '.join([f'{coord[0]:.3f} {coord[1]:.3f}' for coord in normalized_polygon])
: 格式化归一化坐标。-up.write(f'0 {normalized_coords}\n')
: 写入标注文件,0
表示类别标签。
这段代码用于将指定范围内的图像及其标注转换为 YOLO 格式,以便在验证集上进行模型评估。
with open('yolo_seg_dataset/data.yaml', 'w') as up:
data_root = os.path.abspath('yolo_seg_dataset/')
up.write(f'''
path: {data_root}
train: train
val: valid
names:
0: alter
''')
这段代码创建了一个配置文件
data.yaml
,用于 YOLO 模型训练。具体内容如下:
- 打开文件:-
with open('yolo_seg_dataset/data.yaml', 'w') as up
: 打开或创建data.yaml
文件用于写入。 - 写入配置内容:-
data_root = os.path.abspath('yolo_seg_dataset/')
: 获取数据集目录的绝对路径。-up.write(f'''...''')
: 写入多行字符串。
内容包括:
path
: 数据集的根目录。train
: 训练数据所在的子目录。val
: 验证数据所在的子目录。names
: 类别名称映射,0: alter
表示类别 0 的名称。
这个配置文件用于指定数据集路径和类别信息,方便 YOLO 训练脚本使用。
!mkdir -p /root/.config/Ultralytics/
!wget http://mirror.coggle.club/yolo/Arial.ttf -O /root/.config/Ultralytics/Arial.ttf
!wget http://mirror.coggle.club/yolo/yolov8n-v8.2.0.pt -O yolov8n.pt
!wget http://mirror.coggle.club/yolo/yolov8n-seg-v8.2.0.pt -O yolov8n-seg.pt
- 创建配置目录:-
!mkdir -p /root/.config/Ultralytics/
: 创建 Ultralytics 配置目录。 - 下载字体文件:-
!wget http://mirror.coggle.club/yolo/Arial.ttf -O /root/.config/Ultralytics/Arial.ttf
: 下载Arial.ttf
字体文件到配置目录。 - 下载模型权重:-
!wget http://mirror.coggle.club/yolo/yolov8n-v8.2.0.pt -O yolov8n.pt
: 下载 YOLOv8n 模型权重。-!wget http://mirror.coggle.club/yolo/yolov8n-seg-v8.2.0.pt -O yolov8n-seg.pt
: 下载 YOLOv8n 分割模型权重。
这些文件用于配置和初始化 YOLO 模型的训练和推理过程。
步骤三:训练模型
from ultralytics import YOLO
model = YOLO("./yolov8n-seg.pt")
results = model.train(data="./yolo_seg_dataset/data.yaml", epochs=10, imgsz=640)
这段代码用于训练 YOLO 模型。以下是具体步骤:
- 导入 YOLO:-
from ultralytics import YOLO
: 从 Ultralytics 库中导入 YOLO 类。 - 加载模型:-
model = YOLO("./yolov8n-seg.pt")
: 加载预训练的 YOLOv8n 分割模型权重。 - 训练模型:-
results = model.train(data="./yolo_seg_dataset/data.yaml", epochs=10, imgsz=640)
: - 使用指定的数据集配置文件data.yaml
进行训练。- 训练 10 个周期(epochs)。- 图像大小设为 640。
这会启动模型的训练过程,使用提供的数据集和配置。
步骤四:预测测试集
from ultralytics import YOLO
import glob
from tqdm import tqdm
model = YOLO("./runs/segment/train/weights/best.pt")
test_imgs = glob.glob('./test_set_A_rename/*/*')
这段代码用于加载训练好的 YOLO 模型并准备测试图像。以下是具体步骤:
- 导入必要的库:-
from ultralytics import YOLO
: 导入 YOLO 类。-import glob
: 导入 glob 模块,用于文件路径匹配。-from tqdm import tqdm
: 导入 tqdm,用于显示进度条。 - 加载模型:-
model = YOLO("./runs/segment/train/weights/best.pt")
: 加载训练好的 YOLO 模型权重。 - 获取测试图像列表:-
test_imgs = glob.glob('./test_set_A_rename/*/*')
: 获取测试集中的所有图像路径。
这为后续的模型推理准备了测试图像。
Polygon = []
for path in tqdm(test_imgs[:10000]):
results = model(path, verbose=False)
result = results[0]
if result.masks is None:
Polygon.append([])
else:
Polygon.append([mask.astype(int).tolist() for mask in result.masks.xy])
这段代码用于对测试图像进行推理,并提取多边形掩码。以下是具体步骤:
- 初始化列表:-
Polygon = []
: 创建一个空列表,用于存储多边形数据。 - 遍历测试图像:-
for path in tqdm(test_imgs[:10000])
: 遍历前 10,000 张测试图像,使用tqdm
显示进度条。 - 模型推理:-
results = model(path, verbose=False)
: 使用模型对图像进行推理,verbose=False
禁用详细输出。-result = results[0]
: 获取推理结果。 - 处理掩码:-
if result.masks is None
: 检查是否有掩码。 -Polygon.append([])
: 如果没有掩码,添加一个空列表。-else
: 如果有掩码: -Polygon.append([mask.astype(int).tolist() for mask in result.masks.xy])
: 将每个掩码的坐标转换为整数并添加到列表中。
这段代码提取了每张测试图像的多边形掩码数据,便于进一步分析或保存。
import pandas as pd
submit = pd.DataFrame({
'Path': [x.split('/')[-1] for x in test_imgs[:10000]],
'Polygon': Polygon
})
这段代码用于创建一个 DataFrame,用于提交预测结果。具体步骤如下:
- 导入 Pandas:-
import pandas as pd
: 导入 Pandas 库,用于数据处理。 - 创建 DataFrame:-
submit = pd.DataFrame(...)
: 创建一个 DataFrame,包含以下两列: -'Path'
: 提取前 10,000 张测试图像的文件名。-'Polygon'
: 存储对应的多边形数据。
这样可以方便地保存或导出预测结果。
submit = pd.merge(submit, pd.DataFrame({'Path': [x.split('/')[-1] for x in test_imgs[:]]}), on='Path', how='right')
这段代码用于合并两个 DataFrame,以确保所有测试图像都有记录。具体步骤如下:
- 创建完整路径 DataFrame:-
pd.DataFrame({'Path': [x.split('/')[-1] for x in test_imgs[:]})
: 创建一个 DataFrame,包含所有测试图像的文件名。 - 合并 DataFrame:-
submit = pd.merge(...)
: 将submit
与包含所有文件名的 DataFrame 合并。-on='Path'
: 以'Path'
列为键进行合并。-how='right'
: 使用右连接,确保所有测试图像都在结果中。
这样可以确保即使某些图像没有预测结果,它们也会在最终的 DataFrame 中出现。
submit = submit.fillna('[]')
这段代码用于填充缺失值:
submit = submit.fillna('[]')
: 将 DataFrame 中的缺失值替换为'[]'
,表示没有多边形数据的图像。
这样可以确保所有行都有有效的值,便于后续处理或保存。
submit.to_csv('track2_submit.csv', index=None)
这段代码将 DataFrame 导出为 CSV 文件:
submit.to_csv('track2_submit.csv', index=None)
: 将submit
DataFrame 保存为track2_submit.csv
文件,不包括索引。
这样可以方便地提交或共享预测结果。
赛题进阶思路
上分点一:数据集增强
数据增强是机器学习和深度学习中常用的技术,用于通过从现有数据集中生成新的训练样本来提高模型的泛化能力。干净一致的数据对于创建性能良好的模型至关重要。常见的增强技术包括翻转、旋转、缩放和颜色调整。多个库,例如 Albumentations、Imgaug 和 TensorFlow的 ImageDataGenerator,可以生成这些增强。
数据增强方法描述Mosaic Augmentation将四张训练图像组合成一张,增加物体尺度和位置的多样性。Copy-Paste Augmentation复制一个图像的随机区域并粘贴到另一个图像上,生成新的训练样本。Random Affine Transformations包括图像的随机旋转、缩放、平移和剪切,增加对几何变换的鲁棒性。MixUp Augmentation通过线性组合两张图像及其标签创造合成图像,增加特征空间的泛化。Albumentations一个支持多种增强技术的图像增强库,提供灵活的增强管道定义。HSV Augmentation对图像的色相、饱和度和亮度进行随机变化,改变颜色属性。Random Horizontal Flip沿水平轴随机翻转图像,增加对镜像变化的不变性。
如下图所示,是一个数据集增强的效果示例,针对原有数据集进行了翻转、随机拼贴、剪切等处理:
参数名类型默认值取值范围描述hsv_hfloat0.0150.0 - 1.0调整图像色调,引入颜色变异性,提高不同光照下的泛化能力。hsv_sfloat0.70.0 - 1.0调整图像饱和度,改变颜色强度,模拟不同环境条件。hsv_vfloat0.40.0 - 1.0调整图像亮度,帮助模型在不同光照下表现良好。degreesfloat0-180 - +180随机旋转图像,提高识别不同方向物体的能力。translatefloat0.10.0 - 1.0平移图像,帮助模型学习检测部分可见物体。scalefloat0.5>=0.0缩放图像,模拟物体与相机之间的不同距离。shearfloat0-180 - +180剪切图像,模拟从不同角度观察物体的效果。perspectivefloat00.0 - 0.001应用随机透视变换,增强模型对3D空间物体的理解能力。flipudfloat00.0 - 1.0上下翻转图像,增加数据变异性,不影响物体特征。fliplrfloat0.50.0 - 1.0左右翻转图像,有助于学习对称物体和增加数据集多样性。bgrfloat00.0 - 1.0翻转图像通道从RGB到BGR,提高对通道顺序错误的鲁棒性。mosaicfloat10.0 - 1.0合成四张图像,模拟不同场景组合和物体交互,增强复杂场景理解。mixupfloat00.0 - 1.0混合两张图像及标签,创建合成图像,增强泛化能力。copy_pastefloat00.0 - 1.0复制物体并粘贴到另一图像,增加实例和学习遮挡。auto_augmentstrrandaugment-自动应用预定义增强策略,优化分类任务。erasingfloat0.40.0 - 0.9随机擦除图像部分,鼓励模型关注不明显特征。
上分点二:设置 YOLO 模型训练参数
YOLO 模型的训练设置包括多种超参数和配置,这些设置会影响模型的性能、速度和准确性。微调涉及采用预先训练的模型并调整其参数以提高特定任务或数据集的性能。该过程也称为模型再训练,使模型能够更好地理解和预测在实际应用中将遇到的特定数据的结果。您可以根据模型评估重新训练模型,以获得最佳结果。
通常,在初始训练时期,学习率从低开始,逐渐增加以稳定训练过程。但是,由于您的模型已经从以前的数据集中学习了一些特征,因此立即从更高的学习率开始可能更有益。在 YOLO 中绝大部分参数都可以使用默认值。
- imgsz: 训练时的目标图像尺寸,所有图像在此尺寸下缩放。
- save_period: 保存模型检查点的频率(周期数),-1 表示禁用。
- device: 用于训练的计算设备,可以是单个或多个 GPU,CPU 或苹果硅的 MPS。
- optimizer: 训练中使用的优化器,如 SGD、Adam 等,或 'auto' 以根据模型配置自动选择。
- momentum: SGD 的动量因子或 Adam 优化器的 beta1。
- weight_decay: L2 正则化项。
- warmup_epochs: 学习率预热的周期数。
- warmup_momentum: 预热阶段的初始动量。
- warmup_bias_lr: 预热阶段偏置参数的学习率。
- box: 边界框损失在损失函数中的权重。
- cls: 分类损失在总损失函数中的权重。
- dfl: 分布焦点损失的权重。
在YOLOv5及其后续版本中,
imgsz
可以被设置为一个整数,用于训练和验证模式,表示将输入图像调整为正方形的尺寸,例如
imgsz=640
意味着图像将被调整为640x640像素。对于预测和导出模式,
imgsz
可以被设置为一个列表,包含宽度和高度,例如
imgsz=[640, 480]
,表示图像将被调整为640像素宽和480像素高。较大的图像尺寸可能会提高模型的准确性,但会增加计算量和内存消耗。较小的图像尺寸可能会降低模型的准确性,但会提高计算速度和内存效率。因此,用户应根据实际场景需求及硬件资源限制,设置合适的输入图像尺寸
上分点三:设置 YOLO 模型预测行为和性能
提高速度
YOLO模型的预测结果通常包括多个组成部分,每个部分提供关于检测到的对象的不同信息。同时 YOLO 能够处理包括单独图像、图像集合、视频文件或实时视频流在内的多种数据源,也能够一次性处理多个图像或视频帧,进一步提高推理速度。
属性描述cls类别概率,表示当前预测结果属于类别0的概率为0。conf置信度,模型对其预测结果的置信度,接近92%。data包含边界框坐标和置信度以及类别概率的原始数据。id没有分配唯一的对象ID。is_track预测结果不是来自跟踪的对象。orig_shape输入图像的原始尺寸,这里是500x500像素。shape预测结果张量的形状,表示一个边界框的六个值。xywh归一化的边界框坐标,中心坐标和宽高。xywhn归一化的边界框坐标(无偏移)。xyxy原始边界框坐标,左上角和右下角坐标。xyxyn归一化的原始边界框坐标。
from ultralytics import YOLO
# 加载模型
model = YOLO("yolov8n.pt") # 预训练的 YOLOv8n 模型
# 对图像列表运行批量推理
results = model(["im1.jpg", "im2.jpg"]) # 返回结果对象的列表
# 处理结果列表
for result in results:
boxes = result.boxes # 边界框输出
masks = result.masks # 分割掩码输出
keypoints = result.keypoints # 姿态关键点输出
probs = result.probs # 分类概率输出
obb = result.obb # 定向边界框输出
result.show() # 显示结果
result.save(filename="result.jpg") # 保存结果到磁盘
YOLOv8模型的使用者提供了灵活性,允许根据特定应用场景的需求调整模型的行为和性能。例如,如果需要减少误报,可以提高
conf
阈值;如果需要提高模型的执行速度,可以在支持的硬件上使用
half
精度;如果需要处理视频数据并希望加快处理速度,可以调整
vid_stride
来跳过某些帧。这些参数的适当配置对于优化模型的预测性能至关重要。
参数名类型默认值描述conffloat0.25置信度阈值,用于设置检测对象的最小置信度。低于此阈值的检测对象将被忽略。调整此值有助于减少误报。ioufloat0.7非最大值抑制(NMS)的交并比(IoU)阈值。较低的值通过消除重叠的边界框来减少检测数量,有助于减少重复项。imgszint 或 tuple640推理时定义图像的大小。可以是单个整数(如640),用于将图像大小调整为正方形,或(height, width)元组。合适的尺寸可以提高检测精度和处理速度。augmentboolFALSE启用预测时的数据增强(TTA),可能通过牺牲推理速度来提高检测的鲁棒性。
版权归原作者 TheDan 所有, 如有侵权,请联系我们删除。