Skip to content

[add] A PairRandomCrop for both input and target. #221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,16 @@ integer, in which case the target will be of a square shape (size, size)
If ``padding`` is non-zero, then the image is first zero-padded on each
side with ``padding`` pixels.

``PairRandomCrop(size, padding=0)``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Crops the given PIL.Image at a random location to have a region of the
given size for both input image and its target image. size can be a
tuple (target\_height, target\_width) or an integer, in which case the
target will be of a square shape (size, size)
If ``padding`` is non-zero, then the image is first zero-padded on each
side with ``padding`` pixels.

``RandomHorizontalFlip()``
^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
45 changes: 45 additions & 0 deletions torchvision/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,51 @@ def __call__(self, img):
return img.crop((x1, y1, x1 + tw, y1 + th))


class PairRandomCrop(object):
"""Crop the given PIL.Image at a random location for both input and target.

Args:
size (sequence or int): Desired output size of the crop. If size is an
int instead of sequence like (h, w), a square crop (size, size) is
made.
padding (int or sequence, optional): Optional padding on each border
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.
"""
last_position = None

def __init__(self, size, padding=0):
if isinstance(size, numbers.Number):
self.size = (int(size), int(size))
else:
self.size = size
self.padding = padding

def __call__(self, img):
"""
Args:
img (PIL.Image): Image to be cropped.
Returns:
PIL.Image: Cropped image.
"""
if self.padding > 0:
img = ImageOps.expand(img, border=self.padding, fill=0)

w, h = img.size
th, tw = self.size
if w == tw and h == th:
return img

if self.last_position is not None:
(x1, y1), self.last_position = self.last_position, None
else:
x1 = random.randint(0, w - tw)
y1 = random.randint(0, h - th)
self.last_position = (x1, y1)
return img.crop((x1, y1, x1 + tw, y1 + th))


class RandomHorizontalFlip(object):
"""Horizontally flip the given PIL.Image randomly with a probability of 0.5."""

Expand Down