YOLOV4⽤到的⼀些tricks以及代码实现(1)——
CutMixandMosaicda。。。arch me
YOLOV4⽤掉的⼀些tricks以及代码实现(1)——CutMix and Mosaic data augmentation
之前的⼏篇博客将YOLOV4整个流程都过了⼀边,其中把重⼼放在相关的语法中,从这篇博客开始,我将YOLOV4中提到的⼀些tricks逐
⼀进⾏介绍并⽤代码实现。⾸先看下论⽂提到了哪些tricks:
Bag of Freebies(BoF) 指那些能够提⾼精度⽽不增加推断时间的技术。⽐如数据增⼴的⽅法图像⼏何变换、CutOut、grid mask等,⽹络正则化的⽅法DropOut、DropBlock等,类别不平衡的处理⽅法、难例挖掘⽅法、损失函数的设计等。
Bag of Specials (BoS)是指那些增加稍许推断代价,但可以提⾼模型精度的⽅法,⽐如增⼤模型感受野的SPP、ASPP、RFB等,引⼊注意⼒机制Squeeze-and-Excitation (SE) 、Spatial Attention Module (SAM)等 ,特征集成⽅法SFAM , ASFF , BiFPN等,改进的激活函数Swish、Mish等,或者是后处理⽅法如soft NMS、DIoU NMS等。
本篇博客主要介绍:CutMix and Mosaic data augmentation
⽰例代码利⽤opencv展⽰Mosaic data augmentation算法
carboncopy原理:
Yolov4的mosaic数据增强参考了CutMix数据增强⽅式,理论上具有⼀定的相似性!
CutMix数据增强⽅式利⽤两张图⽚进⾏拼接。
但是mosaic利⽤了四张图⽚这样在BN计算的时候⼀下⼦会计算四张图⽚的数据!
实现思路
1、每次读取四张图⽚。
2、分别对四张图⽚进⾏翻转、缩放、⾊域变化等,并且按照四个⽅向位置摆好。
3、进⾏图⽚的组合和框的组合。
通过查看实现思路,其实发现整体思路并不复杂,真正复杂的实在代码实现上,包括坐标转换,标签转换等。
本次⽰例中,利⽤opencv仅仅⽤于图像展⽰,算法原理与yoloV4中data augment ⼀模⼀样。
按照笔者⼀贯思路,逐⼀对代码进⾏分析后,解答上诉问题:
def get_datat(anno_dir, img_dir):
英语寓言小故事
⾸先通过datat获取标签数据和图像数据。
for anno_file in glob.glob(os.path.join(anno_dir, '*.txt'))
遍历anno_dir中的数据,这其中牵扯到glob语法。glob模块是最简单的模块之⼀,内容⾮常少。⽤它可以查找符合特定规则的⽂件路径名。跟使⽤windows下的⽂件搜索差不多。查找⽂件只⽤到三个匹配符:””, “?”, “[]”。””匹配0个或多个字符;”?”匹配单个字符;”[]”匹配指定范围内的字符,如:[0-9]匹配数字。
在这⾥就是查找以“txt"结尾的⽂件,返回的是⽂件路径。
xmin = max(obj[1], 0) / img_width
ymin = max(obj[2], 0) / img_height
xmax = min(obj[3], img_width) / img_width杭州前端培训
ymax = min(obj[4], img_height) / img_height
获取到标注信息的位置后进⾏归⼀化。
idxs = random.sample(range(len(annos)), 4)
random.sample()可以从指定的序列中,随机的截取指定长度的⽚断,不作原地修改。在这⾥⽤于随机选取图⽚。
def update_image_and_anno(all_img_list, all_annos, idxs, output_size, scale_range, filter_scale=0.)
该函数⽤于修改图像和标签,既实现mosaic数据增强。
scale_x = scale_range[0] + random.random() * (scale_range[1] - scale_range[0])
scale_y = scale_range[0] + random.random() * (scale_range[1] - scale_range[0])
divid_point_x = int(scale_x * output_size[1])
divid_point_y = int(scale_y * output_size[0])
利⽤random获取长和宽。注:⽣成的是0-1之间的浮点数。
for i, idx in enumerate(idxs)
根据之前产⽣的随机数获取数据,注:for遍历enumerate时,返回第⼀个值是index,第⼆个值是相对位置的数据。如:
手袋出格培训date = [2,4,6,8,10]
for index, item in enumerate(date):
print("index=%d ,item=%d" %(index,item))
for i in enumerate(date):
print(i)
#结果:
index=0 ,item=2
index=1 ,item=4
index=2 ,item=6
index=3 ,item=8
index=4 ,item=10
(0, 2)
(1, 4)
(2, 6)
(3, 8)
(4, 10)
遍历随机选择出来的四张图后,更改图像尺⼨:
img = cv2.imread(path)
if i == 0: # top-left
img = size(img, (divid_point_x, divid_point_y))
output_img[:divid_point_y, :divid_point_x, :] = img
for bbox in img_annos:
xmin = bbox[1] * scale_x
裙子的英文怎么说ymin = bbox[2] * scale_y
xmax = bbox[3] * scale_x
damnedymax = bbox[4] * scale_y
new_anno.append([bbox[0], xmin, ymin, xmax, ymax])
分别遍历四个⾓的图⽚并修改图像尺⼨和标签,步骤如下:
1.根据随机⽣成的divid_point_x,divid_point_y,将图像随机resize后,放⼊左上⾓的位置。
2.根据scale_x,scale_y修改标签的缩放⽐,注意:⼀张图⽚可能有多个标签,故这⾥⽤了for bbox in img_annos。
3.选取另⼀个位置,重复上两步。
new_anno = [anno for anno in new_anno if filter_scale < (anno[3] - anno[1]) and filter_scale < (anno[4] - anno[2])]
通过filter_scale设定阈值,去除修改后标签尺⼨过⼩的图⽚。
marmot
for anno in new_annos:
accpstart_point = (int(anno[1] * OUTPUT_SIZE[1]), int(anno[2] * OUTPUT_SIZE[0]))
end_point = (int(anno[3] * OUTPUT_SIZE[1]), int(anno[4] * OUTPUT_SIZE[0]))
cv2.imwrite('img/output_box.jpg', new_image)
最后利⽤opencv将⽅框画出来。
Mosaic数据增强⽅法借⽤opencv实现并不复杂,唯⼀需要注意的就是random的⽤法和filter_scale设定进⾏筛选,没什么特语法难度。地道口语