Add Camera Shake Effect To Images With Python

In this post, I am gonna show you how to easily add the camera-shake effect to an image with the help of Python.

This method will let tweak various aspects of this camera-shake animation such as duration of shake effect, frames per second, and intensity of shake.

Check out the final result

You can even mix and merge this image shaking effect with other effects such as zoom-in or zoom-out. Everything can be done with Python alone.

I’ll generate frames where the input image is randomly shifted by a fixed distance in a certain direction (up, down, left, or right) and then ensure it returns to the neutral position.

These frames will be compiled to create an MP4 video showing the shake effect.

Import Python libraries

import numpy as np
from PIL import Image
from moviepy.editor import ImageSequenceClip

Load image

Let’s load an image that will be used as input for the shaking effect.

# load image
image_path = 'image.jpg'
image = Image.open(image_path)
image_np = np.array(image)

Define shake effect parameters

The parameter shift_distance is the amount of movement we wish the image to move in any direction.

# Shake parameters
shift_distance = 5  # Fixed distance for the image to shift
fps = 30  # Frames per second
duration = 8  # Duration of the video in seconds

total_frames = fps * duration

A higher value of fps will result in smoother camera-shake effect. Feel free to change and play around with these parameters.

Adjust frame dimensions for output video

In the camera-shake effect the image will move in all the directions randomly. Let’s say if the image shifts towards right side, that would leave a blank space to the left of the image. Similarly, if the image moves towards the bottom, there will be a blank space to the top of the image.

camera shake effect python

These blank regions appearing due to the shifting of the image from its neutral position would make the shake effect look bad. So, I have thought about a hack to solve this problem.

For the output video, the dimensions of the frames should be kept slightly smaller than the actual dimensions of the image to provide enough margin for the image to shift back and forth.

# Calculate new frame size (smaller to avoid blank regions)
frame_width, frame_height = image.size
new_frame_width = frame_width - (2 * shift_distance)  # subtract shift_distance from both sides
new_frame_height = frame_height - (2 * shift_distance)

# Directions for shifting: [(dx, dy)]
# Top, Bottom, Left, Right shifts respectively
directions = [(-shift_distance, 0), (shift_distance, 0), (0, -shift_distance), (0, shift_distance)]

Generate video with camera-shake effect

# Generate frames
frames = []
for i in range(total_frames):
    if i % 2 == 0:
        # Randomly select a direction for shake
        dx, dy = directions[np.random.randint(0, len(directions))]
        # Create shifted frame
        shifted_image = np.roll(image_np, shift=(dy, dx), axis=(0, 1))
    else:
        # Return to neutral position
        shifted_image = image_np
    
    # Extract the smaller frame from the shifted image to avoid blank regions
    smaller_frame = shifted_image[shift_distance:-shift_distance, shift_distance:-shift_distance]
    frames.append(smaller_frame)

# Create video clip from frames
clip = ImageSequenceClip(frames, fps=fps)

# Write video file to disk
video_path = 'shaken_video.mp4'
clip.write_videofile(video_path, codec='libx264')

Leave a Reply

Your email address will not be published. Required fields are marked *