File size: 1,857 Bytes
954caab |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
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
|