11import functools
22import itertools
33import math
4+ import os
45
56import numpy as np
67import pytest
@@ -495,6 +496,7 @@ def center_crop_bounding_box():
495496 )
496497
497498
499+ @register_kernel_info_from_sample_inputs_fn
498500def center_crop_segmentation_mask ():
499501 for mask , output_size in itertools .product (
500502 make_segmentation_masks (image_sizes = ((16 , 16 ), (7 , 33 ), (31 , 9 ))),
@@ -503,6 +505,16 @@ def center_crop_segmentation_mask():
503505 yield SampleInput (mask , output_size )
504506
505507
508+ @register_kernel_info_from_sample_inputs_fn
509+ def gaussian_blur_image_tensor ():
510+ for image , kernel_size , sigma in itertools .product (
511+ make_images (extra_dims = ((4 ,),)),
512+ [[3 , 3 ]],
513+ [None , [3.0 , 3.0 ]],
514+ ):
515+ yield SampleInput (image , kernel_size = kernel_size , sigma = sigma )
516+
517+
506518@pytest .mark .parametrize (
507519 "kernel" ,
508520 [
@@ -1555,3 +1567,58 @@ def _compute_expected_segmentation_mask(mask, output_size):
15551567
15561568 expected = _compute_expected_segmentation_mask (mask , output_size )
15571569 torch .testing .assert_close (expected , actual )
1570+
1571+
1572+ # Copied from test/test_functional_tensor.py
1573+ @pytest .mark .parametrize ("device" , cpu_and_gpu ())
1574+ @pytest .mark .parametrize ("image_size" , ("small" , "large" ))
1575+ @pytest .mark .parametrize ("dt" , [None , torch .float32 , torch .float64 , torch .float16 ])
1576+ @pytest .mark .parametrize ("ksize" , [(3 , 3 ), [3 , 5 ], (23 , 23 )])
1577+ @pytest .mark .parametrize ("sigma" , [[0.5 , 0.5 ], (0.5 , 0.5 ), (0.8 , 0.8 ), (1.7 , 1.7 )])
1578+ def test_correctness_gaussian_blur_image_tensor (device , image_size , dt , ksize , sigma ):
1579+ fn = F .gaussian_blur_image_tensor
1580+
1581+ # true_cv2_results = {
1582+ # # np_img = np.arange(3 * 10 * 12, dtype="uint8").reshape((10, 12, 3))
1583+ # # cv2.GaussianBlur(np_img, ksize=(3, 3), sigmaX=0.8)
1584+ # "3_3_0.8": ...
1585+ # # cv2.GaussianBlur(np_img, ksize=(3, 3), sigmaX=0.5)
1586+ # "3_3_0.5": ...
1587+ # # cv2.GaussianBlur(np_img, ksize=(3, 5), sigmaX=0.8)
1588+ # "3_5_0.8": ...
1589+ # # cv2.GaussianBlur(np_img, ksize=(3, 5), sigmaX=0.5)
1590+ # "3_5_0.5": ...
1591+ # # np_img2 = np.arange(26 * 28, dtype="uint8").reshape((26, 28))
1592+ # # cv2.GaussianBlur(np_img2, ksize=(23, 23), sigmaX=1.7)
1593+ # "23_23_1.7": ...
1594+ # }
1595+ p = os .path .join (os .path .dirname (os .path .abspath (__file__ )), "assets" , "gaussian_blur_opencv_results.pt" )
1596+ true_cv2_results = torch .load (p )
1597+
1598+ if image_size == "small" :
1599+ tensor = (
1600+ torch .from_numpy (np .arange (3 * 10 * 12 , dtype = "uint8" ).reshape ((10 , 12 , 3 ))).permute (2 , 0 , 1 ).to (device )
1601+ )
1602+ else :
1603+ tensor = torch .from_numpy (np .arange (26 * 28 , dtype = "uint8" ).reshape ((1 , 26 , 28 ))).to (device )
1604+
1605+ if dt == torch .float16 and device == "cpu" :
1606+ # skip float16 on CPU case
1607+ return
1608+
1609+ if dt is not None :
1610+ tensor = tensor .to (dtype = dt )
1611+
1612+ _ksize = (ksize , ksize ) if isinstance (ksize , int ) else ksize
1613+ _sigma = sigma [0 ] if sigma is not None else None
1614+ shape = tensor .shape
1615+ gt_key = f"{ shape [- 2 ]} _{ shape [- 1 ]} _{ shape [- 3 ]} __{ _ksize [0 ]} _{ _ksize [1 ]} _{ _sigma } "
1616+ if gt_key not in true_cv2_results :
1617+ return
1618+
1619+ true_out = (
1620+ torch .tensor (true_cv2_results [gt_key ]).reshape (shape [- 2 ], shape [- 1 ], shape [- 3 ]).permute (2 , 0 , 1 ).to (tensor )
1621+ )
1622+
1623+ out = fn (tensor , kernel_size = ksize , sigma = sigma )
1624+ torch .testing .assert_close (out , true_out , rtol = 0.0 , atol = 1.0 , msg = f"{ ksize } , { sigma } " )
0 commit comments