Fix a couple of typos and add an illustrative test (#26941)
* fix a typo and add an illustrative test * appease black * reduce code duplication and add Annotion type back with a pending deprecation warning * remove unused code * change warning type * black formatting fix * change enum deprecation approach to support 3.8 and earlier * add stacklevel * fix black issue * fix ruff issues * fix ruff issues * move tests to own mixin * include yolos * fix black formatting issue * fix black formatting issue * use logger instead of warnings and include target version for deprecation
This commit is contained in:
@@ -21,7 +21,7 @@ import unittest
|
||||
from transformers.testing_utils import require_torch, require_vision, slow
|
||||
from transformers.utils import is_torch_available, is_vision_available
|
||||
|
||||
from ...test_image_processing_common import ImageProcessingTestMixin, prepare_image_inputs
|
||||
from ...test_image_processing_common import AnnotationFormatTestMixin, ImageProcessingTestMixin, prepare_image_inputs
|
||||
|
||||
|
||||
if is_torch_available():
|
||||
@@ -127,7 +127,7 @@ class ConditionalDetrImageProcessingTester(unittest.TestCase):
|
||||
|
||||
@require_torch
|
||||
@require_vision
|
||||
class ConditionalDetrImageProcessingTest(ImageProcessingTestMixin, unittest.TestCase):
|
||||
class ConditionalDetrImageProcessingTest(AnnotationFormatTestMixin, ImageProcessingTestMixin, unittest.TestCase):
|
||||
image_processing_class = ConditionalDetrImageProcessor if is_vision_available() else None
|
||||
|
||||
def setUp(self):
|
||||
|
||||
@@ -21,7 +21,7 @@ import unittest
|
||||
from transformers.testing_utils import require_torch, require_vision, slow
|
||||
from transformers.utils import is_torch_available, is_vision_available
|
||||
|
||||
from ...test_image_processing_common import ImageProcessingTestMixin, prepare_image_inputs
|
||||
from ...test_image_processing_common import AnnotationFormatTestMixin, ImageProcessingTestMixin, prepare_image_inputs
|
||||
|
||||
|
||||
if is_torch_available():
|
||||
@@ -127,7 +127,7 @@ class DeformableDetrImageProcessingTester(unittest.TestCase):
|
||||
|
||||
@require_torch
|
||||
@require_vision
|
||||
class DeformableDetrImageProcessingTest(ImageProcessingTestMixin, unittest.TestCase):
|
||||
class DeformableDetrImageProcessingTest(AnnotationFormatTestMixin, ImageProcessingTestMixin, unittest.TestCase):
|
||||
image_processing_class = DeformableDetrImageProcessor if is_vision_available() else None
|
||||
|
||||
def setUp(self):
|
||||
|
||||
@@ -21,7 +21,7 @@ import unittest
|
||||
from transformers.testing_utils import require_torch, require_vision, slow
|
||||
from transformers.utils import is_torch_available, is_vision_available
|
||||
|
||||
from ...test_image_processing_common import ImageProcessingTestMixin, prepare_image_inputs
|
||||
from ...test_image_processing_common import AnnotationFormatTestMixin, ImageProcessingTestMixin, prepare_image_inputs
|
||||
|
||||
|
||||
if is_torch_available():
|
||||
@@ -127,7 +127,7 @@ class DetaImageProcessingTester(unittest.TestCase):
|
||||
|
||||
@require_torch
|
||||
@require_vision
|
||||
class DetaImageProcessingTest(ImageProcessingTestMixin, unittest.TestCase):
|
||||
class DetaImageProcessingTest(AnnotationFormatTestMixin, ImageProcessingTestMixin, unittest.TestCase):
|
||||
image_processing_class = DetaImageProcessor if is_vision_available() else None
|
||||
|
||||
def setUp(self):
|
||||
|
||||
@@ -21,7 +21,7 @@ import unittest
|
||||
from transformers.testing_utils import require_torch, require_vision, slow
|
||||
from transformers.utils import is_torch_available, is_vision_available
|
||||
|
||||
from ...test_image_processing_common import ImageProcessingTestMixin, prepare_image_inputs
|
||||
from ...test_image_processing_common import AnnotationFormatTestMixin, ImageProcessingTestMixin, prepare_image_inputs
|
||||
|
||||
|
||||
if is_torch_available():
|
||||
@@ -127,7 +127,7 @@ class DetrImageProcessingTester(unittest.TestCase):
|
||||
|
||||
@require_torch
|
||||
@require_vision
|
||||
class DetrImageProcessingTest(ImageProcessingTestMixin, unittest.TestCase):
|
||||
class DetrImageProcessingTest(AnnotationFormatTestMixin, ImageProcessingTestMixin, unittest.TestCase):
|
||||
image_processing_class = DetrImageProcessor if is_vision_available() else None
|
||||
|
||||
def setUp(self):
|
||||
@@ -159,6 +159,63 @@ class DetrImageProcessingTest(ImageProcessingTestMixin, unittest.TestCase):
|
||||
self.assertEqual(image_processor.size, {"shortest_edge": 42, "longest_edge": 84})
|
||||
self.assertEqual(image_processor.do_pad, False)
|
||||
|
||||
def test_should_raise_if_annotation_format_invalid(self):
|
||||
image_processor_dict = self.image_processor_tester.prepare_image_processor_dict()
|
||||
|
||||
with open("./tests/fixtures/tests_samples/COCO/coco_annotations.txt", "r") as f:
|
||||
detection_target = json.loads(f.read())
|
||||
|
||||
annotations = {"image_id": 39769, "annotations": detection_target}
|
||||
|
||||
params = {
|
||||
"images": Image.open("./tests/fixtures/tests_samples/COCO/000000039769.png"),
|
||||
"annotations": annotations,
|
||||
"return_tensors": "pt",
|
||||
}
|
||||
|
||||
image_processor_params = {**image_processor_dict, **{"format": "_INVALID_FORMAT_"}}
|
||||
image_processor = self.image_processing_class(**image_processor_params)
|
||||
|
||||
with self.assertRaises(ValueError) as e:
|
||||
image_processor(**params)
|
||||
|
||||
self.assertTrue(str(e.exception).startswith("_INVALID_FORMAT_ is not a valid AnnotationFormat"))
|
||||
|
||||
def test_valid_coco_detection_annotations(self):
|
||||
# prepare image and target
|
||||
image = Image.open("./tests/fixtures/tests_samples/COCO/000000039769.png")
|
||||
with open("./tests/fixtures/tests_samples/COCO/coco_annotations.txt", "r") as f:
|
||||
target = json.loads(f.read())
|
||||
|
||||
params = {"image_id": 39769, "annotations": target}
|
||||
|
||||
# encode them
|
||||
image_processing = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
|
||||
|
||||
# legal encodings (single image)
|
||||
_ = image_processing(images=image, annotations=params, return_tensors="pt")
|
||||
_ = image_processing(images=image, annotations=[params], return_tensors="pt")
|
||||
|
||||
# legal encodings (batch of one image)
|
||||
_ = image_processing(images=[image], annotations=params, return_tensors="pt")
|
||||
_ = image_processing(images=[image], annotations=[params], return_tensors="pt")
|
||||
|
||||
# legal encoding (batch of more than one image)
|
||||
n = 5
|
||||
_ = image_processing(images=[image] * n, annotations=[params] * n, return_tensors="pt")
|
||||
|
||||
# example of an illegal encoding (missing the 'image_id' key)
|
||||
with self.assertRaises(ValueError) as e:
|
||||
image_processing(images=image, annotations={"annotations": target}, return_tensors="pt")
|
||||
|
||||
self.assertTrue(str(e.exception).startswith("Invalid COCO detection annotations"))
|
||||
|
||||
# example of an illegal encoding (unequal lengths of images and annotations)
|
||||
with self.assertRaises(ValueError) as e:
|
||||
image_processing(images=[image] * n, annotations=[params] * (n - 1), return_tensors="pt")
|
||||
|
||||
self.assertTrue(str(e.exception) == "The number of images (5) and annotations (4) do not match.")
|
||||
|
||||
@slow
|
||||
def test_call_pytorch_with_coco_detection_annotations(self):
|
||||
# prepare image and target
|
||||
|
||||
@@ -21,7 +21,7 @@ import unittest
|
||||
from transformers.testing_utils import require_torch, require_vision, slow
|
||||
from transformers.utils import is_torch_available, is_vision_available
|
||||
|
||||
from ...test_image_processing_common import ImageProcessingTestMixin, prepare_image_inputs
|
||||
from ...test_image_processing_common import AnnotationFormatTestMixin, ImageProcessingTestMixin, prepare_image_inputs
|
||||
|
||||
|
||||
if is_torch_available():
|
||||
@@ -127,7 +127,7 @@ class YolosImageProcessingTester(unittest.TestCase):
|
||||
|
||||
@require_torch
|
||||
@require_vision
|
||||
class YolosImageProcessingTest(ImageProcessingTestMixin, unittest.TestCase):
|
||||
class YolosImageProcessingTest(AnnotationFormatTestMixin, ImageProcessingTestMixin, unittest.TestCase):
|
||||
image_processing_class = YolosImageProcessor if is_vision_available() else None
|
||||
|
||||
def setUp(self):
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import tempfile
|
||||
|
||||
from transformers import BatchFeature
|
||||
from transformers.image_utils import AnnotationFormat, AnnotionFormat
|
||||
from transformers.testing_utils import check_json_file_has_correct_format, require_torch, require_vision
|
||||
from transformers.utils import is_torch_available, is_vision_available
|
||||
|
||||
@@ -285,3 +288,81 @@ class ImageProcessingTestMixin:
|
||||
self.assertEqual(
|
||||
tuple(encoded_images.shape), (self.image_processor_tester.batch_size, *expected_output_image_shape)
|
||||
)
|
||||
|
||||
|
||||
class AnnotationFormatTestMixin:
|
||||
# this mixin adds a test to assert that usages of the
|
||||
# to-be-deprecated `AnnotionFormat` continue to be
|
||||
# supported for the time being
|
||||
|
||||
def test_processor_can_use_legacy_annotation_format(self):
|
||||
image_processor_dict = self.image_processor_tester.prepare_image_processor_dict()
|
||||
fixtures_path = pathlib.Path(__file__).parent / "fixtures" / "tests_samples" / "COCO"
|
||||
|
||||
with open(fixtures_path / "coco_annotations.txt", "r") as f:
|
||||
detection_target = json.loads(f.read())
|
||||
|
||||
detection_annotations = {"image_id": 39769, "annotations": detection_target}
|
||||
|
||||
detection_params = {
|
||||
"images": Image.open(fixtures_path / "000000039769.png"),
|
||||
"annotations": detection_annotations,
|
||||
"return_tensors": "pt",
|
||||
}
|
||||
|
||||
with open(fixtures_path / "coco_panoptic_annotations.txt", "r") as f:
|
||||
panoptic_target = json.loads(f.read())
|
||||
|
||||
panoptic_annotations = {"file_name": "000000039769.png", "image_id": 39769, "segments_info": panoptic_target}
|
||||
|
||||
masks_path = pathlib.Path(fixtures_path / "coco_panoptic")
|
||||
|
||||
panoptic_params = {
|
||||
"images": Image.open(fixtures_path / "000000039769.png"),
|
||||
"annotations": panoptic_annotations,
|
||||
"return_tensors": "pt",
|
||||
"masks_path": masks_path,
|
||||
}
|
||||
|
||||
test_cases = [
|
||||
("coco_detection", detection_params),
|
||||
("coco_panoptic", panoptic_params),
|
||||
(AnnotionFormat.COCO_DETECTION, detection_params),
|
||||
(AnnotionFormat.COCO_PANOPTIC, panoptic_params),
|
||||
(AnnotationFormat.COCO_DETECTION, detection_params),
|
||||
(AnnotationFormat.COCO_PANOPTIC, panoptic_params),
|
||||
]
|
||||
|
||||
def _compare(a, b) -> None:
|
||||
if isinstance(a, (dict, BatchFeature)):
|
||||
self.assertEqual(a.keys(), b.keys())
|
||||
for k, v in a.items():
|
||||
_compare(v, b[k])
|
||||
elif isinstance(a, list):
|
||||
self.assertEqual(len(a), len(b))
|
||||
for idx in range(len(a)):
|
||||
_compare(a[idx], b[idx])
|
||||
elif isinstance(a, torch.Tensor):
|
||||
self.assertTrue(torch.allclose(a, b, atol=1e-3))
|
||||
elif isinstance(a, str):
|
||||
self.assertEqual(a, b)
|
||||
|
||||
for annotation_format, params in test_cases:
|
||||
with self.subTest(annotation_format):
|
||||
image_processor_params = {**image_processor_dict, **{"format": annotation_format}}
|
||||
image_processor_first = self.image_processing_class(**image_processor_params)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||
image_processor_first.save_pretrained(tmpdirname)
|
||||
image_processor_second = self.image_processing_class.from_pretrained(tmpdirname)
|
||||
|
||||
# check the 'format' key exists and that the dicts of the
|
||||
# first and second processors are equal
|
||||
self.assertIn("format", image_processor_first.to_dict().keys())
|
||||
self.assertEqual(image_processor_second.to_dict(), image_processor_first.to_dict())
|
||||
|
||||
# perform encoding using both processors and compare
|
||||
# the resulting BatchFeatures
|
||||
first_encoding = image_processor_first(**params)
|
||||
second_encoding = image_processor_second(**params)
|
||||
_compare(first_encoding, second_encoding)
|
||||
|
||||
Reference in New Issue
Block a user