mosaic数据增强则利用了四张图片,对四张图片进行拼接,每一张图片都有其对应的框框,将四张图片拼接之后就获得一张新的图片,同时也获得这张图片对应的框框,然后我们将这样一张新的图片传入到神经网络当中去学习,相当于一下子传入四张图片进行学习了。论文中说这极大丰富了检测物体的背景!且在标准化BN计算的时候一下子会计算四张图片的数据!如下图所示:

 1、首先随机取四张图片

2、分别对四张图片进行数据增广操作,并分别粘贴至与最终输出图像大小相等掩模的对应位置。

操作包括:

1、翻转(对原始图片进行左右的翻转);

2、缩放(对原始图片进行大小的缩放);

3、色域变化(对原始图片的明亮度、饱和度、色调进行改变)等操作。

有两个比较关键的参数,最小偏移x, y。示例代码中设置为0.4,如:

# w = 800, h = 608
min_offset_x = 0.4
min_offset_y = 0.4
...# 计算图像等比例缩放比例
scale_low = 1 - min(min_offset_x, min_offset_y)  # 0.6
scale_high = scale_low + 0.2  # 0.8
scale = rand(scale_low, scale_high)
...#
place_x = [0, 0, int(w * min_offset_x), int(w * min_offset_x)]  # [0, 0, 320, 320]
place_y = [0, int(h * min_offset_y), int(w * min_offset_y), 0]  # [0, 243, 320, 0]

首先进行图像数据增强,图像缩放,之后通过它计算四个缩放、变换后图像图贴图的起始位置。分别为:[0,0], [0,243], [320,320], 320,0[]。超出范围的剪裁掉,对应的标注框进行范围的收缩,防止越界,如下图:

 3、进行图片的组合和框的组合

完成四张图片的摆放之后,我们利用矩阵的方式将四张图片它固定的区域截取下来,然后将它们拼接起来,拼接成一 张新的图片,新的图片上含有框框等一系列的内容。

拼图时,依据min_offset_x、min_offset_y生成cutx, cuty的拼图中心坐标。也就是我们事先设置好的随机的分割线。

cutx = np.random.randint(int(w * min_offset_x), int(w * (1 - min_offset_x)))
cuty = np.random.randint(int(h * min_offset_y), int(h * (1 - min_offset_y)))

对于最终拼图,按照拼图顺序后面覆盖前面图像,对应的区域被剪裁掉后,框坐标做对应处理。对于过小的目标,则丢弃掉。

测试代码:

