PyTorch:如何将相同的随机变换应用于多个图像?

如何解决PyTorch:如何将相同的随机变换应用于多个图像?

我正在为包含多对图像的数据集编写一个简单的转换。作为数据增强,我想对每一对应用一些随机变换,但该对中的图像应该以相同的方式进行变换。 例如,给定一对两个图像AB,如果A水平翻转,B必须水平翻转为A。然后下一对CD 应该与AB 进行不同的转换,但是CD 的转换方式相同。我正在以下面的方式尝试

import random
import numpy as np
import torchvision.transforms as transforms
from PIL import Image

img_a = Image.open("sample_ajpg") # note that two images have the same size
img_b = Image.open("sample_b.png")
img_c,img_d = Image.open("sample_c.jpg"),Image.open("sample_d.png")

transform = transforms.RandomChoice(
    [transforms.RandomHorizontalFlip(),transforms.RandomVerticalFlip()]
)
random.seed(0)
display(transform(img_a))
display(transform(img_b))

random.seed(1)
display(transform(img_c))
display(transform(img_d))

然而,上面的代码并没有选择相同的转换,正如我测试的那样,它取决于调用 transform 的次数。

有没有办法强制 transforms.RandomChoice 在指定时使用相同的转换?

解决方法

通常的解决方法是对第一张图像应用变换,检索该变换的参数,然后对其余图像应用这些参数的确定性变换。但是,这里的 RandomChoice 没有提供 API 来获取应用转换的参数,因为它涉及可变数量的转换。 在这些情况下,我通常会覆盖原始函数。

看看 torchvision implementation,就这么简单:

class RandomChoice(RandomTransforms):
    def __call__(self,img):
        t = random.choice(self.transforms)
        return t(img)

这里有两种可能的解决方案。

  1. 您可以在 __init__ 而不是 __call__ 上从变换列表中采样:

    import random
    import torchvision.transforms as T
    
    class RandomChoice(torch.nn.Module):
        def __init__(self):
            super().__init__()
            self.t = random.choice(self.transforms)
    
        def __call__(self,img):
            return self.t(img)
    

    所以你可以这样做:

    transform = T.RandomChoice([
         T.RandomHorizontalFlip(),T.RandomVerticalFlip()
    ])
    display(transform(img_a)) # both img_a and img_b will
    display(transform(img_b)) # have the same transform
    
    transform = T.RandomChoice([
        T.RandomHorizontalFlip(),T.RandomVerticalFlip()
    ])
    display(transform(img_c)) # both img_c and img_d will
    display(transform(img_d)) # have the same transform
    

  1. 或者更好的是,批量转换图像:

    import random
    import torchvision.transforms as T
    
    class RandomChoice(torch.nn.Module):
        def __init__(self,transforms):
           super().__init__()
           self.transforms = transforms
    
        def __call__(self,imgs):
            t = random.choice(self.transforms)
            return [t(img) for img in imgs]
    

    允许这样做:

    transform = T.RandomChoice([
         T.RandomHorizontalFlip(),T.RandomVerticalFlip()
    ])
    
    img_at,img_bt = transform([img_a,img_b])
    display(img_at) # both img_a and img_b will
    display(img_bt) # have the same transform
    
    img_ct,img_dt = transform([img_c,img_d])
    display(img_ct) # both img_c and img_d will
    display(img_dt) # have the same transform
    
,

我不知道修复随机输出的函数。 也许尝试不同的逻辑,比如自己创建随机化以便能够重用相同的转换。 逻辑:

  • 生成随机数
  • 根据数字对两个图像应用转换
  • 生成另一个随机数
  • 对另外两张图片做同样的处理 试试这个:
import random
import numpy as np
import torchvision.transforms as transforms
from PIL import Image

img_a = Image.open("sample_ajpg") # note that two images have the same size
img_b = Image.open("sample_b.png")
img_c,img_d = Image.open("sample_c.jpg"),Image.open("sample_d.png")

if random.random() > 0.5:
        image_a_flipped = transforms.functional_pil.vflip(img_a)
        image_b_flipped = transforms.functional_pil.vflip(img_b)
else:
    image_a_flipped = transforms.functional_pil.hflip(img_a)
    image_b_flipped = transforms.functional_pil.hflip(img_b)

if random.random() > 0.5:
        image_c_flipped = transforms.functional_pil.vflip(img_c)
        image_d_flipped = transforms.functional_pil.vflip(img_d)
else:
    image_c_flipped = transforms.functional_pil.hflip(img_c)
    image_d_flipped = transforms.functional_pil.hflip(img_d)
    
display(image_a_flipped)
display(image_b_flipped)

display(image_c_flipped)
display(image_d_flipped)
,

简单地说,将 PyTorch 中的随机化部分放入 if 语句中。 下面的代码使用 vflip。同样适用于水平或其他变换。

import random
import torchvision.transforms.functional as TF

if random.random() > 0.5:
    image = TF.vflip(image)
    mask  = TF.vflip(mask)

此问题已在 PyTorch forum 中讨论过。官方 GitHub 存储库 page 上讨论了几种解决方案的优缺点。 PyTorch 维护者提出了这种简单的方法。

不要使用torchvision.transforms.RandomVerticalFlip(p=1)。使用torchvision.transforms.functional.vflip

功能转换使您可以对转换管道进行细粒度控制。与上面的转换相反,函数式转换不包含用于其参数的随机数生成器。这意味着您必须指定/生成所有参数,但您可以重用函数转换。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-