yolov5的load_mosaic代码详解

马赛克数据增强:

可以增加数据的复杂度,同时可以增加一张图片的标注数量

代码分析

 这段代码主要分成两部分,第一部分是对图片的切割和拼接,第二部分是对于lable的处理

def load_mosaic(self: object, index: object):
    # loads images in a 4-mosaic

    labels4, segments4 = [], []
    s = self.img_size
    yc, xc = [int(random.uniform(-x, 2 * s + x)) for x in self.mosaic_border]  # mosaic center x, y # 确立合成图中心坐标
    indices = [index] + random.choices(self.indices, k=3)  # 3 additional image indices
    for i, index in enumerate(indices):
        # Load image
        img, _, (h, w) = load_image(self, index) #加载图片并根据设定的输入大小与图片原大小的比例ratio进行resize

        # place img in img4 获得4块的坐标
        if i == 0:  # top left
            img4 = np.full((s * 2, s * 2, img.shape[2]), 114, dtype=np.uint8)  # base image with 4 tiles
            x1a, y1a, x2a, y2a = max(xc - w, 0), max(yc - h, 0), xc, yc  # xmin, ymin, xmax, ymax (large image)
            x1b, y1b, x2b, y2b = w - (x2a - x1a), h - (y2a - y1a), w, h  # xmin, ymin, xmax, ymax (small image)
        elif i == 1:  # top right
            x1a, y1a, x2a, y2a = xc, max(yc - h, 0), min(xc + w, s * 2), yc
            x1b, y1b, x2b, y2b = 0, h - (y2a - y1a), min(w, x2a - x1a), h
        elif i == 2:  # bottom left
            x1a, y1a, x2a, y2a = max(xc - w, 0), yc, xc, min(s * 2, yc + h)
            x1b, y1b, x2b, y2b = w - (x2a - x1a), 0, w, min(y2a - y1a, h)
        elif i == 3:  # bottom right
            x1a, y1a, x2a, y2a = xc, yc, min(xc + w, s * 2), min(s * 2, yc + h)
            x1b, y1b, x2b, y2b = 0, 0, min(w, x2a - x1a), min(y2a - y1a, h)

        img4[y1a:y2a, x1a:x2a] = img[y1b:y2b, x1b:x2b]  # img4[ymin:ymax, xmin:xmax]   # 将小图上截取的部分贴到大图上,img4[ymin:ymax, xmin:xmax]
        # 计算小图到大图上时所产生的偏移,用来计算mosaic增强后的标签框的位置
        padw = x1a - x1b
        padh = y1a - y1b

        # Labels
        labels, segments = self.labels[index].copy(), self.segments[index].copy()
        if labels.size:
            # 重新调整标签框的位置
            labels[:, 1:] = xywhn2xyxy(labels[:, 1:], w, h, padw, padh)  # normalized xywh to pixel xyxy format
            segments = [xyn2xy(x, w, h, padw, padh) for x in segments]
        labels4.append(labels)
        segments4.extend(segments)

    # Concat/clip labels
    labels4 = np.concatenate(labels4, 0)
    for x in (labels4[:, 1:], *segments4):
        np.clip(x, 0, 2 * s, out=x)  # clip when using random_perspective()
    # img4, labels4 = replicate(img4, labels4)  # replicate
    # 对mosaic整合的图片进行随机旋转、平移、缩放、裁剪,并resize为输入大小img_size
    # Augment
    img4, labels4 = random_perspective(img4, labels4, segments4,
                                       degrees=self.hyp['degrees'],
                                       translate=self.hyp['translate'],
                                       scale=self.hyp['scale'],
                                       shear=self.hyp['shear'],
                                       perspective=self.hyp['perspective'],
                                       border=self.mosaic_border)  # border to remove

    return img4, labels4

img4(640,640):一个大图,也是最终处理后输出的图片

 灰色部分是填充的

x1a,x2a,y1a,y2a指的是放在其中一张图片最后放在img4的位置坐标

x1b,x2b。。。指的是在原图(640,640)所截取图片的位置坐标

lable的偏移

算出坐标偏移量

 padw = x1a - x1b
  padh = y1a - y1b

