Warp Perspective
Overview
The Warp Perspective sample demonstrates GPU-accelerated perspective transform using CV-CUDA’s
warp_perspective operator. A 3×3 homography matrix maps every destination pixel back to its
source location, enabling keystone correction, bird’s-eye-view synthesis, and other projective
geometry tasks.
Usage
Basic Usage
Apply a default mild-keystone perspective transform:
python3 warp_perspective.py -i input.jpg
Custom Output Path
Save the warped result to a specific file:
python3 warp_perspective.py -i input.jpg -o cat_warp_perspective.jpg
Command-Line Arguments
Argument |
Short Form |
Default |
Description |
|---|---|---|---|
|
|
tabby_tiger_cat.jpg |
Input image file path |
|
|
cvcuda/.cache/cat_warp_perspective.jpg |
Output image file path |
Implementation
Perspective Matrix Setup
# Build a perspective matrix that applies a mild keystone / tilt effect.
# The matrix maps destination pixel (x, y) to source pixel via homogeneous
# coordinates: [x_src, y_src, w] = M @ [x_dst, y_dst, 1].
# We nudge the top-right and bottom-left corners inward so the image
# appears to recede into the distance without leaving empty regions.
src_pts = np.array(
[[0, 0], [w, 0], [w, h], [0, h]],
dtype=np.float32,
)
dst_pts = np.array(
[
[w * 0.1, h * 0.05],
[w * 0.9, h * 0.1],
[w * 0.85, h * 0.95],
[w * 0.15, h * 0.9],
],
dtype=np.float32,
)
# Use OpenCV-compatible 3x3 float32 perspective matrix expected by cvcuda.warp_perspective.
# We compute it manually via the 4-point DLT (Direct Linear Transform).
def _get_perspective_transform(src: np.ndarray, dst: np.ndarray) -> np.ndarray:
"""Compute 3x3 perspective matrix from 4 point correspondences (DLT)."""
A = []
for (sx, sy), (dx, dy) in zip(src, dst, strict=True):
A.append([-sx, -sy, -1, 0, 0, 0, dx * sx, dx * sy, dx])
A.append([0, 0, 0, -sx, -sy, -1, dy * sx, dy * sy, dy])
A_mat = np.array(A, dtype=np.float64)
_, _, Vt = np.linalg.svd(A_mat)
H = Vt[-1].reshape(3, 3)
return (H / H[2, 2]).astype(np.float32)
xform = _get_perspective_transform(dst_pts, src_pts)
Warp Perspective Call
# Build a perspective matrix that applies a mild keystone / tilt effect.
# The matrix maps destination pixel (x, y) to source pixel via homogeneous
# coordinates: [x_src, y_src, w] = M @ [x_dst, y_dst, 1].
# We nudge the top-right and bottom-left corners inward so the image
# appears to recede into the distance without leaving empty regions.
src_pts = np.array(
[[0, 0], [w, 0], [w, h], [0, h]],
dtype=np.float32,
)
dst_pts = np.array(
[
[w * 0.1, h * 0.05],
[w * 0.9, h * 0.1],
[w * 0.85, h * 0.95],
[w * 0.15, h * 0.9],
],
dtype=np.float32,
)
# Use OpenCV-compatible 3x3 float32 perspective matrix expected by cvcuda.warp_perspective.
# We compute it manually via the 4-point DLT (Direct Linear Transform).
def _get_perspective_transform(src: np.ndarray, dst: np.ndarray) -> np.ndarray:
"""Compute 3x3 perspective matrix from 4 point correspondences (DLT)."""
A = []
for (sx, sy), (dx, dy) in zip(src, dst, strict=True):
A.append([-sx, -sy, -1, 0, 0, 0, dx * sx, dx * sy, dx])
A.append([0, 0, 0, -sx, -sy, -1, dy * sx, dy * sy, dy])
A_mat = np.array(A, dtype=np.float64)
_, _, Vt = np.linalg.svd(A_mat)
H = Vt[-1].reshape(3, 3)
return (H / H[2, 2]).astype(np.float32)
xform = _get_perspective_transform(dst_pts, src_pts)
Key points:
3×3 float32 matrix:
warp_perspectiveexpects a 3×3 homography matrix, either as a nested Python list or a float32 NumPy array. The matrix relates homogeneous destination coordinates to homogeneous source coordinates.WARP_INVERSE_MAP flag: When this flag is combined with the interpolation mode the matrix is interpreted as a destination→source mapping, which is how the standard DLT construction works. Without the flag the operator inverts the matrix internally.
Border mode:
cvcuda.Border.CONSTANTfills pixels that map outside the source image with theborder_value;REPLICATEandWRAPare also supported.Batch support: Pass an
ImageBatchand a(N, 9)float32 transform tensor to apply per-image perspective matrices in a single call.
Expected Output
Original Input Image |
Output: Perspective-warped image |
CV-CUDA Operators Used
Operator |
Purpose |
|---|---|
Apply a 3×3 homography perspective transform to an image |
Common Utilities Used
read_image() - Load image as CV-CUDA tensor
write_image() - Save perspective-warped image
parse_image_args() - Parse
--input/--outputCLI arguments
See Also
Resize Operator - Simple geometric scaling
Common Utilities - Helper functions used across samples