首页 > 其他分享 >Mosaic数据增强的实现

Mosaic数据增强的实现

时间:2023-03-07 22:26:32浏览次数:32  
标签:增强 img self boxes np new 数据 excursion Mosaic

mosaic数据增强是一种在YOLOv4中首次引入的数据增强技术,它可以将4张训练图像以一定的比例合并成一张。这样可以让模型学习如何在比正常更小的尺度上识别物体,也可以在训练中显著减少对大批量大小的需求。

 

mosaic数据增强的优势主要有以下几点:

  • 它可以丰富一张图像上的信息,让模型学习到更多的场景和目标。
  • 它可以减少对大批量大小的依赖,因为一张图像上包含了四张图像的信息。
  • 它可以提高模型对小目标的检测能力,因为将四张图像拼接成一张,相当于缩小了目标的尺寸。
  • 它可以提高模型的泛化能力,因为它可以增加图像背景的复杂度,防止模型过拟合。

Mosaic的一种具体的实现方法如下:

  1. 从数据集中随机挑选四张图片。
  2. 对每张图片进行放大、缩小、平移等几何变换和平滑、模糊、对比度、亮度等像素变换。
  3. 随机从四张图片中各裁剪出一部分区域,进行拼接得到一张固定大小的图片如640x640。
  4. 对每张图片的GT框进行同样的几何变换,同时去除那些裁剪后小于某一阈值的标注框。
