【python】Data Augmentation

news2024/11/16 10:26:01

在这里插入图片描述

参考学习来自:使用Python+OpenCV进行数据增广方法综述(附代码演练)

文章目录

  • Random Cut
  • Cutout
  • Color Jitter
  • Add Noisy

Random Cut

随机裁剪图片中的长款缩放为 scale 倍的区域,resize 到原图大小,bounding box 的坐标也相应的改变

引入了丢弃机制,裁剪后 bbox 的面积如果小于原来的 50%,该 bbox 丢弃

import random
import cv2


def randomcrop(img, gt_boxes, scale=0.5, ratio=0.25):
    '''
    ### Random Crop ###
    img: image
    gt_boxes: format [[obj x1 y1 x2 y2],...]
    scale: percentage of cropped area
    '''
    
    # Crop image
    height, width = int(img.shape[0]*scale), int(img.shape[1]*scale)
    # Top Left Coordinate
    x = random.randint(0, img.shape[1] - int(width))
    y = random.randint(0, img.shape[0] - int(height))
    cropped = img[y:y+height, x:x+width]

    # Visisual bbox
    img_copy = img.copy()
    cv2.rectangle(img_copy, (x, y), (x+width, y+height), color=[255, 0, 255], thickness=10)

    for i in range(len(gt_boxes)):
        cv2.rectangle(img_copy, (gt_boxes[i][1], gt_boxes[i][2]), (gt_boxes[i][3], gt_boxes[i][4]),
                      color=colors[i], thickness=5)
    cv2.imwrite("bbox.jpg", img_copy)

    resized = cv2.resize(cropped, (img.shape[1], img.shape[0]))

    # Modify annotation
    new_boxes = []
    for box in gt_boxes:
        obj_name = box[0]
        x1 = int(box[1])
        y1 = int(box[2])
        x2 = int(box[3])
        y2 = int(box[4])

        if ratio: # 是否丢弃裁剪过半的 bbox
            ori_area = (y2 - y1) * (x2 - x1)
            x1_new, y1_new, x2_new, y2_new = x1, y1, x2, y2
            if x1_new < x:
                x1_new = x
            if y1_new < y:
                y1_new = y
            if x2_new > x+width:
                x2_new = x+width
            if y2_new > y+height:
                y2_new = y+height
            new_area = (y2_new-y1_new) * (x2_new-x1_new)

            if (new_area / ori_area) < ratio:
                continue

        x1, x2 = x1-x, x2-x
        y1, y2 = y1-y, y2-y

        x1, y1, x2, y2 = x1/scale, y1/scale, x2/scale, y2/scale
        if (x1 < img.shape[1] and y1 < img.shape[0]) and (x2 > 0 and y2 > 0):
            if x1 < 0: x1 = 0
            if y1 < 0: y1 = 0
            if x2 > img.shape[1]: x2 = img.shape[1]
            if y2 > img.shape[0]: y2 = img.shape[0]
            new_boxes.append([obj_name, x1, y1, x2, y2])
    return resized, new_boxes


if __name__ == "__main__":
    colors = [[0, 0, 255],
              [0, 255, 0],
              [255, 0, 0],
              [0, 255, 255]]

    bbox = [["person", 777, 221, 1361, 769],
            ["cat", 1085, 413, 1337, 617],
            ['bird', 413, 273, 625, 581],
            ['bag', 877, 781, 1013, 909]]

    img = cv2.imread("./1.jpg")
    resized, new_bbox = randomcrop(img, bbox, scale=0.5, ratio=0.5)
    print(new_bbox)
    """
    [['person', 1162.0, 164.0, 1920, 1080], ['bird', 434.0, 268.0, 858.0, 884.0]]
    """

    for i in range(len(new_bbox)):
        cv2.rectangle(resized, (int(new_bbox[i][1]), int(new_bbox[i][2])),
                      (int(new_bbox[i][3]), int(new_bbox[i][4])),
                      color=colors[i], thickness=5)
    cv2.imwrite("resized.jpg", resized)

    # cv2.imshow("new bbox", resized)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

输入图片
在这里插入图片描述

案例1

bbox.jpg,粉色框是随机裁剪的区域,其他框是目标

在这里插入图片描述
resized.jpg,粉色区域也被缩放成原图大小,可以看到猫的框裁剪过半,被舍弃了

在这里插入图片描述

案例2

在这里插入图片描述
未出现裁剪过半的矩形框,所有目标都被保留

在这里插入图片描述

案例3