def xywhn2xyxy(x, w=640, h=640, padw=0, padh=0):
    # Convert nx4 boxes from [x, y, w, h] normalized to [x1, y1, x2, y2] where xy1=top-left, xy2=bottom-right
    y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)
    y[:, 0] = w * (x[:, 0] - x[:, 2] / 2) + padw  # top left x
    y[:, 1] = h * (x[:, 1] - x[:, 3] / 2) + padh  # top left y
    y[:, 2] = w * (x[:, 0] + x[:, 2] / 2) + padw  # bottom right x
    y[:, 3] = h * (x[:, 1] + x[:, 3] / 2) + padh  # bottom right y
    return y

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是YOLOv5中实现Mosaic数据增强的代码: ```python def mosaic(self, img, boxes, labels): img_size = img.shape[:2] xc, yc = [int(random.uniform(img_size[i] * 0.4, img_size[i] * 0.6)) for i in range(2)] # mosaic中心点坐标 indices = [random.randint(0, len(self.img_files) - 1) for _ in range(3)] # 随机选择三张图像进行拼接 mosaic_img = np.zeros((2 * yc, 2 * xc, 3), dtype=np.uint8) mosaic_boxes, mosaic_labels = [], [] for i, index in enumerate([0, 1, 2, 3]): img_path = self.img_files[indices[index]] img, _, _ = self.load_image(img_path) img_boxes = boxes[indices[index]].copy() img_labels = labels[indices[index]].copy() if i == 0: # 左上角 x1a, y1a, x2a, y2a = self.rand_bbox(img_size, xc, yc) x1b, y1b, x2b, y2b = self.rand_bbox(img_size, xc, yc) mosaic_img[:yc, :xc, :] = img[y1a:y2a, x1a:x2a, :] mosaic_boxes.append(self.box_transform(img_boxes, (x1a, y1a, x2a, y2a))) mosaic_labels.append(img_labels) elif i == 1: # 右上角 x1a, y1a, x2a, y2a = self.rand_bbox(img_size, xc, yc) x1b, y1b, x2b, y2b = self.rand_bbox(img_size, xc, yc) mosaic_img[:yc, xc:, :] = img[y1a:y2a, x1b:x2b, :] mosaic_boxes.append(self.box_transform(img_boxes, (x1b - xc, y1a, x2b - xc, y2a))) mosaic_labels.append(img_labels) elif i == 2: # 左下角 x1a, y1a, x2a, y2a = self.rand_bbox(img_size, xc, yc) x1b, y1b, x2b, y2b = self.rand_bbox(img_size, xc, yc) mosaic_img[yc:, :xc, :] = img[y1b:y2b, x1a:x2a, :] mosaic_boxes.append(self.box_transform(img_boxes, (x1a, y1b - yc, x2a, y2b - yc))) mosaic_labels.append(img_labels) else: # 右下角 x1a, y1a, x2a, y2a = self.rand_bbox(img_size, xc, yc) x1b, y1b, x2b, y2b = self.rand_bbox(img_size, xc, yc) mosaic_img[yc:, xc:, :] = img[y1b:y2b, x1b:x2b, :] mosaic_boxes.append(self.box_transform(img_boxes, (x1b - xc, y1b - yc, x2b - xc, y2b - yc))) mosaic_labels.append(img_labels) return mosaic_img, np.concatenate(mosaic_boxes, 0), np.concatenate(mosaic_labels, 0) def rand_bbox(self, img_size, xc, yc): w, h = img_size size = min(w, h) x1 = random.randint(0, xc) y1 = random.randint(0, yc) x2 = random.randint(xc, size) y2 = random.randint(yc, size) return x1, y1, x2, y2 def box_transform(self, boxes, box): x1, y1, x2, y2 = box w, h = x2 - x1, y2 - y1 boxes[:, [0, 2]] -= x1 boxes[:, [1, 3]] -= y1 boxes[:, [0, 2]] /= w boxes[:, [1, 3]] /= h boxes[:, [0, 2]] = np.clip(boxes[:, [0, 2]], 0, 1) boxes[:, [1, 3]] = np.clip(boxes[:, [1, 3]], 0, 1) boxes[:, 2:4] -= boxes[:, :2] boxes[:, :2] += (x1, y1) boxes[:, 2:4] += (x1, y1) return boxes ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值