Cleanup of ZoomedScene updates

This commit is contained in:
Grant Sanderson
2018-05-10 19:46:10 -07:00
parent 8703e2336c
commit d36a68f756
5 changed files with 20 additions and 166 deletions

View File

@ -34,12 +34,12 @@ class Camera(object):
"frame_shape": (FRAME_HEIGHT, FRAME_WIDTH), "frame_shape": (FRAME_HEIGHT, FRAME_WIDTH),
"space_center": ORIGIN, "space_center": ORIGIN,
"background_color": BLACK, "background_color": BLACK,
"background_alpha": 0, # Out of rgb_max_val
# Points in vectorized mobjects with norm greater # Points in vectorized mobjects with norm greater
# than this value will be rescaled. # than this value will be rescaled.
"max_allowable_norm": FRAME_WIDTH, "max_allowable_norm": FRAME_WIDTH,
"image_mode": "RGBA", "image_mode": "RGBA",
"n_rgb_coords": 4, "n_rgb_coords": 4,
"background_alpha": 0, # Out of rgb_max_val
"pixel_array_dtype": 'uint8', "pixel_array_dtype": 'uint8',
"use_z_coordinate_for_display_order": False, "use_z_coordinate_for_display_order": False,
# z_buff_func is only used if the flag above is set to True. # z_buff_func is only used if the flag above is set to True.

View File

