@@ -111,8 +111,10 @@ def _check_kernel_scripted_vs_eager(kernel, input, *args, rtol, atol, **kwargs):
111111
112112 input = input .as_subclass (torch .Tensor )
113113 with ignore_jit_no_profile_information_warning ():
114- actual = kernel_scripted (input , * args , ** kwargs )
115- expected = kernel (input , * args , ** kwargs )
114+ with freeze_rng_state ():
115+ actual = kernel_scripted (input , * args , ** kwargs )
116+ with freeze_rng_state ():
117+ expected = kernel (input , * args , ** kwargs )
116118
117119 assert_close (actual , expected , rtol = rtol , atol = atol )
118120
@@ -3238,6 +3240,78 @@ def test_functional_image_correctness(self, dimensions, kernel_size, sigma, dtyp
32383240 torch .testing .assert_close (actual , expected , rtol = 0 , atol = 1 )
32393241
32403242
3243+ class TestGaussianNoise :
3244+ @pytest .mark .parametrize (
3245+ "make_input" ,
3246+ [make_image_tensor , make_image , make_video ],
3247+ )
3248+ def test_kernel (self , make_input ):
3249+ check_kernel (
3250+ F .gaussian_noise ,
3251+ make_input (dtype = torch .float32 ),
3252+ # This cannot pass because the noise on a batch in not per-image
3253+ check_batched_vs_unbatched = False ,
3254+ )
3255+
3256+ @pytest .mark .parametrize (
3257+ "make_input" ,
3258+ [make_image_tensor , make_image , make_video ],
3259+ )
3260+ def test_functional (self , make_input ):
3261+ check_functional (F .gaussian_noise , make_input (dtype = torch .float32 ))
3262+
3263+ @pytest .mark .parametrize (
3264+ ("kernel" , "input_type" ),
3265+ [
3266+ (F .gaussian_noise , torch .Tensor ),
3267+ (F .gaussian_noise_image , tv_tensors .Image ),
3268+ (F .gaussian_noise_video , tv_tensors .Video ),
3269+ ],
3270+ )
3271+ def test_functional_signature (self , kernel , input_type ):
3272+ check_functional_kernel_signature_match (F .gaussian_noise , kernel = kernel , input_type = input_type )
3273+
3274+ @pytest .mark .parametrize (
3275+ "make_input" ,
3276+ [make_image_tensor , make_image , make_video ],
3277+ )
3278+ def test_transform (self , make_input ):
3279+ def adapter (_ , input , __ ):
3280+ # This transform doesn't support uint8 so we have to convert the auto-generated uint8 tensors to float32
3281+ # Same for PIL images
3282+ for key , value in input .items ():
3283+ if isinstance (value , torch .Tensor ) and not value .is_floating_point ():
3284+ input [key ] = value .to (torch .float32 )
3285+ if isinstance (value , PIL .Image .Image ):
3286+ input [key ] = F .pil_to_tensor (value ).to (torch .float32 )
3287+ return input
3288+
3289+ check_transform (transforms .GaussianNoise (), make_input (dtype = torch .float32 ), check_sample_input = adapter )
3290+
3291+ def test_bad_input (self ):
3292+ with pytest .raises (ValueError , match = "Gaussian Noise is not implemented for PIL images." ):
3293+ F .gaussian_noise (make_image_pil ())
3294+ with pytest .raises (ValueError , match = "Input tensor is expected to be in float dtype" ):
3295+ F .gaussian_noise (make_image (dtype = torch .uint8 ))
3296+ with pytest .raises (ValueError , match = "sigma shouldn't be negative" ):
3297+ F .gaussian_noise (make_image (dtype = torch .float32 ), sigma = - 1 )
3298+
3299+ def test_clip (self ):
3300+ img = make_image (dtype = torch .float32 )
3301+
3302+ out = F .gaussian_noise (img , mean = 100 , clip = False )
3303+ assert out .min () > 50
3304+
3305+ out = F .gaussian_noise (img , mean = 100 , clip = True )
3306+ assert (out == 1 ).all ()
3307+
3308+ out = F .gaussian_noise (img , mean = - 100 , clip = False )
3309+ assert out .min () < - 50
3310+
3311+ out = F .gaussian_noise (img , mean = - 100 , clip = True )
3312+ assert (out == 0 ).all ()
3313+
3314+
32413315class TestAutoAugmentTransforms :
32423316 # These transforms have a lot of branches in their `forward()` passes which are conditioned on random sampling.
32433317 # It's typically very hard to test the effect on some parameters without heavy mocking logic.
0 commit comments