Hello,
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)?
Thanks
Code:
import os
import cv2
mean_width = 6000
mean_height = 4000
def generate_video():
image_folder = 'Y:\Bilder\Fotos_Webseite_Backup'
video_name = 'mygeneratedvideo.avi'
os.chdir("Y:\Bilder\Fotos_Webseite_Backup")
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)))
cv2.destroyAllWindows()
video.release()
generate_video()
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
cv.destroyAllWindows()
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?
Thanks
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.