人和海鸥裁剪均过半,被舍弃,猫和包裁剪未过半,得以保留

在这里插入图片描述
resize 到原图大小

在这里插入图片描述

Cutout

import random
import cv2

def cutout(img, gt_boxes, amount=0.5):
    '''
    ### Cutout ###
    img: image
    gt_boxes: format [[obj x1 y1 x2 y2],...]
    amount: num of masks / num of objects 
    '''
    out = img.copy()
    ran_select = random.sample(gt_boxes, round(amount*len(gt_boxes)))

    for box in ran_select:
        x1 = int(box[1])
        y1 = int(box[2])
        x2 = int(box[3])
        y2 = int(box[4])
        mask_w = int((x2 - x1)*0.5)
        mask_h = int((y2 - y1)*0.5)
        mask_x1 = random.randint(x1, x2 - mask_w)
        mask_y1 = random.randint(y1, y2 - mask_h)
        mask_x2 = mask_x1 + mask_w
        mask_y2 = mask_y1 + mask_h
        cv2.rectangle(out, (mask_x1, mask_y1), (mask_x2, mask_y2), (0, 0, 0), thickness=-1)
    return out


if __name__ == "__main__":
    colors = [[0, 0, 255],
              [0, 255, 0],
              [255, 0, 0],
              [0, 255, 255]]

    bbox = [["person", 777, 221, 1361, 769],
            ["cat", 1085, 413, 1337, 617],
            ['bird', 413, 273, 625, 581],
            ['bag', 877, 781, 1013, 909]]

    img = cv2.imread("./1.jpg")
    out = cutout(img, bbox)
    for i in range(len(bbox)):
        cv2.rectangle(out, (bbox[i][1], bbox[i][2]), (bbox[i][3], bbox[i][4]),
                      color=colors[i], thickness=5)
    cv2.imwrite("cutout.jpg", out)

在目标中进行 mask,随机左上角,h和w固定为设定值——1/2

输入图片

在这里插入图片描述

输出结果

在这里插入图片描述
可以观察到,人形框和小猫框被 mask 掉了 1/4 区域

Color Jitter

import random
import cv2
import numpy as np

def colorjitter(img, cj_type="b"):
    '''
    ### Different Color Jitter ###
    img: image
    cj_type: {b: brightness, s: saturation, c: constast}
    '''
    if cj_type == "b":
        # value = random.randint(-50, 50)
        value = np.random.choice(np.array([-50, -40, -30, 30, 40, 50]))
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        h, s, v = cv2.split(hsv)
        if value >= 0:
            lim = 255 - value
            v[v > lim] = 255
            v[v <= lim] += value
        else:
            lim = np.absolute(value)
            v[v < lim] = 0
            v[v >= lim] -= np.absolute(value)

        final_hsv = cv2.merge((h, s, v))
        img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
        return img
    
    elif cj_type == "s":
        # value = random.randint(-50, 50)
        value = np.random.choice(np.array([-50, -40, -30, 30, 40, 50]))
        hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        h, s, v = cv2.split(hsv)
        if value >= 0:
            lim = 255 - value
            s[s > lim] = 255
            s[s <= lim] += value
        else:
            lim = np.absolute(value)
            s[s < lim] = 0
            s[s >= lim] -= np.absolute(value)

        final_hsv = cv2.merge((h, s, v))
        img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
        return img
    
    elif cj_type == "c":
        brightness = 10
        contrast = random.randint(40, 100)
        dummy = np.int16(img)
        dummy = dummy * (contrast/127+1) - contrast + brightness
        dummy = np.clip(dummy, 0, 255)
        img = np.uint8(dummy)
        return img


if __name__ == "__main__":
    img = cv2.imread("./1.jpg")
    img1 = colorjitter(img, "b")
    img2 = colorjitter(img, "s")
    img3 = colorjitter(img, "c")
    cv2.imwrite("b.jpg", img1)
    cv2.imwrite("s.jpg", img2)
    cv2.imwrite("c.jpg", img3)

输入图片

在这里插入图片描述

输出结果

b.jpg 亮度增广
在这里插入图片描述

c.jpg 对比度增广
在这里插入图片描述
s.jpg 饱和度增广

在这里插入图片描述

Add Noisy

import cv2
import numpy as np


