Working with Video in OpenCV¶
In this section we'll explore how to utilize OpenCV to manage videos, covering tasks such as reading and extracting informations from videos.
History of video¶
But before diving into the technicalities, let's take a brief journey into the history of video capture 🤓
Back on June 15, 1898, in Palo Alto, California, an intriguing experiment took place. The goal was to ascertain if a horse, while galloping, ever lifted all its hooves off the ground simultaneously. This groundbreaking experiment, led by photographer Eadweard Muybridge, marked the inaugural instance of capturing motion in real-time. The endeavor was funded by Leland Stanford, the name behind Stanford University.
To achieve this, Muybridge set up numerous cameras at intervals of 27 inches alongside a racetrack. Each camera was rigged with a thread across the track. As the horse sprinted, it snapped these threads one by one, sequentially activating the camera shutters and capturing images in a split second.
What exactly is a video¶
Essentially, it's a rapid succession of images. The speed at which these images transition is quantified by a term known as frames per second (FPS). If a video boasts an FPS of 40, it implies that 40 images flash on the screen every second. In other words, a fresh image appears every 25 milliseconds. Other vital aspects to consider are the dimensions of these images, specifically their width and height.
Working with videos in OpenCV is quite straightforward, and it offers a range of functionalities to process and analyze video data. Let's dive into the basics of handling videos in OpenCV and then discuss video encoding and formats.
What is video encoding¶
Video encoding (or video compression) is the process of converting raw video data into a digital format by using a specific algorithm (encoder). The primary goal is to reduce redundancy in video data to store or transmit it more efficiently.
Common Video Codecs¶
- H.264: Widely used for streaming, video conferencing, and video storage. It provides good video quality and efficient compression.
- MPEG-4: Used for both streaming and storage. It's older than H.264 but still popular.
- VP9: An open-source codec developed by Google. It's mainly used for web videos.
- AV1: An emerging open-source codec that aims to be more efficient than H.264 and VP9.
- FourCC: (Four-Character Code) is a sequence of four bytes used to uniquely identify video data formats.
- Common Video Containers: Video files consist of both video (visual) and audio (sound) data. A video container format is used to store this combined data : .avi, .mp4, .mkv, .webm. The container determines the file's extension, while the codec affects the video playback quality and compression.
Capture Video from Camera¶
To capture video from a camera, you need to create a VideoCapture
object. Its argument can be either the device index or the name of a video file. Device index is just the number to specify which camera. Normally, one camera will be connected (as in my case). So I simply pass 0 (or -1). You can select the second camera by passing 1 and so on. After that, you can capture frame-by-frame.
Here is a basic code to capture video with a camera:
import cv2
# Create a VideoCapture object
cap = cv2.VideoCapture(0)
# Check if camera opened successfully
if not cap.isOpened():
print("Unable to read camera feed")
# Default resolutions of the frame are obtained.
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
# Loop until the end of the video
while(True):
#Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
cv2.imshow('frame',frame)
# Press Q on keyboard to stop recording
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release the video capture and video write objects
cap.release()
# Closes all the frames
cv2.destroyAllWindows()
Playing Video from File¶
To play a video from a file, you follow a similar process to the above, but instead of a camera index, you provide the filename of the video file.
# Create a VideoCapture object and read from input file
cap = cv2.VideoCapture('./stemvib/Col0_5c_trim.mp4')
# Check if video file opened successfully
if not cap.isOpened():
print("Error opening video file")
# Read until video is completed
while(cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
if ret == True:
# Display the resulting frame
cv2.imshow('Frame', frame)
# Press Q on keyboard to exit
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# Break the loop
else:
break
# When everything done, release the video capture object
cap.release()
# Closes all the frames
cv2.destroyAllWindows()
Extract frame from video¶
Extracting frames from a video is a foundational task in computer vision it transforms temporal data into spatial data, making many image processing techniques applicable to video content. It serves as a bridge between image and video analysis in the realm of computer vision.
Let's write a python function who extract frames from a given video path and return all the images into a folder :
def extract_frames(video_path):
"""
Extracts frames from a video and returns a list of frames.
Args:
video_path (str): Path to the video file.
Returns:
frames (list): List of frames.
"""
cap = cv2.VideoCapture(video_path)
frames = []
# Check if the video file is valid
if not cap.isOpened():
print(f"Failed to open the video file: {video_path}")
return frames
while True:
ret, frame = cap.read()
if not ret:
break
frames.append(frame)
cap.release()
return frames
Let's print some frames, in order to reduce the printed frames we choose to print only every 100 frames.
import matplotlib.pyplot as plt
frames = extract_frames('./stemvib/Col0_5c_trim.mp4')
# print every 100 frames
for i, frame in enumerate(frames[::100]):
plt.imshow(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) # Convert the image from BGR to RGB format
title = f"Frame {i*100}"
plt.title(title)
plt.show()
Croping video¶
Let's assume our objective is to analyze a video to monitor the motion of a red marker positioned on a stem. Many areas in the image might not contain relevant informations. To avoid introducing noise, it's beneficial to eliminate certain portions of the image. This is why we aim to crop the video and convert it to avi format for more convenience. Now, let's delve into the Python code to do so 🤓
def crop_video(input_video_path, output_video_path, top_percentage, right_percentage):
"""
Crops a video based on the specified top and right percentage values.
Args:
input_video_path (str): Path to the input video file.
output_video_path (str): Path to save the output cropped video.
top_percentage (float): Percentage of the top region to keep (0-1).
right_percentage (float): Percentage of the right region to keep (0-1).
"""
cap = cv2.VideoCapture(input_video_path)
# Check if the input video file is valid
if not cap.isOpened():
print(f"Failed to open the input video file: {input_video_path}")
return
# Get the original video properties
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(cap.get(cv2.CAP_PROP_FPS))
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter(output_video_path, fourcc, fps, (int(width * right_percentage), int(height * top_percentage)))
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# Crop the frame
cropped_frame = frame[:int(height * top_percentage), :int(width * right_percentage)]
# Write the cropped frame
out.write(cropped_frame)
# Release everything if the job is finished
cap.release()
out.release()
print(f"\n--- ✅ Video croped and saved at : {output_video_path} ✅ s---\n")
# Playing with the parameters
input_video_path = './stemvib/Video_5_Aravib.MP4'
output_video_path = './output_vids/Video_5.avi'
top_percentage = 0.6
right_percentage = 0.89
# Crop video
crop_video(input_video_path, output_video_path, top_percentage, right_percentage)
--- ✅ Video croped and saved at : ./output_vids/Video_5.avi ✅ s---