from manim import * import numpy as np from PIL import Image class GrayscaleImageMobject(Group): """Mobject for creating images in Manim from numpy arrays""" def __init__(self, numpy_image, height=2.3): super().__init__() self.numpy_image = numpy_image assert len(np.shape(self.numpy_image)) == 2 input_image = self.numpy_image[None, :, :] # Convert grayscale to rgb version of grayscale input_image = np.repeat(input_image, 3, axis=0) input_image = np.rollaxis(input_image, 0, start=3) self.image_mobject = ImageMobject(input_image, image_mode="RBG") self.add(self.image_mobject) self.image_mobject.set_resampling_algorithm(RESAMPLING_ALGORITHMS["nearest"]) self.image_mobject.scale_to_fit_height(height) @classmethod def from_path(cls, path, height=2.3): """Loads image from path""" image = Image.open(path) numpy_image = np.asarray(image) return cls(numpy_image, height=height) @override_animation(Create) def create(self, run_time=2): return FadeIn(self) def scale(self, scale_factor, **kwargs): """Scales the image mobject""" # super().scale(scale_factor) # height = self.height self.image_mobject.scale(scale_factor) # self.scale_to_fit_height(2) # self.apply_points_function_about_point( # lambda points: scale_factor * points, **kwargs # ) def set_opacity(self, opacity): """Set the opacity""" self.image_mobject.set_opacity(opacity) class LabeledColorImage(Group): """Labeled Color Image""" def __init__( self, image, color=RED, label="Positive", stroke_width=5, font_size=24, buff=0.2 ): super().__init__() self.image = image self.color = color self.label = label self.stroke_width = stroke_width self.font_size = font_size text = Text(label, font_size=self.font_size) text.next_to(self.image, UP, buff=buff) rectangle = SurroundingRectangle( self.image, color=color, buff=0.0, stroke_width=self.stroke_width ) self.add(text) self.add(rectangle) self.add(self.image)