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