5050except ImportError :
5151 HAS_KORNIA = False
5252
53+
54+ try :
55+ import cvcuda
56+ import nvcv
57+
58+ HAS_CUDA_CV = True
59+ except ImportError :
60+ HAS_CUDA_CV = False
61+
5362from PIL import Image
5463
5564# ImageNet normalization constants
5665NORM_MEAN = [0.485 , 0.456 , 0.406 ]
5766NORM_STD = [0.229 , 0.224 , 0.225 ]
58-
67+ NORM_MEAN_CUDA_CV = cvcuda .as_tensor (torch .Tensor (NORM_MEAN ).reshape (1 , 1 , 1 , 3 ).cuda (), "NHWC" )
68+ NORM_STD_CUDA_CV = cvcuda .as_tensor (torch .Tensor (NORM_STD ).reshape (1 , 1 , 1 , 3 ).cuda (), "NHWC" )
5969
6070def torchvision_pipeline (images : torch .Tensor , target_size : int ) -> torch .Tensor :
6171 images = F .resize (
@@ -91,6 +101,25 @@ def pil_pipeline(image: Image.Image, target_size: int) -> torch.Tensor:
91101 return img
92102
93103
104+ def cudacv_pipeline (image : cvcuda .Tensor , target_size : int ) -> torch .Tensor :
105+
106+ img : cvcuda .Tensor = cvcuda .resize (
107+ image ,
108+ (image .shape [0 ], target_size , target_size , image .shape [- 1 ]), # N, H, W, C
109+ interp = cvcuda .Interp .LINEAR ,
110+ )
111+ img : cvcuda .Tensor = cvcuda .convertto (
112+ src = img ,
113+ dtype = np .float32 ,
114+ scale = 1.0 / 255.0 ,
115+ )
116+
117+ img : cvcuda .Tensor = cvcuda .normalize (
118+ img , NORM_MEAN_CUDA_CV , NORM_STD_CUDA_CV
119+ )
120+ return torch .as_tensor (img .cuda ())
121+
122+
94123def albumentations_pipeline (image : np .ndarray , target_size : int ) -> torch .Tensor :
95124 transform = A .Compose (
96125 [
@@ -125,7 +154,7 @@ def run_benchmark(args) -> Dict[str, Any]:
125154
126155 device = args .device .lower ()
127156 # Check device compatibility
128- if device == "cuda" and backend not in ["tv" , "tv-compiled" ]:
157+ if device == "cuda" and backend not in ["tv" , "tv-compiled" , "cudacv" ]:
129158 raise RuntimeError (
130159 f"CUDA device not supported for { backend } backend. Only 'tv' and 'tv-compiled' support CUDA."
131160 )
@@ -135,6 +164,8 @@ def run_benchmark(args) -> Dict[str, Any]:
135164
136165 if backend == "opencv" and not HAS_OPENCV :
137166 raise RuntimeError ("OpenCV not available. Install with: pip install opencv-python" )
167+ if backend == "cudacv" and not HAS_CUDA_CV :
168+ raise RuntimeError ("CudaCV not available. Install with: pip install cudacv" )
138169 if backend == "albumentations" and not HAS_ALBUMENTATIONS :
139170 raise RuntimeError ("Albumentations not available. Install with: pip install albumentations" )
140171 if backend == "kornia" and not HAS_KORNIA :
@@ -163,6 +194,9 @@ def run_benchmark(args) -> Dict[str, Any]:
163194 elif backend == "pil" :
164195 torch .set_num_threads (args .num_threads )
165196 pipeline = pil_pipeline
197+ elif backend == "cudacv" :
198+ torch .set_num_threads (args .num_threads )
199+ pipeline = cudacv_pipeline
166200 elif backend == "albumentations" :
167201 cv2 .setNumThreads (args .num_threads )
168202 pipeline = albumentations_pipeline
@@ -180,7 +214,7 @@ def generate_test_images():
180214 images = images .to (memory_format = torch .channels_last )
181215
182216 # Move to device for torchvision backends
183- if backend in ["tv" , "tv-compiled" ]:
217+ if backend in ["tv" , "tv-compiled" , "cudacv" ]:
184218 images = images .to (device )
185219
186220 if args .batch_size == 1 :
@@ -197,6 +231,12 @@ def generate_test_images():
197231 # Convert to PIL Image (CHW -> HWC)
198232 images = images .numpy ().transpose (1 , 2 , 0 )
199233 images = Image .fromarray (images )
234+ elif backend == "cudacv" :
235+ if images .ndim == 3 : # no batch dimension
236+ images = images .unsqueeze (0 )
237+ # Permute from NCHW to NHWC and ensure contiguity
238+ images = images .permute (0 , 2 , 3 , 1 ).contiguous ()
239+ images = cvcuda .as_tensor (images , nvcv .TensorLayout .NHWC )
200240 elif backend == "albumentations" :
201241 if args .batch_size > 1 :
202242 # TODO is that true????
@@ -243,7 +283,16 @@ def main():
243283 default = "CF" ,
244284 help = "Memory format: CL (channels_last) or CF (channels_first, i.e. contiguous)" ,
245285 )
246- all_backends = ["tv" , "tv-v1" , "tv-compiled" , "opencv" , "pil" , "albumentations" , "kornia" ]
286+ all_backends = [
287+ "tv" ,
288+ "tv-v1" ,
289+ "tv-compiled" ,
290+ "opencv" ,
291+ "pil" ,
292+ "cudacv" ,
293+ "albumentations" ,
294+ "kornia" ,
295+ ]
247296 parser .add_argument (
248297 "--backends" ,
249298 type = str ,
@@ -279,7 +328,7 @@ def main():
279328 except Exception as e :
280329 print (f"ERROR with { backend } : { e } " )
281330
282- if len (results ) > 1 :
331+ if len (results ) >= 1 :
283332 print_comparison_table (results )
284333
285334
0 commit comments