"...text-generation-inference.git" did not exist on "e415b690a68d7a0e149c996e46def41c867ff421"
Commit 69dac5b5 authored by Sam Tsai's avatar Sam Tsai Committed by Facebook GitHub Bot
Browse files

fix affine augmentation coordinate warping

Summary:
Pull Request resolved: https://github.com/facebookresearch/d2go/pull/410

1. Fix bounding box coordinate warping
2. Add apply_segmentation warning (will followup in another fix)

Reviewed By: wat3rBro

Differential Revision: D41013775

fbshipit-source-id: 3652b04c1622fe35fa9893dc22350f7d59b37c6e
parent 42ac339f
...@@ -60,6 +60,9 @@ class AffineTransform(Transform): ...@@ -60,6 +60,9 @@ class AffineTransform(Transform):
coords = (M @ coords)[:2, :].T coords = (M @ coords)[:2, :].T
return coords return coords
def apply_segmentation(self, img: np.ndarray) -> np.ndarray:
raise NotImplementedError()
class RandomPivotScaling(TransformGen): class RandomPivotScaling(TransformGen):
""" """
...@@ -211,6 +214,7 @@ class RandomAffine(TransformGen): ...@@ -211,6 +214,7 @@ class RandomAffine(TransformGen):
center, angle, translation, scale, shear center, angle, translation, scale, shear
) )
M_inv = np.array(M_inv).reshape((2, 3)) M_inv = np.array(M_inv).reshape((2, 3))
M_inv = np.vstack([M_inv, [0.0, 0.0, 1.0]])
return AffineTransform( return AffineTransform(
M_inv, M_inv,
......
...@@ -10,7 +10,7 @@ import numpy as np ...@@ -10,7 +10,7 @@ import numpy as np
import torchvision.transforms as T import torchvision.transforms as T
from d2go.data.transforms.build import build_transform_gen from d2go.data.transforms.build import build_transform_gen
from d2go.runner import Detectron2GoRunner from d2go.runner import Detectron2GoRunner
from detectron2.data.transforms import apply_augmentations from detectron2.data.transforms import apply_augmentations, AugInput
def generate_test_data( def generate_test_data(
...@@ -78,7 +78,6 @@ def generate_test_data( ...@@ -78,7 +78,6 @@ def generate_test_data(
center, angle, translation_t, scale, [shear, shear] center, angle, translation_t, scale, [shear, shear]
) )
M_inv = np.array(M_inv).reshape((2, 3)) M_inv = np.array(M_inv).reshape((2, 3))
exp_out_img = cv2.warpAffine( exp_out_img = cv2.warpAffine(
source_img, source_img,
M_inv, M_inv,
...@@ -87,14 +86,39 @@ def generate_test_data( ...@@ -87,14 +86,39 @@ def generate_test_data(
borderMode=cv2.BORDER_REPLICATE, borderMode=cv2.BORDER_REPLICATE,
) )
return aug_str, exp_out_img # Create test boxes
M_inv = np.vstack([M_inv, [0.0, 0.0, 1.0]])
test_bbox = [0.25 * img_w, 0.25 * img_h, 0.75 * img_h, 0.75 * img_h]
points = np.array(
[
[test_bbox[0], test_bbox[0], test_bbox[2], test_bbox[2]],
[test_bbox[1], test_bbox[3], test_bbox[1], test_bbox[3]],
]
).T
_xp = warp_points(points, M_inv)
out_bbox = [min(_xp[:, 0]), min(_xp[:, 1]), max(_xp[:, 0]), max(_xp[:, 1])]
return aug_str, AugInput(source_img, boxes=[test_bbox]), (exp_out_img, [out_bbox])
def warp_points(coords: np.array, xfm_M: np.array):
coords = coords.T
ones = np.ones((1, coords.shape[1]))
coords = np.vstack((coords, ones))
M = np.linalg.inv(xfm_M)
coords = (M @ coords)[:2, :].T
return coords
class TestDataTransformsAffine(unittest.TestCase): class TestDataTransformsAffine(unittest.TestCase):
def _check_array_close(self, test_output, exp_output): def _check_array_close(self, aug_output, exp_img, exp_bboxes):
self.assertTrue(
np.allclose(exp_img, aug_output.image),
f"Augmented image not the same, expecting\n{exp_img[:,:,0]} \n got\n{aug_output.image[:,:,0]} ",
)
self.assertTrue( self.assertTrue(
np.allclose(exp_output, test_output), np.allclose(exp_bboxes, aug_output.boxes, atol=0.000001),
f"Augmented image not the same, expecting\n{exp_output[:,:,0]} \n got\n{test_output[:,:,0]} ", f"Augmented bbox not the same, expecting\n{exp_img[:,:,0]} \n got\n{aug_output.image[:,:,0]} ",
) )
def test_affine_transforms_angle(self): def test_affine_transforms_angle(self):
...@@ -105,13 +129,15 @@ class TestDataTransformsAffine(unittest.TestCase): ...@@ -105,13 +129,15 @@ class TestDataTransformsAffine(unittest.TestCase):
img[((img_sz + 1) // 2) - 1, :, :] = 255 img[((img_sz + 1) // 2) - 1, :, :] = 255
for angle in [45, 90]: for angle in [45, 90]:
aug_str, exp_out_img = generate_test_data(img, angle=angle) aug_str, aug_input, (exp_out_img, exp_out_bboxes) = generate_test_data(
img, angle=angle
)
default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str] default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str]
tfm = build_transform_gen(default_cfg, is_train=True) tfm = build_transform_gen(default_cfg, is_train=True)
trans_img, _ = apply_augmentations(tfm, img)
self._check_array_close(trans_img, exp_out_img) # Test augmentation
aug_output, _ = apply_augmentations(tfm, aug_input)
self._check_array_close(aug_output, exp_out_img, exp_out_bboxes)
def test_affine_transforms_translation(self): def test_affine_transforms_translation(self):
default_cfg = Detectron2GoRunner.get_default_cfg() default_cfg = Detectron2GoRunner.get_default_cfg()
...@@ -121,13 +147,16 @@ class TestDataTransformsAffine(unittest.TestCase): ...@@ -121,13 +147,16 @@ class TestDataTransformsAffine(unittest.TestCase):
img[((img_sz + 1) // 2) - 1, :, :] = 255 img[((img_sz + 1) // 2) - 1, :, :] = 255
for translation in [0, 1, 2]: for translation in [0, 1, 2]:
aug_str, exp_out_img = generate_test_data(img, translation=translation) # Test image
aug_str, aug_input, (exp_out_img, exp_out_bboxes) = generate_test_data(
img, translation=translation
)
default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str] default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str]
tfm = build_transform_gen(default_cfg, is_train=True) tfm = build_transform_gen(default_cfg, is_train=True)
trans_img, _ = apply_augmentations(tfm, img)
self._check_array_close(trans_img, exp_out_img) # Test augmentation
aug_output, _ = apply_augmentations(tfm, aug_input)
self._check_array_close(aug_output, exp_out_img, exp_out_bboxes)
def test_affine_transforms_shear(self): def test_affine_transforms_shear(self):
default_cfg = Detectron2GoRunner.get_default_cfg() default_cfg = Detectron2GoRunner.get_default_cfg()
...@@ -137,13 +166,15 @@ class TestDataTransformsAffine(unittest.TestCase): ...@@ -137,13 +166,15 @@ class TestDataTransformsAffine(unittest.TestCase):
img[((img_sz + 1) // 2) - 1, :, :] = 255 img[((img_sz + 1) // 2) - 1, :, :] = 255
for shear in [0, 1, 2]: for shear in [0, 1, 2]:
aug_str, exp_out_img = generate_test_data(img, shear=shear) aug_str, aug_input, (exp_out_img, exp_out_bboxes) = generate_test_data(
img, shear=shear
)
default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str] default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str]
tfm = build_transform_gen(default_cfg, is_train=True) tfm = build_transform_gen(default_cfg, is_train=True)
trans_img, _ = apply_augmentations(tfm, img)
self._check_array_close(trans_img, exp_out_img) # Test augmentation
aug_output, _ = apply_augmentations(tfm, aug_input)
self._check_array_close(aug_output, exp_out_img, exp_out_bboxes)
def test_affine_transforms_scale(self): def test_affine_transforms_scale(self):
default_cfg = Detectron2GoRunner.get_default_cfg() default_cfg = Detectron2GoRunner.get_default_cfg()
...@@ -153,13 +184,15 @@ class TestDataTransformsAffine(unittest.TestCase): ...@@ -153,13 +184,15 @@ class TestDataTransformsAffine(unittest.TestCase):
img[((img_sz + 1) // 2) - 1, :, :] = 255 img[((img_sz + 1) // 2) - 1, :, :] = 255
for scale in [0.9, 1, 1.1]: for scale in [0.9, 1, 1.1]:
aug_str, exp_out_img = generate_test_data(img, scale=scale) aug_str, aug_input, (exp_out_img, exp_out_bboxes) = generate_test_data(
img, scale=scale
)
default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str] default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str]
tfm = build_transform_gen(default_cfg, is_train=True) tfm = build_transform_gen(default_cfg, is_train=True)
trans_img, _ = apply_augmentations(tfm, img)
self._check_array_close(trans_img, exp_out_img) # Test augmentation
aug_output, _ = apply_augmentations(tfm, aug_input)
self._check_array_close(aug_output, exp_out_img, exp_out_bboxes)
def test_affine_transforms_angle_non_square(self): def test_affine_transforms_angle_non_square(self):
default_cfg = Detectron2GoRunner.get_default_cfg() default_cfg = Detectron2GoRunner.get_default_cfg()
...@@ -169,15 +202,15 @@ class TestDataTransformsAffine(unittest.TestCase): ...@@ -169,15 +202,15 @@ class TestDataTransformsAffine(unittest.TestCase):
img[((img_sz + 1) // 2) - 1, :, :] = 255 img[((img_sz + 1) // 2) - 1, :, :] = 255
for keep_aspect_ratio in [False, True]: for keep_aspect_ratio in [False, True]:
aug_str, exp_out_img = generate_test_data( aug_str, aug_input, (exp_out_img, exp_out_bboxes) = generate_test_data(
img, angle=45, keep_aspect_ratio=keep_aspect_ratio img, angle=45, keep_aspect_ratio=keep_aspect_ratio
) )
default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str] default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str]
tfm = build_transform_gen(default_cfg, is_train=True) tfm = build_transform_gen(default_cfg, is_train=True)
trans_img, _ = apply_augmentations(tfm, img)
self._check_array_close(trans_img, exp_out_img) # Test augmentation
aug_output, _ = apply_augmentations(tfm, aug_input)
self._check_array_close(aug_output, exp_out_img, exp_out_bboxes)
def test_affine_transforms_angle_no_fit_to_frame(self): def test_affine_transforms_angle_no_fit_to_frame(self):
default_cfg = Detectron2GoRunner.get_default_cfg() default_cfg = Detectron2GoRunner.get_default_cfg()
...@@ -186,10 +219,12 @@ class TestDataTransformsAffine(unittest.TestCase): ...@@ -186,10 +219,12 @@ class TestDataTransformsAffine(unittest.TestCase):
img = np.zeros((img_sz, img_sz, 3)).astype(np.uint8) img = np.zeros((img_sz, img_sz, 3)).astype(np.uint8)
img[((img_sz + 1) // 2) - 1, :, :] = 255 img[((img_sz + 1) // 2) - 1, :, :] = 255
aug_str, exp_out_img = generate_test_data(img, angle=45, fit_in_frame=False) aug_str, aug_input, (exp_out_img, exp_out_bboxes) = generate_test_data(
img, angle=45, fit_in_frame=False
)
default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str] default_cfg.D2GO_DATA.AUG_OPS.TRAIN = [aug_str]
tfm = build_transform_gen(default_cfg, is_train=True) tfm = build_transform_gen(default_cfg, is_train=True)
trans_img, _ = apply_augmentations(tfm, img)
self._check_array_close(trans_img, exp_out_img) # Test augmentation
aug_output, _ = apply_augmentations(tfm, aug_input)
self._check_array_close(aug_output, exp_out_img, exp_out_bboxes)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment