From 9c5c211f0c433556a103179b53f58c00606de33c Mon Sep 17 00:00:00 2001 From: Anguelos Date: Thu, 5 Apr 2018 04:03:14 +0200 Subject: [PATCH 1/5] Made transorms.RandomCrop tolerate images smaller than the given size. --- torchvision/transforms/transforms.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 8385b04df10..fe9cb8edc81 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -368,14 +368,17 @@ class RandomCrop(object): of the image. Default is 0, i.e no padding. If a sequence of length 4 is provided, it is used to pad left, top, right, bottom borders respectively. + pad_if_needed (boolean): It will pad the image if smaller than the + desired size to avoid raising an exception. """ - def __init__(self, size, padding=0): + def __init__(self, size, padding=0, pad_if_needed=False): if isinstance(size, numbers.Number): self.size = (int(size), int(size)) else: self.size = size self.padding = padding + self.pad_if_needed = pad_if_needed @staticmethod def get_params(img, output_size): @@ -408,6 +411,11 @@ def __call__(self, img): if self.padding > 0: img = F.pad(img, self.padding) + if self.pad_if_needed and img.size[0] < self.size[0]: + img = F.pad(img, int((self.size[0] - img.size[0]) / 2), 0) + if self.pad_if_needed and img.size[1] < self.size[1]: + img = F.pad(img,(0, int((self.size[1] - img.size[1]) / 2))) + i, j, h, w = self.get_params(img, self.size) return F.crop(img, i, j, h, w) From d147464ce4e8f2b1e8dda6ddd6b40b8c07d5ecfc Mon Sep 17 00:00:00 2001 From: Anguelos Date: Thu, 5 Apr 2018 04:19:42 +0200 Subject: [PATCH 2/5] Extended the tescase for transforms.RandomCrop --- test/test_transforms.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/test_transforms.py b/test/test_transforms.py index b3d55ae6b57..545831ac9f1 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -205,6 +205,16 @@ def test_random_crop(self): assert result.size(2) == width assert np.allclose(img.numpy(), result.numpy()) + lheight = height + 5 + lwidth = width + 5 + result = transforms.Compose([ + transforms.ToPILImage(), + transforms.RandomCrop((lheight, lwidth), pad_if_needed=True), + transforms.ToTensor(), + ])(img) + assert result.size(1) == lheight + assert result.size(2) == lwidth + def test_pad(self): height = random.randint(10, 32) * 2 width = random.randint(10, 32) * 2 From c47c5b8be64f783fedaab7b86c94d7187409c783 Mon Sep 17 00:00:00 2001 From: Anguelos Date: Thu, 5 Apr 2018 04:26:31 +0200 Subject: [PATCH 3/5] Made the testcase test for owidth=width+1 --- test/test_transforms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_transforms.py b/test/test_transforms.py index 545831ac9f1..8bea19383dd 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -205,8 +205,8 @@ def test_random_crop(self): assert result.size(2) == width assert np.allclose(img.numpy(), result.numpy()) - lheight = height + 5 - lwidth = width + 5 + lheight = height + 1 + lwidth = width + 1 result = transforms.Compose([ transforms.ToPILImage(), transforms.RandomCrop((lheight, lwidth), pad_if_needed=True), From e5b405629a82b5f93708ee22435e5938f7de355d Mon Sep 17 00:00:00 2001 From: Anguelos Date: Thu, 5 Apr 2018 06:19:11 +0200 Subject: [PATCH 4/5] Fixed the one pixel pading and the testcase --- test/test_transforms.py | 2 +- torchvision/transforms/transforms.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/test/test_transforms.py b/test/test_transforms.py index 8bea19383dd..c42468798d4 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -1174,4 +1174,4 @@ def test_random_grayscale(self): if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index fe9cb8edc81..9308564020d 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -411,10 +411,12 @@ def __call__(self, img): if self.padding > 0: img = F.pad(img, self.padding) - if self.pad_if_needed and img.size[0] < self.size[0]: - img = F.pad(img, int((self.size[0] - img.size[0]) / 2), 0) - if self.pad_if_needed and img.size[1] < self.size[1]: - img = F.pad(img,(0, int((self.size[1] - img.size[1]) / 2))) + # pad the width if needed + if self.pad_if_needed and img.size[0] < self.size[1]: + img = F.pad(img, (int((1 + self.size[1] - img.size[0]) / 2), 0)) + # pad the height if needed + if self.pad_if_needed and img.size[1] < self.size[0]: + img = F.pad(img,(0, int((1 + self.size[0] - img.size[1]) / 2))) i, j, h, w = self.get_params(img, self.size) From 33c57f43827193d7ccd77f97b9b27e98f6a74c14 Mon Sep 17 00:00:00 2001 From: Anguelos Date: Thu, 5 Apr 2018 19:03:13 +0200 Subject: [PATCH 5/5] Fixed minor lintint errors. flake8 passes. --- test/test_transforms.py | 10 ++++------ torchvision/transforms/transforms.py | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/test/test_transforms.py b/test/test_transforms.py index c42468798d4..e2232e2491b 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -205,15 +205,13 @@ def test_random_crop(self): assert result.size(2) == width assert np.allclose(img.numpy(), result.numpy()) - lheight = height + 1 - lwidth = width + 1 result = transforms.Compose([ transforms.ToPILImage(), - transforms.RandomCrop((lheight, lwidth), pad_if_needed=True), + transforms.RandomCrop((height + 1, width + 1), pad_if_needed=True), transforms.ToTensor(), ])(img) - assert result.size(1) == lheight - assert result.size(2) == lwidth + assert result.size(1) == height + 1 + assert result.size(2) == width + 1 def test_pad(self): height = random.randint(10, 32) * 2 @@ -1174,4 +1172,4 @@ def test_random_grayscale(self): if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 9308564020d..6475316074f 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -416,7 +416,7 @@ def __call__(self, img): img = F.pad(img, (int((1 + self.size[1] - img.size[0]) / 2), 0)) # pad the height if needed if self.pad_if_needed and img.size[1] < self.size[0]: - img = F.pad(img,(0, int((1 + self.size[0] - img.size[1]) / 2))) + img = F.pad(img, (0, int((1 + self.size[0] - img.size[1]) / 2))) i, j, h, w = self.get_params(img, self.size)