Creating video with movement from images

I’m trying to make my life just a bit easier. I want to make a program that takes images in a folder (got that part figured out) and makes them into a video (basically followed a geeksforgeeks tutorial, works as well). My problem is adding motion to those images in the video. In a regular video editing software I would zoom in about 10-20% and then move the image from top to bottom, left to right, you get the idea. The motion can be random, nothing too crazy though, just slow and steady motion.
How can you move an image in a video with OpenCV (or is there an even better solution for that)?


import os
import cv2

mean_width = 6000
mean_height = 4000

def generate_video():
    image_folder = 'Y:\Bilder\Fotos_Webseite_Backup'
    video_name = 'mygeneratedvideo.avi'

    images = [img for img in os.listdir(image_folder)
              if img.endswith(".jpg") or
              img.endswith(".jpeg") or
              img.endswith("png")]#I'll use my own function for that, just easier to read

    frame = cv2.imread(os.path.join(image_folder, images[0]))

    height, width, layers = frame.shape

    video = cv2.VideoWriter(video_name, 0, 0.25, (width, height))#0.25 so one image is 4 seconds

    for image in images:
        video.write(cv2.imread(os.path.join(image_folder, image)))



warpAffine and a few matrices.

work with 3x3 matrices because those are easy to matrix-multiply, then chop off the last row for an “affine” matrix (2x3).

make functions that produce translation and scale matrices.

import time
import numpy as np
import cv2 as cv

def translate(dx=0, dy=0):
    M = np.eye(3)
    M[0:2,2] = (dx, dy)
    return M

def scale(s=1, sx=1, sy=1):
    M = np.diag([s*sx, s*sy, 1])
    return M

def rotate(alpha=0):
    M = np.eye(3)
    M[0:2, 0:3] = cv.getRotationMatrix2D(center=(0,0), angle=-alpha/np.pi * 180, scale=1.0)
    return M

if __name__ == '__main__':
    img = cv.imread(cv.samples.findFile("lena.jpg"))
    (height, width) = img.shape[:2]
    duration = 10
    fps = 30
    t0 = time.time()
    for t in np.arange(0, duration, 1/fps):
        M = translate(width/2, height/2) @ rotate(2*np.pi * t/10 * 5) @ translate(dx=width/2) @ rotate(2*np.pi * t) @ scale(1 - 0.1 * t) @ translate(dx=-width/2, dy=-height/2)
        output = cv.warpAffine(src=img, M=M[0:2], dsize=(width,height), flags=cv.INTER_CUBIC)
        cv.imshow("output", output)
        now = time.time()
        left = (t0 + t) - now
        key = cv.waitKey(max(1, int(left * 1000)))
        if key in (13, 27): break # Esc, Enter

Hello, Thank you for your answer. I probably didn’t write it clear enough, what I want is more like this (Example - YouTube).
What I want is just zoom in about 35%, and move the image from left to right.
I only managed to zoom into the image and move it at the same time, while also while using the FileWriter video = cv2.VideoWriter(video_name, 0, 30, (width, height)) I had before and using video.write(output), I got 2gb + files that were only 2 or 3 seconds long. What am I doing wrong?

give VideoWriter a sensible codec (fourcc). just follow a tutorial. and if you run my example code, you’ll see that it creates the types of effects you asked for.