Autogradable image resize

meijieru: <p>Within <code>Tensorflow</code>, we can use <code>tf.image.resize_images(img, img_h, img_w)</code> to convert a feature map into another size.<br>
How can we do the same thing in <code>Pytorch</code>?</p>

smth: <p>you can look at these Upsampling* modules to resize up:</p>
<p><a href="http://pytorch.org/docs/nn.html#vision-layers" class="onebox" target="_blank">http://pytorch.org/docs/nn.html#vision-layers</a></p>
<p>To resize down, you can use AvgPool2d</p>

meijieru: <p>It works for me.<br>
Thank you very much.</p>

thnkim: <p>Hello,<br>
Is there a way for fractional resize, e.g., 128x128 to 96x96?</p>
<p>Well, 128x128 -&gt; 96x96 can be done by nn.UpsamplingNearest2d(scale_factor=3) followed by nn.AvgPool2d(4).<br>
I hope I can use another direct way (with interpolation).<br>
Thank you <img src="//discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=5" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

apaszke: <p>You can try <a href="https://github.com/pytorch/pytorch/commit/95a76edd90af22bc9930ee1ae23a353a32890907"><code>FractionalMaxPooling</code></a>.</p>

jwin: <p>Has this been implemented yet for float scale factors? Greatly appreciated!</p>

flavio: <p>Jwin, I had the same problem and I solved using a sampling grid:</p>
<pre><code class="lang-auto">def downsampling(x, size=None, scale_factor=None, mode='nearest'):
	# define size if user has specified scale_factor
	if size is None: size = (int(scale_factor*x.size(2)), int(scale_factor*x.size(3)))
	# create coordinates
	h = torch.arange(0,size[0]) / (size[0]-1) * 2 - 1
	w = torch.arange(0,size[1]) / (size[1]-1) * 2 - 1
	# create grid
	grid = torch.zeros(size[0],size[1],2)
	grid[:,:,0] = w.unsqueeze(0).repeat(size[0],1)
	grid[:,:,1] = h.unsqueeze(0).repeat(size[1],1).transpose(0,1)
	# expand to match batch size
	grid = grid.unsqueeze(0).repeat(x.size(0),1,1,1)
	if x.is_cuda: grid = grid.cuda()
	# do sampling
	return F.grid_sample(x, grid, mode=mode)
</code></pre>
<p>You can either use nearest or bilinear interpolation, depending on your needs. In my case I was downsizing a semantic layout, so I couldn’t use any type of pooling (non-integer values wheren’t allowed and a cross integer value between two classes didn’t have sense).<br>
I didn’t try this in upsampling. Notice that it only works with 4D tensors as input, so if you need to use it with a single image, before you have to .unsqueeze(0) it.</p>

ndronen: <p><a href="https://github.com/pytorch/pytorch/issues/5823" rel="nofollow noopener">My $0.02</a> about <code>tf.image.resize_images</code> and the state of related functionality in PyTorch.</p>

mariosfourn: <p>Does anyone have a solution for autogradable general nearest neighbours upsampling?</p>

ndronen: <p>The implementation of <a href="https://pytorch.org/docs/stable/nn.html#upsample" rel="nofollow noopener">nn.Upsample</a> in &gt;= version 0.4.x has a <code>size</code> kwarg, which allows you to specify an arbitrary height and width for the tensor. That handles upsampling, but the API is, so far, not as general as <code>tf.image.resize_images</code>, which can shrink tensors, too.</p>

mariosfourn: <p>Unfortunately the size cannot be any size. The dimensions must be multiples of the input dimensions, otherwise you get an error message.</p>

ptrblck: <p>If you use the default <code>mode='nearest'</code>.<br>
Change it to <code>mode='bilinear'</code> and it should run:</p>
<pre><code class="lang-python">x = torch.randn(1, 3, 24, 24)
up = nn.Upsample(size=47, mode='bilinear')
y = up(x)
print(y.shape)
&gt; torch.Size([1, 3, 47, 47])
</code></pre>

chenchr: <aside class="quote no-group quote-modified" data-username="flavio" data-post="8" data-topic="580">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/flavio/48/200_2.png" class="avatar"> flavio:</div>
<blockquote>
<p>def downsampling(x, size=None, scale_factor=None, mode=‘nearest’): # define size if user has specified scale_factor if size is None: size = (int(scale_factor<em>x.size(2)), int(scale_factor</em>x.size(3))) # create coordinates h = torch.arange(0,size[0]) / (size[0]-1) * 2 - 1 w = torch.arange(0,size[1]) / (size[1]-1) * 2 - 1 # create grid grid = torch.zeros(size[0],size[1],2) grid[:,:,0] = w.unsqueeze(0).repeat(size[0],1) grid[:,:,1] = h.unsqueeze(0).repeat(size[1],1).transpose(0,1) # expand to match batch size grid = grid.unsqueeze(0).repeat(x.size(0),1,1,1) if x.is_cuda: grid = grid.cuda() # do sampling return F.grid_sample(x, grid, mode=mode)</p>
</blockquote>
</aside>
<p>Is there any plan to support ‘nearest’ ? As in many dense estimation task, a edge preserving property is important, using bilinear  downsample will hurt that property…</p>

solsol: <p>Hi,<br>
I want to resize tensor with shape [n] to [n, m]. what is the best solution?</p>

ptrblck: <p>You cannot resize or view this tensor using these shapes, as the second one would have more elements.<br>
If you would like to repeat the elements of the first tensor <code>m</code> times, you could use <code>tensor.unsqueeze(0).repeat(1, m)</code> or <code>.extend(-1, m)</code>.</p>

solsol: <p>Got it. Thanks a lot</p>