如有错误,恳请指出。
以下内容是学习了参考资料作的笔记,仅供参考,详细内容见参考资料。这里我主要是对yolov4和v5的模型结构记录,及其了解其正负样本匹配的方式。
另外的就是介绍一下Albumentations工具包,这是专门用于计算机视觉中数据增强的一个工具包,提高的数据增强方式比较多,使用也比较方便。
yolov4的结构图:
对于yolov4,之前已经看个了paper总结了一篇笔记,这里就跳过大体部分,之前的笔记见:目标检测算法——YOLOv4。
详细补充一下其消除网格信息(Eliminate grid sensitivity)的做法:
问题:当真实目标中心点非常靠近网格的左上角点(σ(tx)和σ(ty)应该趋近与0 或者右下角点(σ(tx))和σ(ty)应该趋近与1)时,网络的预测值需要负无穷或者正无穷时才能取到,而这种很极端的值网络一般无法达到。
对于具体的改变来说,作者是增加了一个缩放系数与偏移量,从而可以比较容易的接近0-1点,不需要无穷值才可以接近,具体公式为:
通过引入这个系数,网络的预测值能够很容易达到0或者1;一般讲scalexy设置为2,所以公式为:
这样,通过引入1缩放系数scale之后,x在同样的区间内,y的取值范围更大,偏移的范围由原来的(0, 1)调整到了(-0.5, 1.5)
在YOLOv3中针对每一个GT都只分配了一个Anchor。但在YOLOv4包括之前讲过的YOLOv3 SPP以及YOLOv5中一个GT可以同时分配给多个Anchor,它们是直接使用Anchor模板与GT Boxes进行粗略匹配,然后在定位到对应cell的对应Anchor。
Eliminate grid sensitivity同v4的做法,这里再记录一下yolov5的训练策略与其用到的一些数据增强:
ps:这里推荐一个数据增强的工具包:Albumentations 。
其涵盖了绝大部分的数据增强方式,如下:
简单的使用例子:
# 使用 Albumentations 为训练和验证数据集定义转换函数
class CatsVsDogsDataset(Dataset):
def __init__(self, images_filepaths, transform=None):
self.images_filepaths = images_filepaths
self.transform = transform
def __len__(self):
return len(self.images_filepaths)
def __getitem__(self, idx):
image_filepath = self.images_filepaths[idx]
image = cv2.imread(image_filepath)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
if os.path.normpath(image_filepath).split(os.sep)[-2] == "Cat":
label = 1.0
else:
label = 0.0
if self.transform is not None:
image = self.transform(image=image)["image"]
return image, label
train_transform = A.Compose(
[
A.SmallestMaxSize(max_size=160),
A.ShiftScaleRotate(shift_limit=0.05, scale_limit=0.05, rotate_limit=15, p=0.5),
A.RandomCrop(height=128, width=128),
A.RGBShift(r_shift_limit=15, g_shift_limit=15, b_shift_limit=15, p=0.5),
A.RandomBrightnessContrast(p=0.5),
A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),
ToTensorV2(),
]
)
train_dataset = CatsVsDogsDataset(images_filepaths=train_images_filepaths, transform=train_transform)
val_transform = A.Compose(
[
A.SmallestMaxSize(max_size=160),
A.CenterCrop(height=128, width=128),
A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),
ToTensorV2(),
]
)
val_dataset = CatsVsDogsDataset(images_filepaths=val_images_filepaths, transform=val_transform)
可以看见,使用方法类似于pytorch的transform。这里作一个简单的对比,下面的代码是之前自定义宝可梦数据集的例子,见博文:自定义宝可梦数据集
# 对图像进行预处理
transform = transforms.Compose([
# 转换为RGB图像
lambda x: Image.open(x).convert('RGB'),
# 重新确定尺寸
transforms.Resize((int(self.resize * 1.25), int(self.resize * 1.25))),
# 旋转角度
transforms.RandomRotation(15),
# 中心裁剪
transforms.CenterCrop(self.resize),
# 转换为Tensor格式
transforms.ToTensor(),
# 使数据分布在0附近
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
image = transform(image)
所以,使用的方法是类似的。不过,在Albumentations提供的数据增强方式比pytorch官方的更多,使用也比较方便。
这样同样类似于v4的做法,但是主要的区别在于GT Box与Anchor Templates模板的匹配方式。在YOLOv4中是直接将每个GT Box与对应的Anchor Templates模板计算IoU,只要IoU大于设定的阈值就算匹配成功。但在YOLOv5中,作者先去计算每个GT Box与对应的Anchor Templates模板的高宽比例;然后统计这些比例和它们倒数之间的最大值,这里可以理解成计算GT Box和Anchor Templates分别在宽度以及高度方向的最大差异(当相等的时候比例为1,差异最小);接着统计宽度方向与高度方向的最大差异之间的最大值(二值取最大),即宽度和高度方向差异最大的值:
GT Box和对应的Anchor Template的rmax小于阈值anchor_t(在源码中默认设置为4.0),即GT Box和对应的Anchor Template的高、宽比例相差不算太大,则将GT Box分配给该Anchor Template模板。为了方便大家理解,可以看下画的图。假设对某个GT Box而言,其实只要GT Box满足在某个Anchor Template宽和高的× 0.25 \times 0.25×0.25倍和× 4.0 \times 4.0×4.0倍之间就算匹配成功。
参考资料: