Python PyTorch:如何对多个图像应用相同的随机变换?
我正在为包含多对图像的数据集编写一个简单的转换。作为数据扩充,我想对每一对应用一些随机变换,但该对中的图像应以相同的方式进行变换。 例如,给定一对两个图像Python PyTorch:如何对多个图像应用相同的随机变换?,python,pytorch,torchvision,Python,Pytorch,Torchvision,我正在为包含多对图像的数据集编写一个简单的转换。作为数据扩充,我想对每一对应用一些随机变换,但该对中的图像应以相同的方式进行变换。 例如,给定一对两个图像a和B,如果a水平翻转,B必须水平翻转为a。然后下一对C和D应与A和B进行不同的转换,但C和D的转换方式相同。我正在尝试下面的方法 随机导入 将numpy作为np导入 导入torchvision.transforms作为变换 从PIL导入图像 img_a=Image.open(“sample_ajpg”)#注意两个图像的大小相同 img_b=I
a
和B
,如果a
水平翻转,B
必须水平翻转为a
。然后下一对C
和D
应与A
和B
进行不同的转换,但C
和D
的转换方式相同。我正在尝试下面的方法
随机导入
将numpy作为np导入
导入torchvision.transforms作为变换
从PIL导入图像
img_a=Image.open(“sample_ajpg”)#注意两个图像的大小相同
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()]
)
随机种子(0)
显示(变换(img_a))
显示(变换(img_b))
随机种子(1)
显示(变换(img_c))
显示(变换(img_d))
然而,上面的代码并没有选择相同的转换,正如我测试的那样,它取决于调用transform
的次数
有没有办法强制转换。RandomChoice在指定时使用相同的转换?我不知道有什么函数可以修复随机输出。 也许可以尝试不同的逻辑,比如自己创建随机化,以便能够重用相同的转换。 逻辑:
- 生成一个随机数
- 根据数字对两幅图像应用变换
- 生成另一个随机数
- 对其他两个图像执行相同的操作 试试这个:
通常,解决方法是对第一幅图像应用变换,检索该变换的参数,然后对其余图像应用具有这些参数的确定性变换。但是,此处不提供获取应用的转换参数的API,因为它涉及的转换数量可变。 在这些情况下,我通常实现对原始函数的覆盖 看一看,它很简单:
class RandomChoice(RandomTransforms):
def __call__(self, img):
t = random.choice(self.transforms)
return t(img)
这里有两种可能的解决方案
\uuuuu init\uuuuu
而不是\uuuu call\uuuuu
上从转换列表中采样:
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
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
简单地说,将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中讨论过了。在官方GitHub存储库中讨论了几种解决方案的优缺点。
PyTorch维护人员提出了这种简单的方法
不要使用torchvision.transforms.RandomVerticalFlip(p=1)
。使用torchvision.transforms.functional.vflip
函数转换为您提供了对转换管道的细粒度控制。与上面的变换相反,函数变换的参数不包含随机数生成器。这意味着您必须指定/生成所有参数,但您可以重用函数转换。只是为了澄清,
transform=transforms.RandomChoice([
在您的答案中实际上是transform=RandomChoice([
,对吗?Oups,很抱歉应该是T.RandomChoice())
自从我导入了torchvision.transforms
为T
。虽然这段代码可能会解决问题,但如何以及为什么解决问题会真正有助于提高你的文章质量,并可能导致更多的投票。请记住,你是在回答未来读者的问题,而不仅仅是问问题的人g现在。请您的答案添加解释,并说明适用的限制和假设。@AdrianMole感谢您的建议。我添加了解释:-)
import random
import torchvision.transforms.functional as TF
if random.random() > 0.5:
image = TF.vflip(image)
mask = TF.vflip(mask)