Hello and welcome again to yet another part of the OPEN-CV with Python tutorial series. In the previous part, we saw some challenging and intuitive functionalities of Open-CV library and performed a few operations on image frames including how to record videos using Python.
In this part of the tutorial, we are going to apply those principles and practices we learned in the previous tutorial to make a Time Lapse video using Python. This will be a good post in terms of the application of Open-CV. Below is a good example of a time-lapse video taken directly from Youtube.
Let’s Start with importing all the necessary libraries to make such a video.
import os
import numpy as np
import cv2
import time
import datetime
import glob
Here we see that we have imported 3 more libraries than usual, those being Time, datetime, and glob. as the name itself suggests time and datetime are inbuilt python modules for date/time manipulation. The glob module in python finds all the pathnames matching a specified pattern according to the rules used by the Unix shell.
Next, we define a python dictionary that contains all the possible resolutions with their respective heights and widths, as seen in the previous part of this tutorial series in the program of Recording videos. We also define another dictionary that contains values for different video types.
STD_DIM = {
"480p" : (640, 480),
"720p" : (1280, 720),
"1080p" : (1920, 1080),
"4k" : (3840, 2160),
}
VIDEO_TYPE = {
'avi' : cv2.VideoWriter_fourcc(*'XVID'),
'mp4' : cv2.VideoWriter_fourcc(*'XVID'),
'mp4' : cv2.VideoWriter_fourcc(*'H264'),
}
We create different methods to set the dimensions of the video, file type of the video and also set the resolution of the video.
def change_resolution(cap, width, height):
cap.set(3, width)
cap.set(4, height)
def set_dimensions(cap, res = '1080p'):
width, height = STD_DIM['480p']
if res in STD_DIM:
width, height = STD_DIM[res]
change_resolution(cap, width, height)
return width, height
def set_videotype(filename):
filename, ext = os.path.splitext(filename)
if ext in VIDEO_TYPE:
return VIDEO_TYPE[ext]
return (VIDEO_TYPE['avi'])
The following piece of code resizes the image that is captured during the entire process. It basically sets the height and width of all the images and returns the resized images to the specified file path.
# source:https://stackoverflow.com/a/44659589
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
dim = None
(h, w) = image.shape[:2]
if width is None and height is None:
return image
# CHECK TO SEE IF THE WIDTH IS NONE
if width is None:
r = height / float(h)
dim = (int(w * r), height)
else:
r = width / float(w)
dim = (width, int(h * r))
resized = cv2.resize(image, dim, interpolation = inter)
return resized
Next up, we set different parameters like the save-path, file name, FPS, etc and pass all those parameters to output the streaming file into the video writer of cv2. Lastly, we double check for the existence of the save-path
cap = cv2.VideoCapture(0)
frames_per_seconds = 20
save_path='saved-media/video.avi'
my_res = '480p'
filename = 'video.avi'
dims = set_dimensions(cap, res = my_res)
video_type = set_videotype(filename = filename)
out = cv2.VideoWriter(save_path, video_type, frames_per_seconds, dims)
timelapse_img_dir = 'images/timelapse'
seconds_duration = 20
seconds_between_shots = .25
if not os.path.exists(timelapse_img_dir):
os.mkdir(timelapse_img_dir)
if not os.path.exists(save_path):
os.mkdir(save_path)
In the following piece of code, we first define the current time value of the system. We then take another time value which is in the future and start a loop which compares both of these values. Inside this loop, images are captured at every 1/4th of a second’s interval.
Notice that we also provide the name of every image captured in order to keep things simple and sorted.
now = datetime.datetime.now()
finish_time = now + datetime.timedelta(seconds=seconds_duration)
i = 0
while datetime.datetime.now() < finish_time:
ret, frame = cap.read()
filename = "{}/{}.jpg".format(timelapse_img_dir, i)
# filename = f"{timelapse_img_dir}/{i}.jpg"
i += 1
cv2.imwrite(filename, frame)
time.sleep(seconds_between_shots)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
With the help of this function, we stitch all the captured images into a single video file. Sorting of image files is based on ascending order of time of image file creation. At last, we remove all the image files once the video is made. We can avoid this step and keep all the images.
def images_to_video(out, image_dir, clear_images=True):
image_list = glob.glob(image_dir + "/*.jpg")
sorted_images = sorted(image_list, key=os.path.getmtime)
for file in sorted_images:
image_frame = cv2.imread(file)
out.write(image_frame)
if clear_images:
for file in image_list:
os.remove(file)
images_to_video(out, timelapse_img_dir)
cap.release()
out.release()
cv2.destroyAllWindows()
Voila !! We have created our first time-lapse video using Open-CV and Python with a single program.
That’ll be it for this blog post, folks !!! Congratulations for making it this far.
Stay tuned. Until next time…!