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.
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')