Surprising convention for grid sample coordinates

el_samou_samou: <p>Hi,</p>
<p>The coordinate convention for the index in the grid sample is a bit surprising to me. Indeed, it seems to correspond to the standard tensor indexing coordinate but in reverse order.</p>
<p>Here is a code sample to observe what I am saying:</p>
<pre><code class="lang-auto">import torch

a = torch.rand(1, 1, 4, 3)
b = torch.nn.functional.grid_sample(a, torch.tensor([[[[1, -1]]]]).type(torch.FloatTensor), align_corners=True)
#b corresponds to top right corner, i.e. j,i coordinates
print(a[0, 0, 0, 2], b)

c = torch.rand(1, 1, 4, 3, 2)
d = torch.nn.functional.grid_sample(c, torch.tensor([[[[[1, 1, -1]]]]]).type(torch.FloatTensor), align_corners=True)
#Again, here the convention is k, j, i
print(c[0, 0, 0, 2, 1], d)
</code></pre>
<p>I was wondering if there were any reasoning behind this convention as it seems counter-intuitive to me.</p>
<p>Thank you for your help,</p>
<p>Samuel</p>

el_samou_samou: <p>Sorry to insist but I think it should at least be specified in the documentation as the coordinate system used to specify positions where to sample in the input tensor (i.e. the index tensor) is not intuitive.</p>

ptrblck: <p>I’m not sure, if I misunderstand the question, but I would assume this result based on the description from the <a href="https://pytorch.org/docs/stable/nn.functional.html?highlight=grid_sample#torch.nn.functional.grid_sample">docs</a>:</p>
<blockquote>
<p><code>grid</code>  specifies the sampling pixel locations normalized by the  <code>input</code>  spatial dimensions. Therefore, it should have most values in the range of  <code>[-1, 1]</code> . For example, values  <code>x = -1, y = -1</code>  is the left-top pixel of  <code>input</code> , and values  <code>x = 1, y = 1</code>  is the right-bottom pixel of  <code>input</code> .</p>
</blockquote>
<pre data-code-wrap="python"><code class="lang-python">a = torch.rand(1, 1, 4, 3)
top_left = torch.nn.functional.grid_sample(a, torch.tensor([[[[-1, -1]]]]).type(torch.FloatTensor), align_corners=True)
top_right = torch.nn.functional.grid_sample(a, torch.tensor([[[[1, -1]]]]).type(torch.FloatTensor), align_corners=True)
bottom_left = torch.nn.functional.grid_sample(a, torch.tensor([[[[-1, 1]]]]).type(torch.FloatTensor), align_corners=True)
bottom_right = torch.nn.functional.grid_sample(a, torch.tensor([[[[1, 1]]]]).type(torch.FloatTensor), align_corners=True)
#b corresponds to top right corner, i.e. j,i coordinates
print(a[0, 0, 0, 0], top_left)
print(a[0, 0, 0, -1], top_right)
print(a[0, 0, -1, 0], bottom_left)
print(a[0, 0, -1, -1], bottom_right)
</code></pre>
<p>Is the confusion created because of the usage of an image coordinate system with x and y axes?<br>
Note that the x-axis is along the width of an image and the y-axis is along its height.</p>

el_samou_samou: <p>Hi,</p>
<p>Thank you for your answer. The confusion to me comes from when the input tensor is a 5D tensor (so when we consider a batch of 3D inputs with some channels). Then the convention is k,j,i meaning z,y,x which I find surprising (and is not specified in the documentation).</p>
<p>That is what I meant.</p>
<p>Samuel</p>

ptrblck: <p>Ah OK, thanks for the follow up.<br>
You could create an <a href="https://github.com/pytorch/pytorch/issues">issue</a> and suggest to improve the docs.<br>
Would you be interested in creating a PR with this improvement?</p>

el_samou_samou: <p>Hi,</p>
<p>I will create an issue to suggest those specification in the docs. Sorry but I don’t want to handle the PR for this. Thank you for your help.</p>

Ilya_Kotlov: <p><a class="mention" href="/u/ptrblck">@ptrblck</a>, Noticed the same thing. I think from a code perspective, the opposite is the more intuitive and expected outcome.</p>
<aside class="quote no-group" data-username="ptrblck" data-post="3" data-topic="79997">
<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/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<p>Is the confusion created because of the usage of an image coordinate system with x and y axes?<br>
Note that the x-axis is along the width of an image and the y-axis is along its height.</p>
</blockquote>
</aside>
<p>Exactly. I was expected that the image coordinate system will be as same as in a tensor, 2d matrix or any other indexed container. In the terminology you used, the x-axis to be along the height (rows) and the y-axis to be along the width.</p>
<p>Is it worth a PR if ill look at it and change the code in that way ?<br>
Like instead changing the docs, I think it more appropriate to change the behavior.</p>
<p>Or maybe there is some logic in that choice, which I don’t get by first look. I would gladly hear what stands behind this choice.</p>

ptrblck: <aside class="quote no-group" data-username="Ilya_Kotlov" data-post="8" data-topic="79997">
<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/ilya_kotlov/48/35840_2.png" class="avatar"> Ilya_Kotlov:</div>
<blockquote>
<p>Is it worth a PR if ill look at it and change the code in that way ?<br>
Like instead changing the docs, I think it more appropriate to change the behavior.</p>
</blockquote>
</aside>
<p>Introducing backwards compatibility breaking changes are not easily accepted, but you should discuss it with the code owner by creating a GitHub issue and describing your idea.</p>
<aside class="quote no-group" data-username="Ilya_Kotlov" data-post="8" data-topic="79997">
<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/ilya_kotlov/48/35840_2.png" class="avatar"> Ilya_Kotlov:</div>
<blockquote>
<p>Or maybe there is some logic in that choice, which I don’t get by first look. I would gladly hear what stands behind this choice.</p>
</blockquote>
</aside>
<p>The camera coordinate system is defined by having the origin in the “top left” corner and using positive values for the x- and y-axis and is a standard in image processing.<br>
I know that it can be confusing especially if you are more used to working with general “matrices”.</p>

pansanity666: <p>This also confused me for days. But a possible understanding for the choice of ''x-axis width, y-axis height ‘’ is that openCV also uses this kind of coordinate system definition.</p>

pansanity666: <aside class="quote no-group" data-username="ptrblck" data-post="3" data-topic="79997">
<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/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<p>Is the confusion created because of the usage of an image coordinate system with x and y axes?<br>
Note that the x-axis is along the width of an image and the y-axis is along its height.</p>
</blockquote>
</aside>
<p>Maybe using ‘left-top’ corner here is better since x corresponds to left, and y corresponds to top.</p>