【问题标题】:Differentiable affine transformation on patches of images in pytorchpytorch中图像块的可微仿射变换
【发布时间】:2021-12-13 13:55:24
【问题描述】:

我有一个张量的对象边界框,例如具有 [10,4] 的形状,对应于一批图像,例如具有形状 [2,3,64,64] 和具有形状 [10,6] 的每个对象的变换矩阵和定义哪个对象索引属于哪个图像的向量。 我想对图像的补丁应用仿射变换,并在应用变换后替换这些补丁。我现在正在使用 for 循环执行此操作,但我这样做的方式不可区分(我从 pytorch 获得了就地操作错误)。我想知道是否有一种不同的方法可以做到这一点。例如通过 grid_sample?

这是我当前的代码:

for obj_num in range(obj_vecs.shape[0]): #batch_size
    im_id = obj_to_img[obj_num]
    x1, y1, x2, y2 = boxes_pred[obj_num]
    im_patch = img[im_id, :, x1:x2, y1:y2]
    im_patch = im_patch[None, :, :, :]
    img[im_id, :, x1:x2, y1:y2] = self.VITAE.stn(im_patch, theta_mean[obj_num], inverse=False)[0]

【问题讨论】:

    标签: python pytorch affinetransform


    【解决方案1】:

    有几种方法可以在 PyTorch 中执行可区分的裁剪。

    让我们以 2D 为例:

    >>> x1, y1, x2, y2 = torch.randint(0, 9, (4,))
    (tensor(7), tensor(3), tensor(5), tensor(6))
    
    >>> x = torch.randint(0, 100, (9,9), dtype=float, requires_grad=True)
    tensor([[18., 34., 28., 41.,  1., 14., 77., 75., 23.],
            [62., 33., 64., 41., 16., 70., 47., 45., 19.],
            [20., 69.,  5., 51.,  1., 16., 20., 63., 52.],
            [51., 25.,  8., 30., 40., 67., 41., 27., 33.],
            [36.,  6., 95., 53., 69., 84., 51., 42., 71.],
            [46., 72., 88., 82., 71., 75., 86., 36., 15.],
            [66., 19., 58., 50., 91., 28.,  7., 83.,  4.],
            [94., 50., 34., 34., 92., 45., 48., 97., 76.],
            [80., 34., 19., 13., 77., 77., 51., 15., 13.]], dtype=torch.float64,
           requires_grad=True)
    

    给定x1x2(分别是y1y2 高度维度(分别是宽度维度)上的补丁索引边界。您可以使用组合获得对应的坐标网格torch.arangetorch.meshgrid 的:

    >>> sorted_range = lambda a, b: torch.arange(a, b) if b >= a else torch.arange(b, a)
    >>> xi, yi = sorted_range(x1, x2), sorted_range(y1, y2)
    (tensor([3, 4, 5, 6]), tensor([5]))
    
    >>> i, j = torch.meshgrid(xi, yi)
    (tensor([[3],
             [4],
             [5],
             [6]]), 
     tensor([[5],
             [5],
             [5],
             [5]]))
    

    使用该设置,您可以提取和替换 x 的补丁。

    1. 您可以通过直接索引x 来提取补丁:

      >>> patch = x[i, j].reshape(len(xi), len(yi))
      tensor([[67.],
              [84.],
              [75.],
              [28.]], dtype=torch.float64, grad_fn=<ViewBackward>)
      

      这是用于说明目的的掩码:

      tensor([[0., 0., 0., 0., 0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0., 1., 0., 0., 0.],
              [0., 0., 0., 0., 0., 1., 0., 0., 0.],
              [0., 0., 0., 0., 0., 1., 0., 0., 0.],
              [0., 0., 0., 0., 0., 1., 0., 0., 0.],
              [0., 0., 0., 0., 0., 0., 0., 0., 0.],
              [0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=torch.float64,
      grad_fn=<IndexPutBackward>)
      
    2. 您可以将x 中的值替换为使用torch.Tensor.index_put 对补丁进行某些转换的结果:

      >>> values = 2*patch
       tensor([[134.],
               [168.],
               [150.],
               [ 56.]], dtype=torch.float64, grad_fn=<MulBackward0>)
      
      >>> x.index_put(indices=(i, j), values=values)
      tensor([[ 18.,  34.,  28.,  41.,   1.,  14.,  77.,  75.,  23.],
              [ 62.,  33.,  64.,  41.,  16.,  70.,  47.,  45.,  19.],
              [ 20.,  69.,   5.,  51.,   1.,  16.,  20.,  63.,  52.],
              [ 51.,  25.,   8.,  30.,  40., 134.,  41.,  27.,  33.],
              [ 36.,   6.,  95.,  53.,  69., 168.,  51.,  42.,  71.],
              [ 46.,  72.,  88.,  82.,  71., 150.,  86.,  36.,  15.],
              [ 66.,  19.,  58.,  50.,  91.,  56.,   7.,  83.,   4.],
              [ 94.,  50.,  34.,  34.,  92.,  45.,  48.,  97.,  76.],
              [ 80.,  34.,  19.,  13.,  77.,  77.,  51.,  15.,  13.]],
          dtype=torch.float64, grad_fn=<IndexPutBackward>)
      

    【讨论】:

    • 谢谢!在将 im_patch 提供给 STN 之前克隆它是可行的!
    猜你喜欢
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    相关资源
    最近更新 更多