def noisy(img, noise_type="gauss"):
    '''
    ### Adding Noise ###
    img: image
    cj_type: {gauss: gaussian, sp: salt & pepper}
    '''
    if noise_type == "gauss":
        image=img.copy() 
        mean=0
        st=0.7
        gauss = np.random.normal(mean,st,image.shape)
        gauss = gauss.astype('uint8')
        image = cv2.add(image,gauss)
        return image
    
    elif noise_type == "sp":
        image=img.copy() 
        prob = 0.05
        if len(image.shape) == 2:
            black = 0
            white = 255            
        else:
            colorspace = image.shape[2]
            if colorspace == 3:  # RGB
                black = np.array([0, 0, 0], dtype='uint8')
                white = np.array([255, 255, 255], dtype='uint8')
            else:  # RGBA
                black = np.array([0, 0, 0, 255], dtype='uint8')
                white = np.array([255, 255, 255, 255], dtype='uint8')
        probs = np.random.random(image.shape[:2])
        image[probs < (prob / 2)] = black
        image[probs > 1 - (prob / 2)] = white
        return image


if __name__ == "__main__":
    img = cv2.imread("./1.jpg")
    img1 = noisy(img, "gauss")
    img2 = noisy(img, "sp")
    cv2.imwrite("gauss.jpg", img1)
    cv2.imwrite("sp.jpg", img2)

输入图片

在这里插入图片描述

gauss.jpg 高斯噪声
在这里插入图片描述

sp.jpg 椒盐噪声

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1892357.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6域名系统DNS

《计算机网络》第7版&#xff0c;谢希仁 每次记不清楚的知识点&#xff0c;通过上网查找&#xff0c;总是只能看到很零碎的答案。最后还是最喜欢看这个版本的书&#xff0c;一看就回忆起来了&#xff0c;逻辑严谨&#xff0c;循循善诱&#xff0c;知识讲解的全面又清晰&#xf…

Elasticsearch:结合稀疏、密集和地理字段

作者&#xff1a;来自 Elastic Madhusudhan Konda 如何以自定义方式组合多个稀疏、密集和地理字段 Elasticsearch 是一款强大的工具&#xff0c;可用于近乎实时地搜索和分析数据。作为开发人员&#xff0c;我们经常会遇到包含各种不同字段的数据集。有些字段是必填字段&#x…

Cartoon UI(游戏卡通UI图标界面按钮框架)

卡通UI是一套完整的艺术UI组件&#xff0c;图标&#xff0c;按钮&#xff0c;将非常适合你的游戏项目。 所有组件都是高质量的&#xff0c;在专业水平上实现&#xff0c;并具有透明的背景&#xff0c;因此您可以将其放置在任何需要的表面上。 卡通UI包括&#xff1a; -按钮&…

VIO(Virtual_Input_Output) IP 使用笔记

VIO&#xff08;Virtual Input/Output&#xff09;IP 核&#xff0c;即虚拟输入输出 IP&#xff0c;可以通过调试界面模拟 IO 的变化&#xff0c;这可以在板子没有按键等外设、或外设不足的情况下&#xff0c;来模拟外部输入。然而网上关于 VIO 的教程都说的不是很清楚&#xf…

如何学习大型语言模型中的量化

前言 图片来自作者&#xff1a;Flow 展示了量化的必要性。&#xff08;笑脸和生气脸图片来自Yan Krukau) 在我解释上面的图表之前&#xff0c;让我先介绍一下您将在本文中学习的重点内容。 首先&#xff0c;您将了解量化是什么以及为什么量化。接下来&#xff0c;您将深入了解…

sssssssssssssssshare_ptrrrrrrrrrrrrrrrrrrrrrrrrr

智能指针——shared_ptr的原理及仿写 shared_ptr的原理及仿写 共享指针允许多个指针指向同一份数据&#xff0c;因为它使用了引用计数&#xff0c;每多一个指针指向这个数据&#xff0c;引用技术加一&#xff0c;每销毁一个指针&#xff0c;引用技术减一&#xff0c;如果引用计…

【 2024!深入了解 大语言模型(LLM)微调方法(总结)】

引言 众所周知&#xff0c;大语言模型(LLM)正在飞速发展&#xff0c;各行业都有了自己的大模型。其中&#xff0c;大模型微调技术在此过程中起到了非常关键的作用&#xff0c;它提升了模型的生成效率和适应性&#xff0c;使其能够在多样化的应用场景中发挥更大的价值。 那么&…

助力企业数字化转型:无锡哲讯——您的专业SAP系统运维服务商

数字化时代&#xff0c;企业对SAP系统的依赖程度日益加深&#xff0c;而SAP系统的稳定运行对于企业的核心业务至关重要。 无锡哲讯作为专业的SAP运维服务商&#xff0c;致力于为客户提供全面的SAP运维解决方案&#xff0c;助力企业实现数字化转型&#xff0c;提升核心竞争力。 …

