cvcuda.tv Functional API
cvcuda.tv provides a TorchVision-style functional path for image augmentation
and preprocessing with CV-CUDA tensors. It is an alternative for pipelines that
already use CV-CUDA tensors, not a replacement for TorchVision. Its function names,
signatures, and semantics track torchvision.transforms.v2.functional where
CV-CUDA provides the required operation. TorchVision is not required to use the
functions; only cvcuda.tv.Compose needs it.
Callers chain the functions directly (see the table below) or run a TorchVision
v2 transform pipeline with cvcuda.tv.Compose (see
TorchVision pipelines).
Using the API
Access the submodule through the installed cvcuda package. The equivalent
functional chains have the same composition:
TorchVision |
|
|---|---|
import torch
from torchvision.transforms.v2 import functional as F
output = F.normalize(
F.to_dtype(F.resize(torch_image, [224, 224]), torch.float32, scale=True),
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225],
)
|
import cvcuda
import numpy as np
output = cvcuda.tv.normalize(
cvcuda.tv.to_dtype(
cvcuda.tv.resize(cvcuda_image, [224, 224]), np.float32, scale=True
),
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225],
)
|
Inputs are fixed-shape cvcuda.Tensor values with interleaved
HWC/NHWC or planar CHW/NCHW layouts. Supported dtypes and
channel counts vary by operation.
Functions also accept a CUDA torch.Tensor in CHW/NCHW order and then
return torch.Tensor. The tensor arguments of erase (v) and elastic
(displacement) may be torch.Tensor too; like torchvision, they are moved
to the image’s device, so a CPU tensor is copied. elastic takes torchvision’s
relative displacement of shape (1, H, W, 2) and adds the identity sampling
grid itself.
resize and the resize step of resized_crop use cvcuda.tvresize()
for nearest, nearest-exact, bilinear and bicubic interpolation, with or without
antialiasing. Legacy nearest maps to cvcuda.Interp.NEAREST_FLOOR; nearest-exact
maps to cvcuda.Interp.NEAREST. Resizing supports uint8, uint16, int16, float16
and float32, including two-channel tensors. A no-op resize returns the input
unchanged. PIL-only box, hamming and lanczos modes are rejected, matching
torchvision’s tensor API. resized_crop also retains the crop operator’s
input restrictions.
autocontrast on integer images returns floor((x - min) * bound / (max - min)),
which matches Pillow’s ImageOps.autocontrast. TorchVision’s tensor kernel
divides in float32 and can be one lower where that quotient is a whole number.
Operations are asynchronous. By default they use the current CV-CUDA stream;
pass stream= to select one explicitly and synchronize only before a consumer
requires completed data:
stream = cvcuda.Stream()
output = cvcuda.tv.gaussian_blur(image, 5, stream=stream)
stream.sync()
TorchVision pipelines
cvcuda.tv.Compose runs an existing torchvision.transforms.v2 pipeline on
CV-CUDA. Pass it the same list of transform objects you would pass to
v2.Compose:
import cvcuda
import torch
from torchvision.transforms import v2
pipeline = cvcuda.tv.Compose([
v2.RandomResizedCrop(224),
v2.RandomHorizontalFlip(),
v2.ColorJitter(brightness=0.4, contrast=0.4, saturation=0.4),
v2.ToDtype(torch.float32, scale=True),
v2.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
torch.manual_seed(0)
output = pipeline(image) # CUDA torch.Tensor, CHW or NCHW
When to use it
Use Compose when an augmentation or preprocessing pipeline is already written
with TorchVision v2 transform classes and the images are CUDA tensors. It keeps
the pipeline definition as it is, including random transforms and containers
such as RandomApply and RandomChoice. Random transforms draw their
parameters as v2.Compose does, so torch.manual_seed selects the same
crops, flips and factors.
Performance
Calling the cvcuda.tv functions one by one on a torch.Tensor converts the
image to a cvcuda.Tensor and back on every call. Compose converts once on
input and once on output, and passes cvcuda.Tensor intermediates between the
transforms. A pipeline made only of deterministic transforms, such as Resize,
CenterCrop, ToDtype and Normalize, runs as a direct sequence of
CV-CUDA operations.
Inputs and outputs
The input can be a cvcuda.Tensor in HWC, NHWC, CHW or NCHW
layout, or a CUDA torch.Tensor or tv_tensors.Image with 3 or 4
dimensions. The output has the same kind: a cvcuda.Tensor in the input’s
layout, a torch.Tensor, or a tv_tensors.Image, with one output per crop
after FiveCrop or TenCrop. Inputs must have non-zero strides, so call
.contiguous() on an expanded tensor first. The work runs on the current Torch
stream of the input’s device.
Supported transforms
Transforms are checked when the pipeline is built. A transform that CV-CUDA
cannot run raises TypeError at construction, at any nesting depth, rather
than falling back to TorchVision.
Category |
Transforms |
|---|---|
Supported |
|
Unsupported: run arbitrary or Torch-arithmetic code |
|
Unsupported: mix batches and labels |
|
Unsupported: bounding boxes, keypoints, videos |
|
Unsupported: PIL images or ndarrays |
|
Per-type fill and dtype dictionaries are supported and are selected by
the input’s type, including after ToImage or ToPureTensor.
User subclasses of v2.Transform that override make_params or
transform work if transform only calls
torchvision.transforms.v2.functional operations that cvcuda.tv
implements. Inside the pipeline the image has no Torch storage, so Torch
arithmetic, indexing or a freshly allocated result raises RuntimeError.
A subclass that overrides forward is rejected at construction.
See the cvcuda.tv samples for runnable examples and the TV API reference for the full operator list.