warpaffine2gridsample's Introduction
warpaffine2gridsample's People
warpaffine2gridsample's Issues
When the output size is different from the input ,the result is wrong
the code:
...
cv_img = cv2.warpAffine(image, M, (112, 112))
...
theta = normalize_transforms(param[0:2,:], w, h)
...
grid = F.affine_grid(theta, [1,3,112,112])
tensor_img = F.grid_sample(tensor_img, grid)
...
the affine_grid result is wrong.
how to calculate transforms from grid_sample to WarpAffine
how to calculate transforms from grid_sample to WarpAffine matrix
thx.
Drop-in replacement
The following should be quite close to a drop-in replacement for cv2.warpAffine
. The only difference in the interface is that torch_wrapaffine
expects a CxHxW torch.Tensor
, instead of a HxWxC np.ndarray
.
import numpy as np
import torch
import torch.nn.functional as F
def get_N(W, H):
"""N that maps from unnormalized to normalized coordinates"""
N = np.zeros((3, 3), dtype=np.float64)
N[0, 0] = 2.0 / W
N[0, 1] = 0
N[1, 1] = 2.0 / H
N[1, 0] = 0
N[0, -1] = -1.0
N[1, -1] = -1.0
N[-1, -1] = 1.0
return N
def get_N_inv(W, H):
"""N that maps from normalized to unnormalized coordinates"""
# TODO: do this analytically maybe?
N = get_N(W, H)
return np.linalg.inv(N)
def convert_M_to_theta(M, w, h):
"""convert affine warp matrix `M` compatible with `opencv.warpAffine` to `theta` matrix
compatible with `torch.F.affine_grid`
Note:
M works with `opencv.warpAffine`.
To transform a set of bounding box corner points using `opencv.perspectiveTransform`, M^-1 is required
Parameters
----------
M : np.ndarray
affine warp matrix shaped [2, 3]
w : int
width of image
h : int
height of image
Returns
-------
np.ndarray
theta tensor for `torch.F.affine_grid`, shaped [2, 3]
"""
M_aug = np.concatenate([M, np.zeros((1, 3))], axis=0)
M_aug[-1, -1] = 1.0
N = get_N(w, h)
N_inv = get_N_inv(w, h)
theta = N @ M_aug @ N_inv
theta = np.linalg.inv(theta)
return theta[:2, :]
def torch_warpaffine(img: torch.Tensor, M: np.ndarray, dsize, flags=cv2.INTER_NEAREST):
w, h = dsize
theta = convert_M_to_theta(M, w, h)
grid = F.affine_grid(
torch.tensor(theta, dtype=torch.float32, device=img.device).unsqueeze(0),
[1, 3, h, w],
align_corners=False,
)
mode = {
cv2.INTER_NEAREST: 'nearest',
cv2.INTER_LINEAR: 'linear',
}[flags]
result = F.grid_sample(img.unsqueeze(0), grid, mode=mode, align_corners=False).squeeze(0)
return result
In my testing, there were small (1px) differences between the output of cv2.wrapAffine
and torch_wrapaffine
. I have not investigated what causes them, but I would be glad if somebody figured that out.
Why do you invert the matrix before making the transformation?
I went through the various steps and managed to get to the final transformation matrix, but according to my mathematical calculations I shouldn't do the inverse of "param" before. Obviously applying the transformation without the inverse I don't get the correct result as yours... Could you please explain to me why it should be done?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.