Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
vision
Commits
67f3ce28
Unverified
Commit
67f3ce28
authored
Oct 05, 2023
by
Philip Meier
Committed by
GitHub
Oct 05, 2023
Browse files
cleanup legacy transforms tests (#8013)
parent
af3077e3
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
5371 additions
and
5757 deletions
+5371
-5757
test/common_utils.py
test/common_utils.py
+4
-5
test/test_transforms_v2.py
test/test_transforms_v2.py
+5361
-160
test/test_transforms_v2_consistency.py
test/test_transforms_v2_consistency.py
+3
-289
test/test_transforms_v2_functional.py
test/test_transforms_v2_functional.py
+0
-54
test/test_transforms_v2_refactored.py
test/test_transforms_v2_refactored.py
+0
-5242
test/test_transforms_v2_utils.py
test/test_transforms_v2_utils.py
+2
-2
test/transforms_v2_legacy_utils.py
test/transforms_v2_legacy_utils.py
+1
-5
No files found.
test/common_utils.py
View file @
67f3ce28
...
@@ -406,6 +406,7 @@ def make_bounding_boxes(
...
@@ -406,6 +406,7 @@ def make_bounding_boxes(
canvas_size
=
DEFAULT_SIZE
,
canvas_size
=
DEFAULT_SIZE
,
*
,
*
,
format
=
tv_tensors
.
BoundingBoxFormat
.
XYXY
,
format
=
tv_tensors
.
BoundingBoxFormat
.
XYXY
,
num_boxes
=
1
,
dtype
=
None
,
dtype
=
None
,
device
=
"cpu"
,
device
=
"cpu"
,
):
):
...
@@ -419,8 +420,7 @@ def make_bounding_boxes(
...
@@ -419,8 +420,7 @@ def make_bounding_boxes(
dtype
=
dtype
or
torch
.
float32
dtype
=
dtype
or
torch
.
float32
num_objects
=
1
h
,
w
=
[
torch
.
randint
(
1
,
s
,
(
num_boxes
,))
for
s
in
canvas_size
]
h
,
w
=
[
torch
.
randint
(
1
,
s
,
(
num_objects
,))
for
s
in
canvas_size
]
y
=
sample_position
(
h
,
canvas_size
[
0
])
y
=
sample_position
(
h
,
canvas_size
[
0
])
x
=
sample_position
(
w
,
canvas_size
[
1
])
x
=
sample_position
(
w
,
canvas_size
[
1
])
...
@@ -443,12 +443,11 @@ def make_bounding_boxes(
...
@@ -443,12 +443,11 @@ def make_bounding_boxes(
)
)
def
make_detection_mask
(
size
=
DEFAULT_SIZE
,
*
,
dtype
=
None
,
device
=
"cpu"
):
def
make_detection_mask
s
(
size
=
DEFAULT_SIZE
,
*
,
num_masks
=
1
,
dtype
=
None
,
device
=
"cpu"
):
"""Make a "detection" mask, i.e. (*, N, H, W), where each object is encoded as one of N boolean masks"""
"""Make a "detection" mask, i.e. (*, N, H, W), where each object is encoded as one of N boolean masks"""
num_objects
=
1
return
tv_tensors
.
Mask
(
return
tv_tensors
.
Mask
(
torch
.
testing
.
make_tensor
(
torch
.
testing
.
make_tensor
(
(
num_
object
s
,
*
size
),
(
num_
mask
s
,
*
size
),
low
=
0
,
low
=
0
,
high
=
2
,
high
=
2
,
dtype
=
dtype
or
torch
.
bool
,
dtype
=
dtype
or
torch
.
bool
,
...
...
test/test_transforms_v2.py
View file @
67f3ce28
This diff is collapsed.
Click to expand it.
test/test_transforms_v2_consistency.py
View file @
67f3ce28
import
importlib.machinery
import
importlib.machinery
import
importlib.util
import
importlib.util
import
inspect
import
random
import
random
import
re
from
pathlib
import
Path
from
pathlib
import
Path
import
numpy
as
np
import
pytest
import
pytest
import
torch
import
torch
import
torchvision.transforms.v2
as
v2_transforms
import
torchvision.transforms.v2
as
v2_transforms
from
common_utils
import
assert_
close
,
assert_equal
,
set_rng_seed
from
common_utils
import
assert_
equal
from
torchvision
import
transforms
as
legacy_transforms
,
tv_tensors
from
torchvision
import
tv_tensors
from
torchvision.transforms
import
functional
as
legacy_F
from
torchvision.transforms
import
functional
as
legacy_F
from
torchvision.transforms.v2
import
functional
as
prototype_F
from
torchvision.transforms.v2
import
functional
as
prototype_F
from
torchvision.transforms.v2._utils
import
_get_fill
,
query_size
from
torchvision.transforms.v2._utils
import
_get_fill
,
query_size
from
torchvision.transforms.v2.functional
import
to_pil_image
from
torchvision.transforms.v2.functional
import
to_pil_image
from
transforms_v2_legacy_utils
import
(
ArgsKwargs
,
make_bounding_boxes
,
make_detection_mask
,
make_image
,
make_images
,
make_segmentation_mask
,
)
DEFAULT_MAKE_IMAGES_KWARGS
=
dict
(
color_spaces
=
[
"RGB"
],
extra_dims
=
[(
4
,)])
@
pytest
.
fixture
(
autouse
=
True
)
def
fix_rng_seed
():
set_rng_seed
(
0
)
yield
class
NotScriptableArgsKwargs
(
ArgsKwargs
):
"""
This class is used to mark parameters that render the transform non-scriptable. They still work in eager mode and
thus will be tested there, but will be skipped by the JIT tests.
"""
pass
class
ConsistencyConfig
:
def
__init__
(
self
,
prototype_cls
,
legacy_cls
,
# If no args_kwargs is passed, only the signature will be checked
args_kwargs
=
(),
make_images_kwargs
=
None
,
supports_pil
=
True
,
removed_params
=
(),
closeness_kwargs
=
None
,
):
self
.
prototype_cls
=
prototype_cls
self
.
legacy_cls
=
legacy_cls
self
.
args_kwargs
=
args_kwargs
self
.
make_images_kwargs
=
make_images_kwargs
or
DEFAULT_MAKE_IMAGES_KWARGS
self
.
supports_pil
=
supports_pil
self
.
removed_params
=
removed_params
self
.
closeness_kwargs
=
closeness_kwargs
or
dict
(
rtol
=
0
,
atol
=
0
)
# These are here since both the prototype and legacy transform need to be constructed with the same random parameters
LINEAR_TRANSFORMATION_MEAN
=
torch
.
rand
(
36
)
LINEAR_TRANSFORMATION_MATRIX
=
torch
.
rand
([
LINEAR_TRANSFORMATION_MEAN
.
numel
()]
*
2
)
CONSISTENCY_CONFIGS
=
[]
def
check_call_consistency
(
prototype_transform
,
legacy_transform
,
images
=
None
,
supports_pil
=
True
,
closeness_kwargs
=
None
):
if
images
is
None
:
images
=
make_images
(
**
DEFAULT_MAKE_IMAGES_KWARGS
)
closeness_kwargs
=
closeness_kwargs
or
dict
()
for
image
in
images
:
image_repr
=
f
"[
{
tuple
(
image
.
shape
)
}
,
{
str
(
image
.
dtype
).
rsplit
(
'.'
)[
-
1
]
}
]"
image_tensor
=
torch
.
Tensor
(
image
)
try
:
torch
.
manual_seed
(
0
)
output_legacy_tensor
=
legacy_transform
(
image_tensor
)
except
Exception
as
exc
:
raise
pytest
.
UsageError
(
f
"Transforming a tensor image
{
image_repr
}
failed in the legacy transform with the "
f
"error above. This means that you need to specify the parameters passed to `make_images` through the "
"`make_images_kwargs` of the `ConsistencyConfig`."
)
from
exc
try
:
torch
.
manual_seed
(
0
)
output_prototype_tensor
=
prototype_transform
(
image_tensor
)
except
Exception
as
exc
:
raise
AssertionError
(
f
"Transforming a tensor image with shape
{
image_repr
}
failed in the prototype transform with "
f
"the error above. This means there is a consistency bug either in `_get_params` or in the "
f
"`is_pure_tensor` path in `_transform`."
)
from
exc
assert_close
(
output_prototype_tensor
,
output_legacy_tensor
,
msg
=
lambda
msg
:
f
"Tensor image consistency check failed with:
\n\n
{
msg
}
"
,
**
closeness_kwargs
,
)
try
:
torch
.
manual_seed
(
0
)
output_prototype_image
=
prototype_transform
(
image
)
except
Exception
as
exc
:
raise
AssertionError
(
f
"Transforming a image tv_tensor with shape
{
image_repr
}
failed in the prototype transform with "
f
"the error above. This means there is a consistency bug either in `_get_params` or in the "
f
"`tv_tensors.Image` path in `_transform`."
)
from
exc
assert_close
(
output_prototype_image
,
output_prototype_tensor
,
msg
=
lambda
msg
:
f
"Output for tv_tensor and tensor images is not equal:
\n\n
{
msg
}
"
,
**
closeness_kwargs
,
)
if
image
.
ndim
==
3
and
supports_pil
:
image_pil
=
to_pil_image
(
image
)
try
:
torch
.
manual_seed
(
0
)
output_legacy_pil
=
legacy_transform
(
image_pil
)
except
Exception
as
exc
:
raise
pytest
.
UsageError
(
f
"Transforming a PIL image with shape
{
image_repr
}
failed in the legacy transform with the "
f
"error above. If this transform does not support PIL images, set `supports_pil=False` on the "
"`ConsistencyConfig`. "
)
from
exc
try
:
torch
.
manual_seed
(
0
)
output_prototype_pil
=
prototype_transform
(
image_pil
)
except
Exception
as
exc
:
raise
AssertionError
(
f
"Transforming a PIL image with shape
{
image_repr
}
failed in the prototype transform with "
f
"the error above. This means there is a consistency bug either in `_get_params` or in the "
f
"`PIL.Image.Image` path in `_transform`."
)
from
exc
assert_close
(
output_prototype_pil
,
output_legacy_pil
,
msg
=
lambda
msg
:
f
"PIL image consistency check failed with:
\n\n
{
msg
}
"
,
**
closeness_kwargs
,
)
@
pytest
.
mark
.
parametrize
(
(
"config"
,
"args_kwargs"
),
[
pytest
.
param
(
config
,
args_kwargs
,
id
=
f
"
{
config
.
legacy_cls
.
__name__
}
-
{
idx
:
0
{
len
(
str
(
len
(
config
.
args_kwargs
)))
}
d
}
"
)
for
config
in
CONSISTENCY_CONFIGS
for
idx
,
args_kwargs
in
enumerate
(
config
.
args_kwargs
)
],
)
@
pytest
.
mark
.
filterwarnings
(
"ignore"
)
def
test_call_consistency
(
config
,
args_kwargs
):
args
,
kwargs
=
args_kwargs
try
:
legacy_transform
=
config
.
legacy_cls
(
*
args
,
**
kwargs
)
except
Exception
as
exc
:
raise
pytest
.
UsageError
(
f
"Initializing the legacy transform failed with the error above. "
f
"Please correct the `ArgsKwargs(
{
args_kwargs
}
)` in the `ConsistencyConfig`."
)
from
exc
try
:
prototype_transform
=
config
.
prototype_cls
(
*
args
,
**
kwargs
)
except
Exception
as
exc
:
raise
AssertionError
(
"Initializing the prototype transform failed with the error above. "
"This means there is a consistency bug in the constructor."
)
from
exc
check_call_consistency
(
prototype_transform
,
legacy_transform
,
images
=
make_images
(
**
config
.
make_images_kwargs
),
supports_pil
=
config
.
supports_pil
,
closeness_kwargs
=
config
.
closeness_kwargs
,
)
@
pytest
.
mark
.
parametrize
(
(
"config"
,
"args_kwargs"
),
[
pytest
.
param
(
config
,
args_kwargs
,
id
=
f
"
{
config
.
legacy_cls
.
__name__
}
-
{
idx
:
0
{
len
(
str
(
len
(
config
.
args_kwargs
)))
}
d
}
"
)
for
config
in
CONSISTENCY_CONFIGS
for
idx
,
args_kwargs
in
enumerate
(
config
.
args_kwargs
)
if
not
isinstance
(
args_kwargs
,
NotScriptableArgsKwargs
)
],
)
def
test_jit_consistency
(
config
,
args_kwargs
):
args
,
kwargs
=
args_kwargs
prototype_transform_eager
=
config
.
prototype_cls
(
*
args
,
**
kwargs
)
legacy_transform_eager
=
config
.
legacy_cls
(
*
args
,
**
kwargs
)
legacy_transform_scripted
=
torch
.
jit
.
script
(
legacy_transform_eager
)
prototype_transform_scripted
=
torch
.
jit
.
script
(
prototype_transform_eager
)
for
image
in
make_images
(
**
config
.
make_images_kwargs
):
image
=
image
.
as_subclass
(
torch
.
Tensor
)
torch
.
manual_seed
(
0
)
output_legacy_scripted
=
legacy_transform_scripted
(
image
)
torch
.
manual_seed
(
0
)
output_prototype_scripted
=
prototype_transform_scripted
(
image
)
assert_close
(
output_prototype_scripted
,
output_legacy_scripted
,
**
config
.
closeness_kwargs
)
from
transforms_v2_legacy_utils
import
make_bounding_boxes
,
make_detection_mask
,
make_image
,
make_segmentation_mask
class
TestToTensorTransforms
:
def
test_pil_to_tensor
(
self
):
prototype_transform
=
v2_transforms
.
PILToTensor
()
legacy_transform
=
legacy_transforms
.
PILToTensor
()
for
image
in
make_images
(
extra_dims
=
[()]):
image_pil
=
to_pil_image
(
image
)
assert_equal
(
prototype_transform
(
image_pil
),
legacy_transform
(
image_pil
))
def
test_to_tensor
(
self
):
with
pytest
.
warns
(
UserWarning
,
match
=
re
.
escape
(
"The transform `ToTensor()` is deprecated"
)):
prototype_transform
=
v2_transforms
.
ToTensor
()
legacy_transform
=
legacy_transforms
.
ToTensor
()
for
image
in
make_images
(
extra_dims
=
[()]):
image_pil
=
to_pil_image
(
image
)
image_numpy
=
np
.
array
(
image_pil
)
assert_equal
(
prototype_transform
(
image_pil
),
legacy_transform
(
image_pil
))
assert_equal
(
prototype_transform
(
image_numpy
),
legacy_transform
(
image_numpy
))
def
import_transforms_from_references
(
reference
):
def
import_transforms_from_references
(
reference
):
...
@@ -447,54 +212,3 @@ class TestRefSegTransforms:
...
@@ -447,54 +212,3 @@ class TestRefSegTransforms:
)
)
def
test_common
(
self
,
t_ref
,
t
,
data_kwargs
):
def
test_common
(
self
,
t_ref
,
t
,
data_kwargs
):
self
.
check
(
t
,
t_ref
,
data_kwargs
)
self
.
check
(
t
,
t_ref
,
data_kwargs
)
@
pytest
.
mark
.
parametrize
(
(
"legacy_dispatcher"
,
"name_only_params"
),
[
(
legacy_F
.
get_dimensions
,
{}),
(
legacy_F
.
get_image_size
,
{}),
(
legacy_F
.
get_image_num_channels
,
{}),
(
legacy_F
.
to_tensor
,
{}),
(
legacy_F
.
pil_to_tensor
,
{}),
(
legacy_F
.
convert_image_dtype
,
{}),
(
legacy_F
.
to_pil_image
,
{}),
(
legacy_F
.
to_grayscale
,
{}),
(
legacy_F
.
rgb_to_grayscale
,
{}),
(
legacy_F
.
to_tensor
,
{}),
],
)
def
test_dispatcher_signature_consistency
(
legacy_dispatcher
,
name_only_params
):
legacy_signature
=
inspect
.
signature
(
legacy_dispatcher
)
legacy_params
=
list
(
legacy_signature
.
parameters
.
values
())[
1
:]
try
:
prototype_dispatcher
=
getattr
(
prototype_F
,
legacy_dispatcher
.
__name__
)
except
AttributeError
:
raise
AssertionError
(
f
"Legacy dispatcher `F.
{
legacy_dispatcher
.
__name__
}
` has no prototype equivalent"
)
from
None
prototype_signature
=
inspect
.
signature
(
prototype_dispatcher
)
prototype_params
=
list
(
prototype_signature
.
parameters
.
values
())[
1
:]
# Some dispatchers got extra parameters. This makes sure they have a default argument and thus are BC. We don't
# need to check if parameters were added in the middle rather than at the end, since that will be caught by the
# regular check below.
prototype_params
,
new_prototype_params
=
(
prototype_params
[:
len
(
legacy_params
)],
prototype_params
[
len
(
legacy_params
)
:],
)
for
param
in
new_prototype_params
:
assert
param
.
default
is
not
param
.
empty
# Some annotations were changed mostly to supersets of what was there before. Plus, some legacy dispatchers had no
# annotations. In these cases we simply drop the annotation and default argument from the comparison
for
prototype_param
,
legacy_param
in
zip
(
prototype_params
,
legacy_params
):
if
legacy_param
.
name
in
name_only_params
:
prototype_param
.
_annotation
=
prototype_param
.
_default
=
inspect
.
Parameter
.
empty
legacy_param
.
_annotation
=
legacy_param
.
_default
=
inspect
.
Parameter
.
empty
elif
legacy_param
.
annotation
is
inspect
.
Parameter
.
empty
:
prototype_param
.
_annotation
=
inspect
.
Parameter
.
empty
assert
prototype_params
==
legacy_params
test/test_transforms_v2_functional.py
deleted
100644 → 0
View file @
af3077e3
import
numpy
as
np
import
PIL.Image
import
pytest
import
torch
from
torchvision.transforms.v2
import
functional
as
F
@
pytest
.
mark
.
parametrize
(
(
"alias"
,
"target"
),
[
pytest
.
param
(
alias
,
target
,
id
=
alias
.
__name__
)
for
alias
,
target
in
[
(
F
.
hflip
,
F
.
horizontal_flip
),
(
F
.
vflip
,
F
.
vertical_flip
),
(
F
.
get_image_num_channels
,
F
.
get_num_channels
),
(
F
.
to_pil_image
,
F
.
to_pil_image
),
(
F
.
elastic_transform
,
F
.
elastic
),
(
F
.
to_grayscale
,
F
.
rgb_to_grayscale
),
]
],
)
def
test_alias
(
alias
,
target
):
assert
alias
is
target
@
pytest
.
mark
.
parametrize
(
"inpt"
,
[
127
*
np
.
ones
((
32
,
32
,
3
),
dtype
=
"uint8"
),
PIL
.
Image
.
new
(
"RGB"
,
(
32
,
32
),
122
),
],
)
def
test_to_image
(
inpt
):
output
=
F
.
to_image
(
inpt
)
assert
isinstance
(
output
,
torch
.
Tensor
)
assert
output
.
shape
==
(
3
,
32
,
32
)
assert
np
.
asarray
(
inpt
).
sum
()
==
output
.
sum
().
item
()
@
pytest
.
mark
.
parametrize
(
"inpt"
,
[
torch
.
randint
(
0
,
256
,
size
=
(
3
,
32
,
32
),
dtype
=
torch
.
uint8
),
127
*
np
.
ones
((
32
,
32
,
3
),
dtype
=
"uint8"
),
],
)
@
pytest
.
mark
.
parametrize
(
"mode"
,
[
None
,
"RGB"
])
def
test_to_pil_image
(
inpt
,
mode
):
output
=
F
.
to_pil_image
(
inpt
,
mode
=
mode
)
assert
isinstance
(
output
,
PIL
.
Image
.
Image
)
assert
np
.
asarray
(
inpt
).
sum
()
==
np
.
asarray
(
output
).
sum
()
test/test_transforms_v2_refactored.py
deleted
100644 → 0
View file @
af3077e3
This diff is collapsed.
Click to expand it.
test/test_transforms_v2_utils.py
View file @
67f3ce28
...
@@ -4,7 +4,7 @@ import pytest
...
@@ -4,7 +4,7 @@ import pytest
import
torch
import
torch
import
torchvision.transforms.v2._utils
import
torchvision.transforms.v2._utils
from
common_utils
import
DEFAULT_SIZE
,
make_bounding_boxes
,
make_detection_mask
,
make_image
from
common_utils
import
DEFAULT_SIZE
,
make_bounding_boxes
,
make_detection_mask
s
,
make_image
from
torchvision
import
tv_tensors
from
torchvision
import
tv_tensors
from
torchvision.transforms.v2._utils
import
has_all
,
has_any
from
torchvision.transforms.v2._utils
import
has_all
,
has_any
...
@@ -13,7 +13,7 @@ from torchvision.transforms.v2.functional import to_pil_image
...
@@ -13,7 +13,7 @@ from torchvision.transforms.v2.functional import to_pil_image
IMAGE
=
make_image
(
DEFAULT_SIZE
,
color_space
=
"RGB"
)
IMAGE
=
make_image
(
DEFAULT_SIZE
,
color_space
=
"RGB"
)
BOUNDING_BOX
=
make_bounding_boxes
(
DEFAULT_SIZE
,
format
=
tv_tensors
.
BoundingBoxFormat
.
XYXY
)
BOUNDING_BOX
=
make_bounding_boxes
(
DEFAULT_SIZE
,
format
=
tv_tensors
.
BoundingBoxFormat
.
XYXY
)
MASK
=
make_detection_mask
(
DEFAULT_SIZE
)
MASK
=
make_detection_mask
s
(
DEFAULT_SIZE
)
@
pytest
.
mark
.
parametrize
(
@
pytest
.
mark
.
parametrize
(
...
...
test/transforms_v2_legacy_utils.py
View file @
67f3ce28
...
@@ -5,12 +5,8 @@ implemented there and must not use any of the utilities here.
...
@@ -5,12 +5,8 @@ implemented there and must not use any of the utilities here.
The following legacy modules depend on this module
The following legacy modules depend on this module
- test_transforms_v2_functional.py
- test_transforms_v2_consistency.py
- test_transforms_v2_consistency.py
- test_transforms_v2.py
- test_prototype_transforms.py
When all the logic is ported from the files above to test_transforms_v2_refactored.py, delete
all the legacy modules including this one and drop the _refactored prefix from the name.
"""
"""
import
collections.abc
import
collections.abc
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment