Pytorch resize 3d numpy array

username: bioinfo-dirty-jobs
cooked: <p>Dear all,<br>
I have 3d image and I would like to write a dataloader with a rescale trasformation .</p>
<p>What is the best way to do the rescaling? I have [240,240,180] I would like to  trasform [128,128,128].<br>
Any suggestion on  function for dataloader.<br>
Thanks so much</p>
<pre><code class="lang-auto">class Resize(object):
   
    def __init__(self, output_size):
        assert isinstance(output_size, (int, tuple))
        self.output_size = output_size

    def __call__(self, sample):
        image, label = sample["data"], sample["label"]

        h, w = image.shape[:2]
        if isinstance(self.output_size, int):
            if h &gt; w:
                new_h, new_w = self.output_size * h / w, self.output_size
            else:
                new_h, new_w = self.output_size, self.output_size * w / h
        else:
            new_h, new_w = self.output_size

        new_h, new_w = int(new_h), int(new_w)

        # img = transform.resize(image, (new_h, new_w))
        img = scipy.ndimage.zoom(image, 0.5)
        return {"data": img, "label": label}
</code></pre>

username: ptrblck
cooked: <p>If you want to use a bilinear or nearest neighbor interpolation, you could use `grid_sample](<a href="https://pytorch.org/docs/stable/nn.functional.html?highlight=grid_sample#torch.nn.functional.grid_sample">https://pytorch.org/docs/stable/nn.functional.html?highlight=grid_sample#torch.nn.functional.grid_sample</a>).</p>

username: bioinfo-dirty-jobs
cooked: <p>Thanks so much… I have a 3d  data and I create a  tensor like this:<br>
torch.Size([1, 240, 240, 240])</p>
<p>When I try  to use grid sample I have this error. Seem I can’t use for only 3D data it is correct?</p>
<pre><code class="lang-auto">flow = torch.Tensor([1,128,128,128])
torch.nn.functional.grid_sample(data['data'],flow, mode='bilinear', padding_mode='zeros', align_corners=None)
untimeError: grid_sampler(): expected 4D or 5D input and grid with same number of dimensions, but got input with sizes [1, 240, 240, 240] and grid with sizes [4]
</code></pre>

username: ptrblck
cooked: <p>You can use it for 4-D and 5-D data (your case, if you unsqueeze a fake channel dimension).<br>
However, the grid shape should be <code>[N, H_out, W_out, 2]</code>, while you are passing 4 values.</p>
<p>Here is a small example of the usage:</p>
<pre><code class="lang-python">N, C, H, W = 1, 24, 24, 24
x = torch.arange(N*C*H*W).view(N, 1, C, H, W).float()

d = torch.linspace(-1, 1, 12)
meshx, meshy, meshz = torch.meshgrid((d, d, d))
grid = torch.stack((meshx, meshy, meshz), 3)
grid = grid.unsqueeze(0) # add batch dim

out = F.grid_sample(x, grid, align_corners=True)
</code></pre>
<p>You might want to check, if the order of the meshes is correct for your use case.</p>

username: wjm
cooked: <p>hi ,I have a 4d data and like this: torch.Size([100, 1, 2, 2]),I want to know how resize it become ([100, 1, 32, 32])?</p>

username: ptrblck
cooked: <p>You cannot resize a tensor with 400 elements to 102400 elements.<br>
Depending on your use case, you could <code>repeat</code> the values in the last two dimensions:</p>
<pre><code class="lang-python">x = torch.randn(100, 1, 2, 2)
y = x.repeat(1, 1, 16, 16)
</code></pre>

username: zestyzapus
cooked: <p>Nice example! But I think the dimensions D, H, W corresponds to the directions z, y, x, respectively. If this is true, then <code>meshx, meshy, meshz = torch.meshgrid((d, d, d))</code> should be replaced with <code>meshz, meshy, meshx = torch.meshgrid((d, d, d))</code>. I’m not sure if there is another use case though.</p>
<p>From <code>gridsample</code> documentation:</p>
<blockquote>
<p>grid[n, d, h, w] specifies the x, y, z pixel locations for interpolating output[n, :, d, h, w]</p>
</blockquote>
<p>So indeed <code>meshx</code> should be put first when stacked. But since <code>meshx</code> changes in the dimension W, it should be the last of <code>torch.meshgrid</code> outputs.</p>
<p>Here is an example motived by yours. The element values indicate their coordinates, e.g. 291 is at (d,h,w) = (2,9,1).</p>
<pre data-code-wrap="python"><code class="lang-python">N, C, D, H, W = 1, 1, 3, 10, 10
x = torch.arange(N*C*D*H*W).view(N, C, D, H, W).float()

d = torch.linspace(-1, 1, 2)
h = torch.linspace(-1, 1, 3)
w = torch.linspace(-1, 1, 4)
meshz, meshy, meshx = torch.meshgrid((d, h, w))
grid = torch.stack((meshx, meshy, meshz), 3)
grid = grid.unsqueeze(0) # add batch dim

out = F.grid_sample(x, grid, align_corners=True)
print(x, grid, out)
</code></pre>

username: mikbuch
cooked: <p>Maybe a bit simplistic, and outside of the PyTorch library, but you could use a linear transformation with <code>scipy</code>:</p>
<pre><code class="lang-auto">import numpy as np

from scipy.ndimage import zoom

data = np.zeros((240, 240, 180))

data = zoom(data, (128/data.shape[0], 128/data.shape[1], 128/data.shape[2]))

print(data.shape)
</code></pre>
<p>Output:</p>
<pre><code class="lang-auto">(128, 128, 128)
</code></pre>
<p>Reference: <a href="https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.zoom.html" class="inline-onebox" rel="noopener nofollow ugc">scipy.ndimage.zoom — SciPy v1.11.1 Manual</a></p>