再次登榜,深兰科技荣膺全球独角兽企业500强

6月27&#xff5e;28日&#xff0c;《2024全球独角兽企业500强》榜单发布&#xff0c;深兰科技凭借在AI产业赋能和产品出海方面的出色表现&#xff0c;继2023年之后再次登榜。 《2024全球独角兽企业500强》评委会介绍&#xff0c;本届榜单的产生&#xff0c;是由“全球独角兽企…

logback log.info耗时异常,RollingFileAppender+TimeBasedRollingPolicy配置踩坑

我喜欢把核心内容放开头 此次log.info耗时异常升高&#xff0c;是由于日志量过大&#xff08;5G甚至以上&#xff09;&#xff0c;并且使用同步阻塞的RollingFileAppenderTimeBasedRollingPolicy&#xff0c;导致log.info一直等待日志文件滚动&#xff0c;造成了异常。解决方式…

ETCD概述--使用/特性/架构/原理

ETCD概述 ETCD是一个高度一致的分布式键值存储, 它提供了一种可靠的方式来存储需要由分布式系统或机器集群访问的数据(高可用, 强一致性)​全局的配置服务中心. 本文将介绍其特性、相关操作和常见的应用场景. 如果想了解更多, 请查阅我的技术博客: https://dingyuqi.com 特性 …

专访ATFX首席战略官Drew Niv:以科技创新引领企业高速发展

在金融科技创新的浪潮中&#xff0c;人才是推动企业高速发展的核心驱动力&#xff0c;优质服务是引领企业急速前行的灯塔。作为差价合约领域的知名品牌&#xff0c;ATFX高度重视人才引进工作&#xff0c;秉持“聚天下英才而用之”的理念&#xff0c;在全球范围内广揽科技精英&a…

某业帮六月校招后端笔试

题目一 解题思路 签到题&#xff0c;dp就行。 题目二 解题思路 这个比较烦人&#xff0c;需要处理额外的引号和括号。用DFS&#xff0c;对于每个间隙&#xff0c;插入与不插入都搜一遍。 题目三 解题思路&#xff1a; 双指针&#xff0c;左右各一个指针&#xff0c;对比长度&…

变频器配置V20

变频器控制最好是变频电机&#xff0c;在速度不低的情况下工频电机 改变电机转速&#xff0c;调节扭矩&#xff0c; 变频器 L1 L2 L3 ,R S T 电机输入 uvw 电机输出 FSD 制动电阻 设置步骤 恢复出厂设置 p0010:30 p0970:21p0003:3(设定访问级别) P0003 用户访问级别 0 - 4 1…

沟通方法和技巧

0 Preface/Foreword 1 沟通对象 沟通维度&#xff1a; upward&#xff0c;向上沟通&#xff0c;直接上级downward&#xff0c;向下沟通&#xff0c;直接下级horizontal&#xff0c;横向沟通&#xff0c;同部门/跨部门同事 2 沟通方式&#xff08;5W2H&#xff09; 对于开会和…

css样式flex布局之,盒子垂直居中

<div class"item"><img src"../../assets/images!code_app.png" alt"" /><div>5555</div><p>微信扫一扫关注</p><p>“快速预约挂号”</p></div>.item{display: flex;flex-direction: col…

两个令人兴奋的 PostgreSQL 特性可改善 NULL 处理#PG认证

唯一列中的 NULL 值永久链接 一个众所周知但令人讨厌的怪异值NULL是NULL ! NULL&#xff0c;因此一UNIQUE列仍然可以有多个NULL值。 #PG培训#PG考试#postgresql培训#postgresql考试#postgresql认证 &#xff08;为了简单起见&#xff0c;示例使用数字 id 列&#xff0c;但我…

DevExpress WPF中文教程:Grid - 如何显示摘要(设计时)?

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

chrome 谷歌浏览器插件打包

1、找到id对应的字符串去搜索 C:\Users\<你的用户名>\AppData\Local\Google\Chrome\User Data\Default\Extensions2、选择根目录 直接加载下面的路径扩展可用&#xff1a;

liteide教程-运行平台和3264位

【1】编译后的运行平台选择&#xff08;linux/windows&#xff09; 1&#xff09;点击"查看"&#xff0c;选择"编辑当前环境" 2)GOOS参数修改 GOOSlinux //表示linux系统 GOOSwindows //表示Windows系统 【2】编译后的是32位还是64位程序 1&#x…