class MosicDataset(Dataset):

    def __init__(self, size=(640, 640)):
        super(MosicDataset, self).__init__()
        self.src_data = VocDataset()  # 一个DataSet类,每次返回一个图片,以及对应的标注框
        self.dst_size = size

    def __getitem__(self, idx):
        scale_ratio = (0.6, 1.4)
        src_img, src_boxes, _ = self.src_data[idx]
        img_indexs = np.random.choice(np.arange(self.__len__()), size=3)
        datas = [(src_img, src_boxes)]
        # 随机取出三张图片加上固定的一张一共四张
        for i in img_indexs:
            img, boxes, _ = self.src_data[i]
            datas.append((img, boxes))
        random.shuffle(datas)  # 打乱图片
        h, w = self.dst_size
        # 在640X640大小的背景上随机确定一点,过此点做垂直于四条边的线,将图片分为四部分
        cy, cx = random.randint(h // 4, w * 3 // 4), random.randint(h // 4, w * 3 // 4)
        cys = [cy, h - cy, 0]  # 分别是第一部分的高度,第二部分的高度,最后一个为0,方便循环
        cxs = [cx, w - cx, 0]
        new_images = np.ones(shape=(h, w, 3), dtype=np.uint8) * 114
        new_boxes = []
        for i in range(2):
            for j in range(2):
                img, boxes = datas[i * 2 + j]
                H, W, _ = img.shape
                sr = np.random.uniform(scale_ratio[0], scale_ratio[1])  # 随机缩放图片
                img = cv2.resize(img, (int(sr * W), int(sr * H)), interpolation=cv2.INTER_LINEAR)
                H, W, _ = img.shape
                # 随机在每张图片上进行裁剪
                excursion_x, excursion_y = random.randint(0, max(H - cxs[i], 0)), random.randint(0, max(W - cys[j], 0))
                # 将裁剪后的图片复制到画布上
                new_images[cxs[i - 1]: cxs[i - 1] + min(cxs[i], H - excursion_x),
                cys[j - 1]: cys[j - 1] + min(cys[j], W - excursion_y)] = img[
                                                                         excursion_x: excursion_x + min(cxs[i],
                                                                                                        H - excursion_x),
                                                                         excursion_y: excursion_y + min(cys[j],
                                                                                                        W - excursion_y)]
                for box in boxes:
                    # 对标注框进行放缩
                    xmin, ymin, xmax, ymax = box[:4] * sr
                    # 确保标注框不会出界
                    xmin = np.clip(xmin - excursion_y, a_min=0, a_max=cys[j])
                    ymin = np.clip(ymin - excursion_x, a_min=0, a_max=cxs[i])
                    xmax = np.clip(xmax - excursion_y, a_min=0, a_max=cys[j])
                    ymax = np.clip(ymax - excursion_x, a_min=0, a_max=cxs[i])
                    # 排除裁剪后和裁剪前相比剩余部分较小的标注框:这里既可以用比例,也可以指定面积。
                    if ((ymax - ymin) * (xmax - xmin)) / ((box[3] - box[1]) * (box[2] - box[0]) * sr * sr) > 0.3:
                        # 将标注框还原到画布
                        new_boxes.append(
                            [xmin + cys[j - 1], ymin + cxs[i - 1], xmax + cys[j - 1], ymax + cxs[i - 1], box[-1]])

        new_boxes = np.array(new_boxes, dtype=np.float32)
        trans = transforms.Compose([transforms.ToTensor(),
                                    transforms.ColorJitter(0.2, 0.2, 0.2),
                                    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])
        # new_images = trans(new_images)
        # new_boxes = paddle.to_tensor(new_boxes, dtype=paddle.float32)
        return new_images, new_boxes

    def __len__(self):
        return self.src_data.__len__()

诸事不顺,幸得二月初春,忽见嫩芽新发,才不致满面愁容。最后以白居易的一首诗结尾吧:

春风先发苑中梅,樱杏桃梨次第开。荠花榆荚深村里,亦道春风为我来。 — 唐代·白居易《春风》

标签:增强,img,self,boxes,np,new,数据,excursion,Mosaic
From: https://www.cnblogs.com/wensi-eric/p/17189930.html

相关文章

  • String类和基本数据类型
    String和基本数据类型笔记String笔记String基础publicfinalclassString  implementsjava.io.Serializable,Comparable<String>,CharSequence{在String源码......
  • 接受参数和数据回传及JavaWeb可能遇到的乱码问题
    一.处理提交的数据我们通过编写一个控制类来测试:@Controller@RequestMapping("/user")publicclasscontrollerTest5{@GetMapping("/t1")publicStringte......
  • 数据结构第一篇:线性表的顺序存储结构
    一:线性表的抽象数据类型(ADT)描述:ADTList{Data:D={a1,a2,......,an}//每个元素的类型均为ElemType类型。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱......
  • 数据挖掘(2.1)--数据预处理
    一、基础知识1.数据的基本概念1.1基础知识数据是数据对象(DataObjects)及其属性(Attributes)的集合。数据对象(一条记录、一个实体、一个案例、一个样本等)是对一个事物或......
  • redis-redis介绍与安装、连接池、数据类型
    1.介绍和安装1.介绍:缓存数据库(大部分时间做缓存,不仅仅可以做缓存),非关系型数据库(区别于mysql关系型数据库)。原来从mysql中查的数据,现在可以从Redis中查,可以提高效率。......
  • docker容器数据卷
    作用:容器之间可以交互数据。docker容器产生的数据,如果不通过dockercommit成为新的镜像,使得数据作为镜像的一部分保存下来,那       么当容器删除后,数据自然也......
  • 如何在VirtualBox中创建共享文件夹(增强功能老安装不上版)
    这个破功能折腾了我几个小时现在来记录一下解决过程一开始是用的seedlabs中的一个方法:https://seedsecuritylabs.org/Labs_16.04/Documents/SEEDVM_VirtualBoxManual.pdf......
  • 连上mysql数据库了,先小发表一下
    首先我的mysql是8.0版本的,用的8版本的驱动包就连接失败找不到类,后来换成5版本的就好了。一开始我按照网上的教程,告诉我需要在子线程才能执行jdbc的连接,代码如下所示:r......
  • 关系型数据库特点
    1)数据集中控制。在文件管理方法中,文件是分散的,每个用户或每种处理都有各自的文件,这些文件之间一般是没有联系的,因此,不能按照统一的方法来控制、维护和管理。而数据库则很好......
  • 软件工程日报十一——安卓studio的数据查询
    上一篇博客实现了安卓studio内数据的添加,这篇博客来实现数据的查询。mainactivity_main.xml文件<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android=......