From 4038fdacbb1e361f57c6cb147eafeb56126a9099 Mon Sep 17 00:00:00 2001 From: Grant Sanderson Date: Thu, 1 Feb 2018 21:56:09 -0800 Subject: [PATCH] Added BackgroundColoredVMobject --- camera/camera.py | 32 ++++++++++++++++++++++++++++--- mobject/__init__.py | 2 +- mobject/vectorized_mobject.py | 36 +++++++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/camera/camera.py b/camera/camera.py index f8c80a5c..17b2d744 100644 --- a/camera/camera.py +++ b/camera/camera.py @@ -7,7 +7,8 @@ from colour import Color import aggdraw from helpers import * -from mobject import Mobject, PMobject, VMobject, ImageMobject, Group +from mobject import Mobject, PMobject, VMobject, \ + ImageMobject, Group, BackgroundColoredVMobject class Camera(object): CONFIG = { @@ -160,13 +161,15 @@ class Camera(object): mobjects = self.get_mobjects_to_display(mobjects, **kwargs) vmobjects = [] for mobject in mobjects: - if isinstance(mobject, VMobject): + if isinstance(mobject, VMobject) and not isinstance(mobject, BackgroundColoredVMobject): vmobjects.append(mobject) elif len(vmobjects) > 0: self.display_multiple_vectorized_mobjects(vmobjects) vmobjects = [] - if isinstance(mobject, PMobject): + if isinstance(mobject, BackgroundColoredVMobject): + self.display_background_colored_vmobject(mobject) + elif isinstance(mobject, PMobject): self.display_point_cloud( mobject.points, mobject.rgbas, self.adjusted_thickness(mobject.stroke_width) @@ -250,6 +253,29 @@ class Camera(object): result += " ".join([start] + cubics + [end]) return result + def display_background_colored_vmobject(self, cvmobject): + mob_array = np.zeros( + self.pixel_array.shape, + dtype = self.pixel_array_dtype + ) + image = Image.fromarray(mob_array, mode = self.image_mode) + canvas = aggdraw.Draw(image) + self.display_vectorized(cvmobject, canvas) + canvas.flush() + cv_background = cvmobject.background_array + if not np.all(self.pixel_array.shape == cv_background): + cvmobject.resize_background_array_to_match(self.pixel_array) + cv_background = cvmobject.background_array + array = np.array( + (np.array(mob_array).astype('float')/255.)*\ + np.array(cv_background), + dtype = self.pixel_array_dtype + ) + self.pixel_array[:,:] = np.maximum( + self.pixel_array, array + ) + + def display_point_cloud(self, points, rgbas, thickness): if len(points) == 0: return diff --git a/mobject/__init__.py b/mobject/__init__.py index e87c8285..4dbeb0f9 100644 --- a/mobject/__init__.py +++ b/mobject/__init__.py @@ -6,5 +6,5 @@ __all__ = [ from mobject import Mobject, Group from point_cloud_mobject import Point, Mobject1D, Mobject2D, PMobject -from vectorized_mobject import VMobject, VGroup +from vectorized_mobject import VMobject, VGroup, BackgroundColoredVMobject from image_mobject import ImageMobject \ No newline at end of file diff --git a/mobject/vectorized_mobject.py b/mobject/vectorized_mobject.py index 634b5f18..c64851fb 100644 --- a/mobject/vectorized_mobject.py +++ b/mobject/vectorized_mobject.py @@ -427,7 +427,7 @@ class VMobject(Mobject): return self class VGroup(VMobject): - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs): if len(args) == 1 and isinstance(args[0], (tuple, list)): args = args[0] @@ -439,7 +439,6 @@ class VGroup(VMobject): VMobject.__init__(self, *packed_args, **kwargs) - class VectorizedPoint(VMobject): CONFIG = { "color" : BLACK, @@ -458,6 +457,39 @@ class VectorizedPoint(VMobject): def get_height(self): return self.artificial_height +class BackgroundColoredVMobject(VMobject): + CONFIG = { + "background_image" : "color_background", + "stroke_color" : WHITE, + "fill_color" : WHITE, + } + def __init__(self, vmobject, **kwargs): + # Note: At the moment, this does nothing to mimic + # the full family of the vmobject passed in. + VMobject.__init__(self, **kwargs) + + #Match properties of vmobject + self.points = np.array(vmobject.points) + self.set_stroke(WHITE, vmobject.get_stroke_width()) + self.set_fill(WHITE, vmobject.get_fill_opacity()) + for submob in vmobject.submobjects: + self.add(BackgroundColoredVMobject(submob, **kwargs)) + + #Initialize background array + path = get_full_raster_image_path(self.background_image) + image = Image.open(path) + self.background_array = np.array(image) + + def resize_background_array(self, new_width, new_height, mode = "RGBA"): + image = Image.fromarray(self.background_array, mode = mode) + resized_image = image.resize((new_width, new_height)) + self.background_array = np.array(resized_image) + + def resize_background_array_to_match(self, pixel_array): + height, width = pixel_array.shape[:2] + mode = "RGBA" if pixel_array.shape[2] == 4 else "RGB" + self.resize_background_array(width, height, mode) +