13
13
"lanczos5" ,
14
14
"bicubic" ,
15
15
)
16
+ AFFINE_TRANSFORM_INTERPOLATIONS = { # map to order
17
+ "nearest" : 0 ,
18
+ "bilinear" : 1 ,
19
+ }
20
+ AFFINE_TRANSFORM_FILL_MODES = {
21
+ "constant" ,
22
+ "nearest" ,
23
+ "wrap" ,
24
+ "mirror" ,
25
+ "reflect" ,
26
+ }
27
+ MAP_COORDINATES_FILL_MODES = {
28
+ "constant" ,
29
+ "nearest" ,
30
+ "wrap" ,
31
+ "mirror" ,
32
+ "reflect" ,
33
+ }
34
+ SCALE_AND_TRANSLATE_METHODS = {
35
+ "linear" ,
36
+ "bilinear" ,
37
+ "trilinear" ,
38
+ "cubic" ,
39
+ "bicubic" ,
40
+ "tricubic" ,
41
+ "lanczos3" ,
42
+ "lanczos5" ,
43
+ }
16
44
17
45
18
46
def rgb_to_grayscale (images , data_format = None ):
@@ -367,7 +395,7 @@ def resize(
367
395
return _resize (images , size , method = interpolation , antialias = antialias )
368
396
369
397
370
- def compute_weight_mat (
398
+ def _compute_weight_mat (
371
399
input_size , output_size , scale , translation , kernel , antialias
372
400
):
373
401
dtype = np .result_type (scale , translation )
@@ -410,32 +438,11 @@ def compute_weight_mat(
410
438
411
439
412
440
def _resize (image , shape , method , antialias ):
413
- def _fill_triangle_kernel (x ):
414
- return np .maximum (0 , 1 - np .abs (x ))
415
-
416
- def _fill_keys_cubic_kernel (x ):
417
- out = ((1.5 * x - 2.5 ) * x ) * x + 1.0
418
- out = np .where (x >= 1.0 , ((- 0.5 * x + 2.5 ) * x - 4.0 ) * x + 2.0 , out )
419
- return np .where (x >= 2.0 , 0.0 , out )
420
-
421
- def _fill_lanczos_kernel (radius , x ):
422
- y = radius * np .sin (np .pi * x ) * np .sin (np .pi * x / radius )
423
- out = np .where (
424
- x > 1e-3 , np .divide (y , np .where (x != 0 , np .pi ** 2 * x ** 2 , 1 )), 1
425
- )
426
- return np .where (x > radius , 0.0 , out )
427
-
428
441
if method == "nearest" :
429
442
return _resize_nearest (image , shape )
430
- elif method == "bilinear" :
431
- kernel = _fill_triangle_kernel
432
- elif method == "lanczos3" :
433
- kernel = lambda x : _fill_lanczos_kernel (3.0 , x )
434
- elif method == "lanczos5" :
435
- kernel = lambda x : _fill_lanczos_kernel (5.0 , x )
436
- elif method == "bicubic" :
437
- kernel = _fill_keys_cubic_kernel
438
443
else :
444
+ kernel = _kernels .get (method , None )
445
+ if kernel is None :
439
446
raise ValueError ("Unknown resize method" )
440
447
441
448
spatial_dims = tuple (
@@ -473,6 +480,34 @@ def _resize_nearest(x, output_shape):
473
480
return x
474
481
475
482
483
+ def _fill_triangle_kernel (x ):
484
+ return np .maximum (0 , 1 - np .abs (x ))
485
+
486
+
487
+ def _fill_keys_cubic_kernel (x ):
488
+ out = ((1.5 * x - 2.5 ) * x ) * x + 1.0
489
+ out = np .where (x >= 1.0 , ((- 0.5 * x + 2.5 ) * x - 4.0 ) * x + 2.0 , out )
490
+ return np .where (x >= 2.0 , 0.0 , out )
491
+
492
+
493
+ def _fill_lanczos_kernel (radius , x ):
494
+ y = radius * np .sin (np .pi * x ) * np .sin (np .pi * x / radius )
495
+ out = np .where (
496
+ x > 1e-3 , np .divide (y , np .where (x != 0 , np .pi ** 2 * x ** 2 , 1 )), 1
497
+ )
498
+ return np .where (x > radius , 0.0 , out )
499
+
500
+
501
+ _kernels = {
502
+ "linear" : _fill_triangle_kernel ,
503
+ "bilinear" : _fill_triangle_kernel , # For `resize`.
504
+ "cubic" : _fill_keys_cubic_kernel ,
505
+ "bicubic" : _fill_keys_cubic_kernel , # For `resize`.
506
+ "lanczos3" : lambda x : _fill_lanczos_kernel (3.0 , x ),
507
+ "lanczos5" : lambda x : _fill_lanczos_kernel (5.0 , x ),
508
+ }
509
+
510
+
476
511
def _scale_and_translate (
477
512
x , output_shape , spatial_dims , scale , translation , kernel , antialias
478
513
):
@@ -492,9 +527,9 @@ def _scale_and_translate(
492
527
d = d % x .ndim
493
528
m , n = input_shape [d ], output_shape [d ]
494
529
495
- w = compute_weight_mat (
530
+ w = _compute_weight_mat (
496
531
m , n , scale [i ], translation [i ], kernel , antialias
497
- ).astype (np . float32 )
532
+ ).astype (output . dtype )
498
533
output = np .tensordot (output , w , axes = (d , 0 ))
499
534
output = np .moveaxis (output , - 1 , d )
500
535
@@ -504,19 +539,6 @@ def _scale_and_translate(
504
539
return output
505
540
506
541
507
- AFFINE_TRANSFORM_INTERPOLATIONS = { # map to order
508
- "nearest" : 0 ,
509
- "bilinear" : 1 ,
510
- }
511
- AFFINE_TRANSFORM_FILL_MODES = {
512
- "constant" ,
513
- "nearest" ,
514
- "wrap" ,
515
- "mirror" ,
516
- "reflect" ,
517
- }
518
-
519
-
520
542
def affine_transform (
521
543
images ,
522
544
transform ,
@@ -877,15 +899,6 @@ def compute_homography_matrix(start_points, end_points):
877
899
return homography_matrix
878
900
879
901
880
- MAP_COORDINATES_FILL_MODES = {
881
- "constant" ,
882
- "nearest" ,
883
- "wrap" ,
884
- "mirror" ,
885
- "reflect" ,
886
- }
887
-
888
-
889
902
def map_coordinates (
890
903
inputs , coordinates , order , fill_mode = "constant" , fill_value = 0.0
891
904
):
@@ -1135,3 +1148,40 @@ def elastic_transform(
1135
1148
transformed_images = transformed_images .astype (input_dtype )
1136
1149
1137
1150
return transformed_images
1151
+
1152
+
1153
+ def scale_and_translate (
1154
+ images ,
1155
+ output_shape ,
1156
+ scale ,
1157
+ translation ,
1158
+ spatial_dims ,
1159
+ method ,
1160
+ antialias = True ,
1161
+ ):
1162
+ if method not in SCALE_AND_TRANSLATE_METHODS :
1163
+ raise ValueError (
1164
+ "Invalid value for argument `method`. Expected of one "
1165
+ f"{ SCALE_AND_TRANSLATE_METHODS } . Received: method={ method } "
1166
+ )
1167
+ if method in ("linear" , "bilinear" , "trilinear" , "triangle" ):
1168
+ method = "linear"
1169
+ elif method in ("cubic" , "bicubic" , "tricubic" ):
1170
+ method = "cubic"
1171
+
1172
+ images = convert_to_tensor (images )
1173
+ scale = convert_to_tensor (scale )
1174
+ translation = convert_to_tensor (translation )
1175
+ kernel = _kernels [method ]
1176
+ dtype = backend .result_type (scale .dtype , translation .dtype )
1177
+ scale = scale .astype (dtype )
1178
+ translation = translation .astype (dtype )
1179
+ return _scale_and_translate (
1180
+ images ,
1181
+ output_shape ,
1182
+ spatial_dims ,
1183
+ scale ,
1184
+ translation ,
1185
+ kernel ,
1186
+ antialias ,
1187
+ )
0 commit comments