1

I need to create a scale matrix that is autograd compatible, works on B,C,H,W tensors, and takes input values (possibly generated randomly) for controlling the scaling. How can I generate and use a scale matrix for this?

import torch
import torch.nn.functional as F
import torchvision.transforms as transforms
from PIL import Image


# Load image
def preprocess_simple(image_name, image_size):
    Loader = transforms.Compose([transforms.Resize(image_size), transforms.ToTensor()])
    image = Image.open(image_name).convert('RGB')
    return Loader(image).unsqueeze(0)
    
# Save image   
def deprocess_simple(output_tensor, output_name):
    output_tensor.clamp_(0, 1)
    Image2PIL = transforms.ToPILImage()
    image = Image2PIL(output_tensor.squeeze(0))
    image.save(output_name)


def get_scale_mat(theta):
    ...
    return scale_mat


def scale_img(x, theta, dtype):
    scale_mat = get_scale_mat(theta)

    # Can F.affine_grid & F.grid_sample be used with a scale matrix?
    grid = F.affine_grid(scale_mat , x.size()).type(dtype)
    x = F.grid_sample(x, grid)
    return x


# Shear tensor
test_input = # Test image
scale = 5 # Example value
scaled_tensor = scale_img(test_input, scale)
ProGamerGov
  • 870
  • 1
  • 10
  • 23

1 Answers1

1

This is how you create and use a 3x2 scale matrix with F.affine_grid and F.grid_sample:

def get_scale_mat(m, device, dtype):
    scale_mat = torch.tensor([[m, 0., 0.],
                              [0., m, 0.]])
    return scale_mat
    
def scale_tensor(x, scale):
    assert scale > 0
    scale_matrix = get_scale_mat(scale, x.device, x.dtype)[None, ...].repeat(x.shape[0],1,1)                                        
    grid = F.affine_grid(scale_matrix, x.size())
    x = F.grid_sample(x, grid)
    return x
ProGamerGov
  • 870
  • 1
  • 10
  • 23
  • 1
    Yes, but you could get rid of ```theta``` and just get ```m``` as input to ```get_scale_mat```. ```m``` should be restricted to non-negative numbers. – Gil Pinsky Oct 19 '20 at 17:21
  • @GilPinsky Do you mean I should generate `m` in `scale_tensor` with the same code? – ProGamerGov Oct 19 '20 at 19:46
  • 1
    Your change to scale_tensor is good (just drop the ```:``` at the end of the assert line). What I mean is in ```get_scale_mat``` replace ```theta``` with ```m``` and drop the line ```m=1 / torch.sqrt(...```. The ```1/sqrt(theta)``` is redundant – Gil Pinsky Oct 19 '20 at 19:55
  • 1
    @GilPinsky Thanks for the help! I've removed the unnecessary code now. – ProGamerGov Oct 19 '20 at 20:23