#!/usr/bin/env python3
# coding: utf-8
import os
import cv2
import numpy as np
from PIL import Image, ImageDraw
from matplotlib.colors import rgb_to_hsv, hsv_to_rgbdef rand(a=0, b=1):return np.random.rand() * (b - a) + adef merge_bboxes(bboxes, cutx, cuty):merge_bbox = []for i in range(len(bboxes)):for box in bboxes[i]:tmp_box = []x1, y1, x2, y2 = box[0], box[1], box[2], box[3]if i == 0:if y1 > cuty or x1 > cutx:continueif y2 >= cuty and y1 <= cuty:y2 = cutyif y2 - y1 < 5:continueif x2 >= cutx and x1 <= cutx:x2 = cutxif x2 - x1 < 5:continueif i == 1:if y2 < cuty or x1 > cutx:continueif y2 >= cuty and y1 <= cuty:y1 = cutyif y2 - y1 < 5:continueif x2 >= cutx and x1 <= cutx:x2 = cutxif x2 - x1 < 5:continueif i == 2:if y2 < cuty or x2 < cutx:continueif y2 >= cuty and y1 <= cuty:y1 = cutyif y2 - y1 < 5:continueif x2 >= cutx and x1 <= cutx:x1 = cutxif x2 - x1 < 5:continueif i == 3:if y1 > cuty or x2 < cutx:continueif y2 >= cuty and y1 <= cuty:y2 = cutyif y2 - y1 < 5:continueif x2 >= cutx and x1 <= cutx:x1 = cutxif x2 - x1 < 5:continuetmp_box.append(x1)tmp_box.append(y1)tmp_box.append(x2)tmp_box.append(y2)tmp_box.append(box[-1])merge_bbox.append(tmp_box)return merge_bboxdef get_random_data(b_data, input_shape, hue=.1, sat=1.5, val=1.5):h, w = input_shape  # (540, 680)min_offset_x = 0.4min_offset_y = 0.4scale_low = 1 - min(min_offset_x, min_offset_y)  # 0.6scale_high = scale_low + 0.2  # 0.8image_datas = []box_datas = []index = 0place_x = [0, 0, int(w * min_offset_x), int(w * min_offset_x)]  # [0, 0, 243, 243]place_y = [0, int(h * min_offset_y), int(w * min_offset_y), 0]  # [0, 216, 243, 0]print("place:", place_x, place_y)for i in range(4):idx = iimg, box, img_path = b_data[i]# print(img_path, boxes)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)image = Image.fromarray(img, mode="RGB")# 图片的大小iw, ih = image.size# 是否翻转图片flip = rand() < .5if flip and len(box) > 0:image = image.transpose(Image.FLIP_LEFT_RIGHT)box[:, [0, 2]] = iw - box[:, [2, 0]]# 对输入进来的图片进行缩放new_ar = w / hscale = (scale_low + scale_high) / 2# scale = rand(scale_low, scale_high)if new_ar < 1:nh = int(scale * h)nw = int(nh * new_ar)else:nw = int(scale * w)nh = int(nw / new_ar)image = image.resize((nw, nh), Image.BICUBIC)# 进行色域变换hue = rand(-hue, hue)sat = rand(1, sat) if rand() < .5 else 1 / rand(1, sat)val = rand(1, val) if rand() < .5 else 1 / rand(1, val)x = rgb_to_hsv(np.array(image) / 255.)x[..., 0] += huex[..., 0][x[..., 0] > 1] -= 1x[..., 0][x[..., 0] < 0] += 1x[..., 1] *= satx[..., 2] *= valx[x > 1] = 1x[x < 0] = 0image = hsv_to_rgb(x)image = Image.fromarray((image * 255).astype(np.uint8))# 将图片进行放置,分别对应四张分割图片的位置dx = place_x[index]dy = place_y[index]new_image = Image.new('RGB', (w, h), (128, 128, 128))new_image.paste(image, (dx, dy))image_data = np.array(new_image) / 255index = index + 1box_data = []# 对box进行重新处理,处理越界问题。if len(box) > 0:np.random.shuffle(box)box[:, [0, 2]] = box[:, [0, 2]] * nw / iw + dxbox[:, [1, 3]] = box[:, [1, 3]] * nh / ih + dybox[:, 0:2][box[:, 0:2] < 0] = 0box[:, 2][box[:, 2] > w] = wbox[:, 3][box[:, 3] > h] = hbox_w = box[:, 2] - box[:, 0]box_h = box[:, 3] - box[:, 1]box = box[np.logical_and(box_w > 1, box_h > 1)]box_data = np.zeros((len(box), 5))box_data[:len(box)] = boximage_datas.append(image_data)box_datas.append(box_data)img = Image.fromarray((image_data * 255).astype(np.uint8))for j in range(len(box_data)):thickness = 3left, top, right, bottom = box_data[j][0:4]draw = ImageDraw.Draw(img)for i in range(thickness):draw.rectangle([left + i, top + i, right - i, bottom - i], outline=(255, 255, 255))# img.show()img.save("box_%d.jpg" % (idx + 1))# 将图片分割,放在一起cutx = np.random.randint(int(w * min_offset_x), int(w * (1 - min_offset_x)))cuty = np.random.randint(int(h * min_offset_y), int(h * (1 - min_offset_y)))new_image = np.zeros([h, w, 3])new_image[:cuty, :cutx, :] = image_datas[0][:cuty, :cutx, :]new_image[cuty:, :cutx, :] = image_datas[1][cuty:, :cutx, :]new_image[cuty:, cutx:, :] = image_datas[2][cuty:, cutx:, :]new_image[:cuty, cutx:, :] = image_datas[3][:cuty, cutx:, :]# 对框进行进一步的处理new_boxes = merge_bboxes(box_datas, cutx, cuty)return new_image, new_boxesdef get_4_data():data_dir = r"E:\dataset\coco128"file_paths = [os.path.join(data_dir, v) for v in os.listdir(data_dir)]print(file_paths)file_paths = [v for v in file_paths if v.endswith(".jpg") and os.path.exists(v[:-4] + ".txt")]print("label img cnt:", len(file_paths), file_paths)if len(file_paths) < 4:print("数据不足!")returnbatch_data = []for img_path in file_paths:img = cv2.imread(img_path)gt_boxes = []lines = []with open(img_path[:-4] + ".txt") as fp:for item in fp.readlines():lines.append(item.strip().split())lines = [v for v in lines if v]img_h, img_w = img.shape[:2]for item in lines:item = [float(v) for v in item][cls, cx, cy, bw, bh] = itemx1 = max(0, int((cx - bw / 2) * img_w))y1 = max(0, int((cy - bh / 2) * img_h))x2 = min(int((cx + bw / 2) * img_w), img_w - 1)y2 = min(int((cy + bh / 2) * img_h), img_h - 1)gt_boxes.append([x1, y1, x2, y2, int(cls)])batch_data.append([img, np.array(gt_boxes), img_path])return batch_dataif __name__ == "__main__":batch_data = get_4_data()image_data, box_data = get_random_data(batch_data, [608, 800])img = Image.fromarray((image_data * 255).astype(np.uint8))for j in range(len(box_data)):thickness = 3left, top, right, bottom = box_data[j][0:4]draw = ImageDraw.Draw(img)for i in range(thickness):draw.rectangle([left + i, top + i, right - i, bottom - i], outline=(255, 255, 255))# img.show()img.save("box_all.jpg")

