目标检测中的数据增强方法

Cutmix

在这里插入图片描述

   def load_cutmix_image_and_boxes(self, index, imsize=1024):
        """
        This implementation of cutmix author:  https://www.kaggle.com/nvnnghia
        Refactoring and adaptation: https://www.kaggle.com/shonenkov
        """
        w, h = imsize, imsize
        s = imsize // 2

        xc, yc = [int(random.uniform(imsize * 0.25, imsize * 0.75)) for _ in range(2)]  # center x, y
        indexes = [index] + [random.randint(0, self.image_ids.shape[0] - 1) for _ in range(3)]

        result_image = np.full((imsize, imsize, 3), 1, dtype=np.float32)
        result_boxes = []

        for i, index in enumerate(indexes):
            image, boxes = self.load_image_and_boxes(index)
            if i == 0:
                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, max(xc, 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)
            result_image[y1a:y2a, x1a:x2a] = image[y1b:y2b, x1b:x2b]
            padw = x1a - x1b
            padh = y1a - y1b

            boxes[:, 0] += padw
            boxes[:, 1] += padh
            boxes[:, 2] += padw
            boxes[:, 3] += padh

            result_boxes.append(boxes)

        result_boxes = np.concatenate(result_boxes, 0)
        np.clip(result_boxes[:, 0:], 0, 2 * s, out=result_boxes[:, 0:])
        result_boxes = result_boxes.astype(np.int32)
        result_boxes = result_boxes[
            np.where((result_boxes[:, 2] - result_boxes[:, 0]) * (result_boxes[:, 3] - result_boxes[:, 1]) > 0)]
        return result_image, result_boxes

Mixup

在这里插入图片描述

    def load_mixup_image_and_boxes(self, index):
        image, boxes = self.load_image_and_boxes(index)
        r_image, r_boxes = self.load_image_and_boxes(random.randint(0, self.image_ids.shape[0] - 1))
        return (image+r_image)/2, np.vstack((boxes, r_boxes)).astype(np.int32)

随机旋转n*90°,n∈(0,1,2,3)

在这里插入图片描述

class RandomRotate90:
    def __init__(self, prob=1.):
        self.prob = prob

    def __call__(self, img, bbox=None):
        w, h = img.shape[:2]
        bbox = (bbox[:, 0], bbox[:, 1], bbox[:, 2], bbox[:, 3])
        if random.random() < self.prob:
            factor = random.randint(0, 3)
            img = np.rot90(img, factor)
            if bbox is not None:
                bbox = self.bbox_rot90(bbox, factor, w)
        bbox = np.asarray(bbox).transpose((1, 0))
        return img, bbox

    def bbox_rot90(self, bbox, factor, shape):  # skipcq: PYL-W0613
        """Rotates a bounding box by 90 degrees CCW (see np.rot90)

        Args:
            bbox (tuple): A bounding box tuple (x_min, y_min, x_max, y_max).
            factor (int): Number of CCW rotations. Must be in set {0, 1, 2, 3} See np.rot90.
            rows (int): Image rows.
            cols (int): Image cols.

        Returns:
            tuple: A bounding box tuple (x_min, y_min, x_max, y_max).

        """
        if factor not in {0, 1, 2, 3}:
            raise ValueError("Parameter n must be in set {0, 1, 2, 3}")
        x_min, y_min, x_max, y_max = bbox[:4]
        if factor == 1:
            bbox = y_min, shape - x_max, y_max, shape - x_min
        elif factor == 2:
            bbox = shape - x_max, shape - y_max, shape - x_min, shape - y_min
        elif factor == 3:
            bbox = shape - y_max, x_min, shape - y_min, x_max
        return bbox

随机水平或垂直旋转

在这里插入图片描述

class RandomFlip:
    def __init__(self, prob=1):
        self.prob = prob

    def bbox_hflip(self, bbox, shape):  # skipcq: PYL-W0613
        """Flip a bounding box horizontally around the y-axis.

        Args:
            bbox (tuple): A bounding box `(x_min, y_min, x_max, y_max)`.

        Returns:
            tuple: A bounding box `(x_min, y_min, x_max, y_max)`.

        """
        x_min, y_min, x_max, y_max = bbox
        return shape - x_max, y_min, shape - x_min, y_max

    def bbox_vflip(self, bbox, shape):  # skipcq: PYL-W0613
        """Flip a bounding box vertically around the x-axis.

        Args:
            bbox (tuple): A bounding box `(x_min, y_min, x_max, y_max)`.

        Returns:
            tuple: A bounding box `(x_min, y_min, x_max, y_max)`.

        """
        x_min, y_min, x_max, y_max = bbox
        return x_min, shape - y_max, x_max, shape - y_min

    def __call__(self, img, bbox=None):
        w, h = img.shape[:2]
        bbox = (bbox[:, 0], bbox[:, 1], bbox[:, 2], bbox[:, 3])
        if random.random() < self.prob:
            d = random.randint(-1, 1)
            img = cv2.flip(img, d)
            if bbox is not None:
                if d == 0:
                    bbox = self.bbox_vflip(bbox, w)
                elif d == 1:
                    bbox = self.bbox_hflip(bbox, w)
                elif d == -1:
                    bbox = self.bbox_hflip(bbox, w)
                    bbox = self.bbox_vflip(bbox, w)
                else:
                    raise ValueError("Invalid d value {}. Valid values are -1, 0 and 1".format(d))

        bbox = np.asarray(bbox).transpose((1, 0))
        return img, bbox

随机擦除

在这里插入图片描述

class CoarseDropout:
    """
    CoarseDropout of the rectangular regions in the image.
    """
    def __init__(self, max_holes=30, max_height=8, max_width=8,
                 min_holes=5, min_height=4, min_width=4,
                 fill_value=0, p=1):
        self.max_holes = max_holes
        self.max_height = max_height
        self.max_width = max_width
        self.min_holes = min_holes if min_holes is not None else max_holes
        self.min_height = min_height if min_height is not None else max_height
        self.min_width = min_width if min_width is not None else max_width
        self.fill_value = fill_value
        self.prob = p
        assert 0 < self.min_holes <= self.max_holes
        assert 0 < self.min_height <= self.max_height
        assert 0 < self.min_width <= self.max_width

    def get_params_dependent_on_targets(self, img):
        height, width = img.shape[:2]

        holes = []
        for n in range(random.randint(self.min_holes, self.max_holes + 1)):
            hole_height = random.randint(self.min_height, self.max_height + 1)
            hole_width = random.randint(self.min_width, self.max_width + 1)

            y1 = random.randint(0, height - hole_height)
            x1 = random.randint(0, width - hole_width)
            y2 = y1 + hole_height
            x2 = x1 + hole_width
            holes.append((x1, y1, x2, y2))

        return holes

    def __call__(self, image, box=None):
        if random.random() < self.prob:
            holes = self.get_params_dependent_on_targets(image)
            image = cutout(image, holes, self.fill_value)
        return image, box
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点PY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值