-
Notifications
You must be signed in to change notification settings - Fork 7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unified inputs for F.rotate
#2495
Conversation
- updated F.affine tests
Codecov Report
@@ Coverage Diff @@
## master #2495 +/- ##
==========================================
+ Coverage 70.73% 70.80% +0.07%
==========================================
Files 94 94
Lines 8029 8077 +48
Branches 1275 1283 +8
==========================================
+ Hits 5679 5719 +40
- Misses 1946 1950 +4
- Partials 404 408 +4
Continue to review full report at Codecov.
|
|
||
point = torch.tensor([0.0, 0.0, 1.0]) | ||
for i in range(oh): | ||
for j in range(ow): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, we should optimize grid computation, e.g. matrix of points by theta
matrix multiplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should optimize this otherwise the performance will be very bad.
Can't we do something like (untested and probably has bugs)
i = (torch.arange(oh) + d - oh * 0.5) / (0.5 * h)
j = (torch.arange(ow) + d - ow * 0.5) / (0.5 * w)
ii, jj = torch.meshgrid(i, j)
coords = torch.stack([j, i], dim=-1)
output_grid = torch.matmul(coords, theta.T)
Note that I removed the 3rd coordinate of point
, it might be that it's necessary and we should put it back but this gives the gist of it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the code snippet. Yes, it is something like that, I was trying to implement it from my side too :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the PR!
I have a few questions and comments that I think would make the code a bit simpler and faster, let me know what you think.
We can do it in two ways -- we can either merge this and then have an immediate follow-up task to optimize this function, or do it here. We can do as you prefer.
|
||
point = torch.tensor([0.0, 0.0, 1.0]) | ||
for i in range(oh): | ||
for j in range(ow): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should optimize this otherwise the performance will be very bad.
Can't we do something like (untested and probably has bugs)
i = (torch.arange(oh) + d - oh * 0.5) / (0.5 * h)
j = (torch.arange(ow) + d - ow * 0.5) / (0.5 * w)
ii, jj = torch.meshgrid(i, j)
coords = torch.stack([j, i], dim=-1)
output_grid = torch.matmul(coords, theta.T)
Note that I removed the 3rd coordinate of point
, it might be that it's necessary and we should put it back but this gives the gist of it
return _apply_grid_transform(img, grid, mode) | ||
|
||
|
||
def _compute_output_size(theta: Tensor, w: int, h: int) -> Tuple[int, int]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this (relatively expensive) function for calculating the output size? I think we can get it in constant time.
From some quick analysis, we might be able to get the height/width of the new image via something like
h_new = h * sin(alpha) + w * cos(alpha)
w_new = h * cos(alpha) + w * sin(alpha)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Analytical approach can be nice :)
Here there matrix computations for just 4 points, so it is not that expensive. Let me check if I can provide an analytical computation with the same result as PIL.
@@ -418,21 +418,21 @@ def test_affine(self): | |||
test_configs = [ | |||
(45, [5, 6], 1.0, [0.0, 0.0]), | |||
(33, (5, -4), 1.0, [0.0, 0.0]), | |||
(45, [5, 4], 1.2, [0.0, 0.0]), | |||
(33, (4, 8), 2.0, [0.0, 0.0]), | |||
(45, [-5, 4], 1.2, [0.0, 0.0]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a particular reason why we are changing those values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests were missing negative transpose values, so added just them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the comments Francisco ! I'll update the PR and ping you once it is ready
@@ -418,21 +418,21 @@ def test_affine(self): | |||
test_configs = [ | |||
(45, [5, 6], 1.0, [0.0, 0.0]), | |||
(33, (5, -4), 1.0, [0.0, 0.0]), | |||
(45, [5, 4], 1.2, [0.0, 0.0]), | |||
(33, (4, 8), 2.0, [0.0, 0.0]), | |||
(45, [-5, 4], 1.2, [0.0, 0.0]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests were missing negative transpose values, so added just them.
return _apply_grid_transform(img, grid, mode) | ||
|
||
|
||
def _compute_output_size(theta: Tensor, w: int, h: int) -> Tuple[int, int]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Analytical approach can be nice :)
Here there matrix computations for just 4 points, so it is not that expensive. Let me check if I can provide an analytical computation with the same result as PIL.
|
||
point = torch.tensor([0.0, 0.0, 1.0]) | ||
for i in range(oh): | ||
for j in range(ow): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the code snippet. Yes, it is something like that, I was trying to implement it from my side too :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks a lot!
return int(size[0]), int(size[1]) | ||
|
||
|
||
def _expanded_affine_grid(theta: Tensor, w: int, h: int, expand: bool = False) -> Tensor: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given that we will be using our own _gen_affine_grid
, I think it can be part of this function maybe?
* Added code for F_t.rotate with test - updated F.affine tests * Rotate test tolerance to 2% * Fixes failing test * Optimized _expanded_affine_grid with a single matmul op * Recoded _compute_output_size
Related to #2292
Description:
F_t.rotate
with testF.affine
tests