Source code for moviepy.video.fx.Painting
from dataclasses import dataclass
import numpy as np
from PIL import Image, ImageFilter
from moviepy.Clip import Clip
from moviepy.Effect import Effect
[docs]
@dataclass
class Painting(Effect):
"""Transforms any photo into some kind of painting.
Transforms any photo into some kind of painting. Saturation
tells at which point the colors of the result should be
flashy. ``black`` gives the amount of black lines wanted.
np_image : a numpy image
"""
saturation: float = 1.4
black: float = 0.006
[docs]
def to_painting(self, np_image, saturation=1.4, black=0.006):
"""Transforms any photo into some kind of painting.
Transforms any photo into some kind of painting. Saturation
tells at which point the colors of the result should be
flashy. ``black`` gives the amount of black lines wanted.
np_image : a numpy image
"""
image = Image.fromarray(np_image)
image = image.filter(ImageFilter.EDGE_ENHANCE_MORE)
# Convert the image to grayscale
grayscale_image = image.convert("L")
# Find the image edges
edges_image = grayscale_image.filter(ImageFilter.FIND_EDGES)
# Convert the edges image to a numpy array
edges = np.array(edges_image)
# Create the darkening effect
darkening = black * (255 * np.dstack(3 * [edges]))
# Apply the painting effect
painting = saturation * np.array(image) - darkening
# Clip the pixel values to the valid range of 0-255
painting = np.maximum(0, np.minimum(255, painting))
# Convert the pixel values to unsigned 8-bit integers
painting = painting.astype("uint8")
return painting
[docs]
def apply(self, clip: Clip) -> Clip:
"""Apply the effect to the clip."""
return clip.image_transform(
lambda im: self.to_painting(im, self.saturation, self.black)
)