@ -10,9 +10,9 @@ from utils.config_ops import digest_config
class MovingCamera(Camera): class MovingCamera(Camera):
""" """
Stays in line with the height, width and position Stays in line with the height, width and position of it's 'frame', which is a Rectangle
of a given mobject
""" """
CONFIG = { CONFIG = {
"fixed_dimension": 0, # width "fixed_dimension": 0, # width
"default_frame_stroke_color": WHITE, "default_frame_stroke_color": WHITE,
@ -21,8 +21,8 @@ class MovingCamera(Camera):
def __init__(self, frame=None, **kwargs): def __init__(self, frame=None, **kwargs):
""" """
frame is a Mobject, (should be a rectangle) determining frame is a Mobject, (should almost certainly be a rectangle)
which region of space the camera displys determining which region of space the camera displys
""" """
digest_config(self, kwargs) digest_config(self, kwargs)
if frame is None: if frame is None:

View File

@ -3,17 +3,9 @@ from __future__ import absolute_import
from camera.moving_camera import MovingCamera from camera.moving_camera import MovingCamera
from utils.iterables import list_difference_update from utils.iterables import list_difference_update
# Distinct notions of view frame vs. display frame
# For now, let's say it is the responsibility of the scene holding
# this camera to add all of the relevant image_mobjects_from_cameras,
# as well as their display_frames
class MultiCamera(MovingCamera): class MultiCamera(MovingCamera):
CONFIG = { CONFIG = {
# "lock_display_frame_dimensions_to_view_frame": True,
# "display_frame_fixed_dimension": 1, # Height
"allow_cameras_to_capture_their_own_display": False, "allow_cameras_to_capture_their_own_display": False,
} }
@ -31,11 +23,7 @@ class MultiCamera(MovingCamera):
self.image_mobjects_from_cameras.append(imfc) self.image_mobjects_from_cameras.append(imfc)
def update_sub_cameras(self): def update_sub_cameras(self):
# if self.lock_display_frame_dimensions_to_view_frame: """ Reshape sub_camera pixel_arrays """
# for imfc in self.image_mobjects_from_cameras:
# aspect_ratio = imfc.view_frame.get_width() / imfc.view_frame.get_height()
# Reshape sub_camera pixel_arrays
for imfc in self.image_mobjects_from_cameras: for imfc in self.image_mobjects_from_cameras:
frame_height, frame_width = self.frame_shape frame_height, frame_width = self.frame_shape
pixel_height, pixel_width = self.get_pixel_array().shape[:2] pixel_height, pixel_width = self.get_pixel_array().shape[:2]
@ -55,7 +43,6 @@ class MultiCamera(MovingCamera):
return self return self
def capture_mobjects(self, mobjects, **kwargs): def capture_mobjects(self, mobjects, **kwargs):
# Make sure all frames are in mobjects? Or not?
self.update_sub_cameras() self.update_sub_cameras()
for imfc in self.image_mobjects_from_cameras: for imfc in self.image_mobjects_from_cameras:
to_add = list(mobjects) to_add = list(mobjects)

View File

@ -19,11 +19,7 @@ class AbstractImageMobject(Mobject):
Automatically filters out black pixels Automatically filters out black pixels
""" """
CONFIG = { CONFIG = {
"filter_color": "black",
"invert": False,
# "use_cache" : True,
"height": 2.0, "height": 2.0,
"image_mode": "RGBA",
"pixel_array_dtype": "uint8", "pixel_array_dtype": "uint8",
} }
@ -31,12 +27,11 @@ class AbstractImageMobject(Mobject):
raise Exception("Not implemented") raise Exception("Not implemented")
def set_color(self): def set_color(self):
# Likely to be implemented in subclasses # Likely to be implemented in subclasses, but no obgligation
pass pass
def init_points(self): def init_points(self):
# Corresponding corners of image are fixed to these # Corresponding corners of image are fixed to these 3 points
# Three points
self.points = np.array([ self.points = np.array([
UP + LEFT, UP + LEFT,
UP + RIGHT, UP + RIGHT,
@ -52,16 +47,9 @@ class AbstractImageMobject(Mobject):
class ImageMobject(AbstractImageMobject): class ImageMobject(AbstractImageMobject):
"""
Automatically filters out black pixels
"""
CONFIG = { CONFIG = {
"filter_color": "black",
"invert": False, "invert": False,
# "use_cache" : True,
"height": 2.0,
"image_mode": "RGBA", "image_mode": "RGBA",
"pixel_array_dtype": "uint8",
} }
def __init__(self, filename_or_array, **kwargs): def __init__(self, filename_or_array, **kwargs):
@ -118,6 +106,10 @@ class ImageMobject(AbstractImageMobject):
mobject1.pixel_array, mobject2.pixel_array, alpha mobject1.pixel_array, mobject2.pixel_array, alpha
).astype(self.pixel_array_dtype) ).astype(self.pixel_array_dtype)
# TODO, add the ability to have the dimensions/orientation of this
# mobject more strongly tied to the frame of the camera it contains,
# in the case where that's a MovingCamera
class ImageMobjectFromCamera(AbstractImageMobject): class ImageMobjectFromCamera(AbstractImageMobject):
CONFIG = { CONFIG = {

View File

@ -1,17 +1,16 @@
from __future__ import absolute_import from __future__ import absolute_import
import numpy as np
from scene.scene import Scene from scene.scene import Scene
from animation.creation import FadeIn
from camera.moving_camera import MovingCamera from camera.moving_camera import MovingCamera
from camera.multi_camera import MultiCamera from camera.multi_camera import MultiCamera
from mobject.geometry import Rectangle
from mobject.types.image_mobject import ImageMobjectFromCamera from mobject.types.image_mobject import ImageMobjectFromCamera
from constants import * from constants import *
# Note, any scenes from old videos using ZoomedScene will almost certainly
# break, as it was restructured.
class ZoomedScene(Scene): class ZoomedScene(Scene):
CONFIG = { CONFIG = {
"camera_class": MultiCamera, "camera_class": MultiCamera,
@ -56,9 +55,10 @@ class ZoomedScene(Scene):
self.zoomed_display = zoomed_display self.zoomed_display = zoomed_display
def activate_zooming(self, animate=False, run_times=[2, 1]): def activate_zooming(self, animate=False, run_times=[2, 1]):
self.zoom_activated = True
zoomed_camera = self.zoomed_camera zoomed_camera = self.zoomed_camera
zoomed_display = self.zoomed_display zoomed_display = self.zoomed_display
self.zoom_activated = True
self.camera.add_image_mobject_from_camera(zoomed_display) self.camera.add_image_mobject_from_camera(zoomed_display)
to_add = [zoomed_camera.frame, zoomed_display] to_add = [zoomed_camera.frame, zoomed_display]
@ -84,132 +84,7 @@ class ZoomedScene(Scene):
zoomed_mobjects = [self.zoomed_camera.frame, self.zoomed_display] zoomed_mobjects = [self.zoomed_camera.frame, self.zoomed_display]
moving_zoomed_mobjects = set(moving_mobjects).intersection(zoomed_mobjects) moving_zoomed_mobjects = set(moving_mobjects).intersection(zoomed_mobjects)
if self.zoom_activated and moving_zoomed_mobjects: if self.zoom_activated and moving_zoomed_mobjects:
# If either of the zoomed_mobjects are moving, then so is
# everything
return self.mobjects return self.mobjects
else: return moving_mobjects
return moving_mobjects
class OldZoomedScene(Scene):
"""
Move around self.little_rectangle to determine
which part of the screen is zoomed in on.
"""
CONFIG = {
"zoomed_canvas_frame_shape": (3, 3),
"zoomed_canvas_center": None,
"zoomed_canvas_corner": UP + RIGHT,
"zoomed_canvas_corner_buff": DEFAULT_MOBJECT_TO_EDGE_BUFFER,
"zoomed_camera_background": None,
"little_rectangle_start_position": ORIGIN,
"zoom_factor": 6,
"square_color": WHITE,
"zoom_activated": False,
}
def activate_zooming(self):
self.generate_big_rectangle()
self.setup_zoomed_canvas()
self.setup_zoomed_camera()
self.zoom_activated = True
def animate_activate_zooming(self):
self.activate_zooming()
self.play(*map(FadeIn, [
self.little_rectangle, self.big_rectangle
]))
def disactivate_zooming(self):
self.remove(self.big_rectangle, self.little_rectangle)
self.zoom_activated = False
def get_zoomed_camera_mobject(self):
return self.little_rectangle
def get_zoomed_screen(self):
return self.big_rectangle
def generate_big_rectangle(self):
height, width = self.zoomed_canvas_frame_shape
self.big_rectangle = Rectangle(
height=height,
width=width,
color=self.square_color
)
if self.zoomed_canvas_center is not None:
self.big_rectangle.shift(self.zoomed_canvas_center)
elif self.zoomed_canvas_corner is not None:
self.big_rectangle.to_corner(
self.zoomed_canvas_corner,
buff=self.zoomed_canvas_corner_buff
)
self.add(self.big_rectangle)
def setup_zoomed_canvas(self):
upper_left = self.big_rectangle.get_corner(UP + LEFT)
lower_right = self.big_rectangle.get_corner(DOWN + RIGHT)
pixel_coords = self.camera.points_to_pixel_coords(
np.array([upper_left, lower_right])
)
self.zoomed_canvas_pixel_indices = pixel_coords
(up, left), (down, right) = pixel_coords
self.zoomed_canvas_pixel_shape = (
right - left,
down - up,
)
def setup_zoomed_camera(self):
self.little_rectangle = self.big_rectangle.copy()
self.little_rectangle.scale(1. / self.zoom_factor)
self.little_rectangle.move_to(
self.little_rectangle_start_position
)
self.zoomed_camera = MovingCamera(
self.little_rectangle,
pixel_shape=self.zoomed_canvas_pixel_shape,
background=self.zoomed_camera_background
)
self.add(self.little_rectangle)
# TODO, is there a better way to hanld this?
self.zoomed_camera.adjusted_thickness = lambda x: x
def get_frame(self):
frame = Scene.get_frame(self)
if self.zoom_activated:
(up, left), (down, right) = self.zoomed_canvas_pixel_indices
frame[left:right, up:down, :] = self.zoomed_camera.get_image()
return frame
def set_camera_pixel_array(self, pixel_array):
self.camera.set_pixel_array(pixel_array)
if self.zoom_activated:
(up, left), (down, right) = self.zoomed_canvas_pixel_indices
self.zoomed_camera.set_pixel_array(
pixel_array[left:right, up:down])
def set_camera_background(self, background):
self.set_camera_pixel_array(self, background)
# TODO, check this...
def reset_camera(self):
self.camera.reset()
if self.zoom_activated:
self.zoomed_camera.reset()
def capture_mobjects_in_camera(self, mobjects, **kwargs):
self.camera.capture_mobjects(mobjects, **kwargs)
if self.zoom_activated:
if self.big_rectangle in mobjects:
mobjects = list(mobjects)
mobjects.remove(self.big_rectangle)
self.zoomed_camera.capture_mobjects(
mobjects, **kwargs
)
def get_moving_mobjects(self, *animations):
moving_mobjects = Scene.get_moving_mobjects(self, *animations)
if self.zoom_activated and self.little_rectangle in moving_mobjects:
# When the camera is moving, so is everything,
return self.mobjects
else:
return moving_mobjects