callum-canavan's picture
Add helpers, change to hot dog example
954caab
raw
history blame
1.86 kB
from PIL import Image
import numpy as np
import torch
import torchvision.transforms.functional as TF
from .permutations import make_inner_circle_perm
from .view_permute import PermuteView
class InnerCircleView(PermuteView):
'''
Implements an "inner circle" view, where a circle inside the image spins
but the border stays still. Inherits from `PermuteView`, which implements
the `view` and `inverse_view` functions as permutations. We just make
the correct permutation here, and implement the `make_frame` method
for animation
'''
def __init__(self):
'''
Make the correct "inner circle" permutations and pass it to the
parent class constructor.
'''
self.perm_64 = make_inner_circle_perm(im_size=64, r=24)
self.perm_256 = make_inner_circle_perm(im_size=256, r=96)
super().__init__(self.perm_64, self.perm_256)
def make_frame(self, im, t):
im_size = im.size[0]
frame_size = int(im_size * 1.5)
theta = -t * 180
# Convert to tensor
im = torch.tensor(np.array(im) / 255.).permute(2,0,1)
# Get mask of circle (TODO: assuming size 256)
coords = torch.arange(0, 256) - 127.5
xx, yy = torch.meshgrid(coords, coords)
mask = xx**2 + yy**2 < (24*4)**2
mask = torch.stack([mask]*3).float()
# Get rotate image
im_rotated = TF.rotate(im, theta)
# Composite rotated circle + border together
im = im * (1 - mask) + im_rotated * mask
# Convert back to PIL
im = Image.fromarray((np.array(im.permute(1,2,0)) * 255.).astype(np.uint8))
# Paste on to canvas
frame = Image.new('RGB', (frame_size, frame_size), (255, 255, 255))
frame.paste(im, ((frame_size - im_size) // 2, (frame_size - im_size) // 2))
return frame