| 798 | |
| 799 | |
| 800 | class Interpolation(Function): |
| 801 | @staticmethod |
| 802 | def forward(ctx, xyz, new_xyz, input, offset, new_offset, k=3): |
| 803 | """ |
| 804 | input: xyz: (m, 3), new_xyz: (n, 3), input: (m, c), offset: (b), new_offset: (b) |
| 805 | output: (n, c) |
| 806 | """ |
| 807 | assert xyz.is_contiguous() and new_xyz.is_contiguous() and input.is_contiguous() |
| 808 | idx, dist = knnquery(k, xyz, new_xyz, offset, new_offset) # (n, k), (n, k) |
| 809 | dist_recip = 1.0 / (dist + 1e-8) # (n, k) |
| 810 | norm = torch.sum(dist_recip, dim=1, keepdim=True) |
| 811 | weight = dist_recip / norm # (n, k) |
| 812 | |
| 813 | n, c, m = new_xyz.shape[0], input.shape[1], input.shape[0] |
| 814 | output = torch.cuda.FloatTensor(n, c).zero_() |
| 815 | pointops_cuda.interpolation_forward_cuda(n, c, k, input, idx, weight, output) |
| 816 | ctx.m, ctx.k = m, k |
| 817 | ctx.save_for_backward(idx, weight) |
| 818 | return output |
| 819 | |
| 820 | @staticmethod |
| 821 | def backward(ctx, grad_output): |
| 822 | """ |
| 823 | input: xyz: (m, 3), new_xyz: (n, 3), input: (m, c), offset: (b), new_offset: (b) |
| 824 | output: (n, c) |
| 825 | """ |
| 826 | m, k = ctx.m, ctx.k |
| 827 | idx, weight = ctx.saved_tensors |
| 828 | n, c = grad_output.shape |
| 829 | grad_input = torch.cuda.FloatTensor(m, c).zero_() |
| 830 | pointops_cuda.interpolation_backward_cuda(n, c, k, grad_output, idx, weight, grad_input) |
| 831 | return None, None, grad_input, None, None, None |
| 832 | |
| 833 | interpolation2 = Interpolation.apply |
nothing calls this directly
no outgoing calls
no test coverage detected