Inputs:points holds N=3 points (x,y). transform is the 2×3 matrix M whose left 2×2 block is the identity (no rotation or scaling) and whose last column is the translation (tx,ty)=(10,20).
Homogeneous form: each point gains a third coordinate equal to 1, e.g. (1,0)→(1,0,1). That 1 multiplies tx and ty, folding translation into one matrix product.
Worked point (1,0):x′=1⋅1+0⋅0+10⋅1=11 and y′=0⋅1+1⋅0+20⋅1=20.
Other points:(0,1)→(0+10,1+20)=(10,21) and (1,1)→(11,21).
Output: one (x′,y′) row per input point, so N×2: [[11.0, 20.0], [10.0, 21.0], [11.0, 21.0]]. Floats, rounded to 4 decimal places.
Notice: every point moves by exactly (10,20) because the linear part is the identity; a block of 2s on the diagonal with zero translation would double them instead.
Constraints
points: Tensor of shape (N, 2) containing 2D points
transform: Tensor of shape (2, 3) - affine transformation matrix
Return: Transformed points as tensor of shape (N, 2)
You want to apply a single 2×3 affine transform to a batch of 2D points using PyTorch tensor ops only (no Python loops), by using homogeneous coordinates and a single matrix multiply.
1. Background Knowledge
An affine transformation in 2D is a function that maps a point (x,y) to a new point (x′,y′) by combining a linear transform (rotation, scaling, shear) and a translation:
(x′y′)=(acbdtxty)xy1
The 2×2 block (acbd) handles the linear part; (tx,ty) is the translation.
To express this as a single matrix multiplication, we use homogeneous coordinates: we append a 1 to each 2D point so that each point becomes (x,y,1). For a batch of N points, stacking them gives a tensor Ph of shape (N,3). The affine matrix M has shape (2,3). Using PyTorch’s row-major convention for batched points, the natural operation is:
P′=Ph⋅MT
where Ph∈RN×3, MT∈R3×2, giving P′∈RN×2.
In deep learning / CV code, this pattern shows up everywhere: you keep all points in a tensor of shape (N,2), convert once to homogeneous coordinates, and then use vectorized matrix multiplication so the operation is fast and GPU-friendly.
If you later extend to a batch of matrices (B, 2, 3) and points (B, N, 2), you will use broadcasting or einsum / bmm, but the idea remains: augment with ones, then multiply.
4. Common Pitfalls
Shape mismatches:
Using M instead of M.T: (N, 3) @ (2, 3) is invalid; you need (N, 3) @ (3, 2).
Concatenating along wrong dimension (e.g., dim=0 instead of dim=1).
Forgetting homogeneous coordinate:
If you multiply (N, 2) by a (2, 2) linear matrix, you only get rotation/scale/shear, no translation.
Device/dtype mismatch:
Creating ones on CPU while points is on GPU, or using different dtypes; always match device and dtype.
Incorrect point layout:
Some APIs store as (2, N) instead of (N, 2). Ensure you know whether points are stored as rows or columns and adjust matmul accordingly.