数据集格式:

coco128,标签为类别、量化至0~1后的中心点x,y、宽高。

mosaic数据增强相关推荐

  1. mosaic数据增强_YoloV4当中的Mosaic数据增强方法(附代码详细讲解)

    上一期中讲解了图像分类和目标检测中的数据增强的区别和联系,这期讲解数据增强的进阶版- yolov4中的Mosaic数据增强方法以及CutMix. 前言 Yolov4的mosaic数据增强参考了CutM ...

  2. 睿智的目标检测28——YoloV4当中的Mosaic数据增强方法

    睿智的目标检测28--YoloV4当中的Mosaic数据增强方法 学习前言 代码下载 什么是Mosaic数据增强方法 实现思路 全部代码 1.数据增强 2.调用代码 学习前言 哈哈哈!我又来数据增强了 ...

  3. 【目标检测】(10) Mosaic 数据增强方法,附Python完整代码

    各位同学好,今天和大家分享一下目标检测算法中常用的图像数据增强方法 Mosaic.先放张图看效果.将四张图片缩放后裁剪拼接在一起,并调整检测框的坐标位置,处理位于图像边缘的检测框.文末有完整代码 1. ...

  4. YoloV4当中的Mosaic数据增强方法(附代码讲解)

    上一期中讲解了图像分类和目标检测中的数据增强的区别和联系,这期讲解数据增强的进阶版- yolov4中的Mosaic数据增强方法以及CutMix. 前言 Yolov4的mosaic数据增强参考了CutM ...

  5. 数据增强:YoloV4当中的Mosaic数据增强方法

    代码:https://github.com/bubbliiiing/yolo3-pytorch 对数据集转换成VOC格式,代码与上面可得. yolo3整体的文件夹构架如下: 本文使用VOC格式进行训练 ...

  6. yolov4中的mosaic数据增强

    文章详细讲解yolov4中的mosaic数据增强方法以及代码细节,如有错误,希望指正. 参考代码链接:https://github.com/bubbliiiing/yolov4-keras 1.下述代 ...

  7. 数据增强之Mosaic数据增强的优点、Mixup,Cutout,CutMix的区别

    一.Mosaic data augmentation Mosaic数据增强方法是YOLOV4论文中提出来的,主要思想是将四张图片进行随机裁剪,再拼接到一张图上作为训练数据. 这样做有以下几个优点: 1 ...

  8. 【图像数据增强】Mixup、Cutout、Random Erasing、CutMix、Mosaic等详解

    对于模型而言一般包含四个部分:输入.输出.网络结构.训练相关.如果想要改善模型,就可以从这四个部分入手. ● 输入:数据 --> Data Augmentation ● 输出:Loss相关 ● ...

  9. 几种数据增强:Mixup,Cutout,CutMix 和yolov4中的 Mosaic

    作者:RayChiu_Labloy 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 目录 1.几种数据增强的比较 2.What does model learn with ...

最新文章

  1. python快速编程入门课后题答案-《Python编程:从入门到实践》第五章 if语句 习题答案...
  2. 【算法】算法测试题4:最长公共连续子串
  3. Python 之glob模块
  4. 第三章 最小化SpringXml 配置
  5. java调用keras theano模型_使用Keras获得模型输出的梯度w.r.t权重
  6. 如果云是水滴,Kubernetes就是水滴管理平台
  7. pycharm pro版本激活
  8. 排序构造 GYM 101149 F - The Weakest Sith
  9. 【令人头秃的线段树】线段树入门题目详解(代码逐句分析)
  10. LINUX删除指定子目录下所有指定文件名
  11. 传统金融行业 IT 的核心竞争力究竟在何处?
  12. python百度关键词自动提交订单_百度链接提交-主动推送Python版
  13. 基于WEB的达内学子书城/商城源代码
  14. 华人“芯片女神”苏妈的硅谷传奇之路
  15. c++控制台版 俄罗斯方块 闪瞎眼
  16. 录屏鼠标光标圆圈如何实现_录屏鼠标光标圆圈如何实现
  17. Easy_RL 01:强化学习基础
  18. 数据库-SQL Server数据库查询速度慢(连接超时)原因及优化方法
  19. Matlab:串联示例
  20. Beyond Compare文件对比工具中文网站来啦

热门文章

  1. RTP协议学习大总结从原理到代码
  2. 讯飞配音使用记录:Excel VBA 编程处理多段短文字配音切分及 Hedit、GoldWave 后期处理、编程合成 WAV 文件
  3. windows11家庭版安装hyperv-v
  4. matlab 生成 gif
  5. Python3简单爬虫:爬取猫眼评分top100电影
  6. 十六进制与ascii码的互转(c语言),十六进制与ASCII码转换
  7. CSS第四篇(复合选择器)
  8. android微信7,微信7.0安卓版之初体验
  9. [SOC]clock与reset设计
  10. 2014年总结和2015年计划