2. Use OpenCV to read and write video

Reading and writing videos in OpenCV is very similar to reading and writing images. Video is nothing but a series of images commonly called frames . So all you need to do is loop through all the frames in the video sequence and process them one frame at a time. In this post we will demonstrate how to read, display and write video from files , image sequences and webcams . We will also investigate some errors that may have occurred along the way and help understand how to fix them.

Let's start by looking at a code example for reading a video file. It essentially contains functions to read video from disk and display it. As you progress, we'll discuss the functions used in this implementation in detail.

Python

import cv2

# Create a video capture object, in this case we are reading the video from a file
vid_capture = cv2.VideoCapture('person_test.mp4')

if (vid_capture.isOpened() == False):
    
print("Error opening the video file")
# Read fps and frame count
else:
   
# Get frame rate information
    # You can replace 5 with CAP_PROP_FPS as well, they are enumerations
   
fps = vid_capture.get(5)
   
print('Frames per second : ', fps,'FPS')

   
# Get frame count
    # You can replace 7 with CAP_PROP_FRAME_COUNT as well, they are enumerations
   
frame_count = vid_capture.get(7)
   
print('Frame count : ', frame_count)

   
while(vid_capture.isOpened()):
     
# vid_capture.read() methods returns a tuple, first element is a bool
      # and the second is frame
     
ret, frame = vid_capture.read()
     
if ret == True:
        cv2.imshow(
'Frame',frame)
       
# 20 is in milliseconds, try to increase the value, say 50 and observe
       
key = cv2.waitKey(20)

       
if key == ord('q'):
         
break
      else
:
       
break

   
# Release the video capture object
   
vid_capture.release()
    cv2.destroyAllWindows()

These are the main functions in OpenCV video I/O that we will discuss in this blog post :

  1. cv2.VideoCapture Creates a video capture object, which will facilitate streaming or displaying video.
  2. cv2.VideoWriter save the output video to a directory.
  3. In addition, we also discussed other required functions cv2.imshow() , cv2.waitKey() and get() methods for reading video metadata such as frame height, width, fps , etc.

read video from file

The next block of code below uses VideoCapture()this class to create a VideoCapture object, which we will then use to read the video file. The syntax for using this class is as follows: 

VideoCapture(path, apiPreference)

The first parameter is the filename / path of the video file. The second is an optional parameter, indicating API a preference. Some options related to this optional parameter are discussed further below. To learn more apiPreference, visit the official documentation link VideoCaptureAPIs .

# Create a video capture object, in this case we are reading the video from a file
vid_capture = cv2.VideoCapture('person_test.mp4')

Now that we have a video capture object, we can use the isOpened()method to confirm that the video file was successfully opened. This isOpened()method returns a boolean indicating whether the video stream is valid. Otherwise, you will receive an error message. Error messages can imply many things. One of them is that the entire video is corrupted, or some frames are corrupted. Assuming the video file has been successfully opened, we can use this get()method to retrieve important metadata associated with the video stream. Note that this method does not work with webcams. The method takes a single argument from the options enumeration list documented here . get()In the example below, we have provided numeric values ​​5 and 7 , which correspond to frame rate ( CAP_PROP_FPS) and number of frames CAP_PROP_FRAME_COUNT) . Either a value or a name can be provided.

Python

view source code

if (vid_capture.isOpened() == False):
    
print("Error opening the video file")
# Read fps and frame count
else:
   
# Get frame rate information
    # You can replace 5 with CAP_PROP_FPS as well, they are enumerations
   
fps = vid_capture.get(5)
   
print('Frames per second : ', fps,'FPS')

   
# Get frame count
    # You can replace 7 with CAP_PROP_FRAME_COUNT as well, they are enumerations
   
frame_count = vid_capture.get(7)
   
print('Frame count : ', frame_count)

After retrieving the required metadata associated with the video file, we are now ready to read each image frame from the file. This is done by creating a loop and using the vid_capture.read() method to read from the video stream one frame at a time. 

The vid_capture.read() method returns a tuple where the first element is a boolean value and the next element is the actual video frame. When the first element is True , it indicates that the video stream contains frames to be read. 

If there are frames to read, you can use imshow() to display the current frame in the window, otherwise exit the loop. Note that you also use the waitKey() function to pause for 20 milliseconds between video frames . Calling the waitKey() function allows you to monitor the keyboard for user input. In this case, for example, if the user presses the q ' key, the loop is exited.

while(vid_capture.isOpened()):
 
# vid_capture.read() methods returns a tuple, first element is a bool
  # and the second is frame
 
ret, frame = vid_capture.read()
 
if ret == True:
    cv2.imshow(
'Frame',frame)
   
# 20 is in milliseconds, try to increase the value, say 50 and observe
   
key = cv2.waitKey(20)

   
if key == ord('q'):
     
break
  else
:
   
break

Once the video stream is fully processed or the user exits the loop prematurely, you release the video capture object vid_capture) and close the window, using the following code:

Python

# Release the video capture object
vid_capture.release()
cv2.destroyAllWindows()

Read video from webcam 

Reading a video stream from a webcam is also very similar to the example discussed above. How can this be? This is all thanks to the flexibility of the video capture class in OpenCV , which has several overloaded functions that accept different input parameters for convenience. Instead of specifying the source location of the video file or image sequence, you only need to provide the video capture device index as shown below. 

  • If your system has a built-in webcam, the camera's device index will be 0" . 
  • If you have multiple cameras connected to your system, the device index associated with each additional camera is incremented (eg 1, 2etc.

Python

vid_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW)

You might be wondering about flags  CAP_DSHOW. This is an optional parameter and therefore not required. CAP_DSHOWJust another video capture API preference, which is short for Direct Display Via Video Input.

write video

Now let's see how to write a video. Just like video reading, we can compose a video from any source (video file, image sequence or webcam). To write a video file: 

  • Use the method to retrieve the height and width of the image frame get().
  • Initialize a video capture object (as described in previous sections) with any of the previously described sources to read the video stream into memory.
  • Create a video writer object.
  • Use a video writer object to save the video stream to disk. 

Continuing with our running example, let's get()start by using the method to get the width and height of a video frame.

Python

# Obtain frame size information using get() method
frame_width = int(vid_capture.get(3))
frame_height =
int(vid_capture.get(4))
frame_size = (frame_width
,frame_height)
fps =
20

get()As mentioned earlier, methods in a class VideoCapture()need to:

  •  A single parameter in an enumerated list that allows you to retrieve various metadata associated with a video frame. 

The metadata available is extensive and can be found here . 

  • In this case, you retrieve the width and height of the frame by specifying 3CAP_PROP_FRAME_WIDTH) and 4CAP_PROP_FRAME_HEIGHT) . You will use these dimensions further below when writing the video file to disk.

In order to write a video file, you need to first VideoWriter()create a video-writer object from this class, as shown in the code below. 

Here's VideoWriter()the syntax:

VideoWriter(filename, apiPreference, fourcc, fps, frameSize[, isColor])

This class VideoWriter()takes the following parameters: 

  • filename: The path name of the output video file
  • apiPreference: API backend identifier
  • fourcc: 4 -character code of the codec for compressed frames ( fourcc )
  • fps: The frame rate of the created video stream
  • frame_size: the size of the video frame
  • isColor: If non-zero, the encoder will expect and encode color frames. Otherwise it will apply to grayscale frames (this flag is currently only supported on Windows ).

The following code creates a video writer object outputfrom a class. VideoWriter()A special convenience function for retrieving the four-character codec is required as the second argument of the video writer object, cv2.

  • VideoWriter_fourcc('M', 'J', 'P', 'G')in Python .
  • VideoWriter::fourcc('M', 'J', 'P', 'G') in C++ .

A video codec specifies how to compress a video stream. It converts uncompressed video to compressed format and vice versa. To create AVI or MP4 format, use the following Fourcc specification:

video:cv2.VideoWriter_fourcc('M','J','P','G')

MP4 cv2.VideoWriter_fourcc(*'XVID')

The next two input parameters specify the frame rate and frame size (width, height) in FPS .

Python

# Initialize video writer object
output = cv2.VideoWriter('Resources/output_video_from_file.mp4', cv2.VideoWriter_fourcc(*'XVID'), 20, frame_size)

Now that you have created a video writer object, use it to write a video file to disk, one frame at a time, as shown in the following code. Here you are writing an MP4 video file to disk at 20 frames per second . Notice how we simplified to a loop from the previous example.

Python

while(vid_capture.isOpened()):
 
# vid_capture.read() methods returns a tuple, first element is a bool
  # and the second is frame
 
ret, frame = vid_capture.read()
 
if ret == True:
    output.write(frame)

Finally, in the code below, the video capture and video-writer objects are released.

Python

# Release the video capture object
vid_capture.release()
output.release()

Mistakes you may encounter while reading or writing a video

video reading

When reading frames, it may throw an error if the path is wrong or the file is corrupted or the frame is lost. ifThat's why we use statements in loops . whilecan be seen in the line if ret == True. This way it will only process the frame if it exists. The following is an example of the error log observed in this case. It is not a complete log, only key parameters.

cap_gstreamer.cpp:890: error: (-2) GStreamer: unable to start pipeline  in function

For the wrong path :

VideoCapture()Using this class will not show any error or warning when you provide wrong video path. The problem comes when you try to do anything with the video frames. To do this, you can use a simple if block to check if you have read the video file, like we did in our example. That should print the following message.

Error opening the video file

video writing

Various errors may occur during this step. The most common ones are wrong frame size and wrong api preferences . If the frame size is not similar to the video, then even if we get a video file in the output directory, it will be blank. If you use the NumPy shape method to retrieve the frame size, remember to invert the output, since OpenCV will return height x width x channels . If it throws api preference error, we may need to pass flag in parameter CAP_ANY. VideoCapture()It can be seen in the webcam example, which we use CAP_DHOWto avoid generating warnings.

Here is an example of an error log:

When CAP_DSHOW fails:

 [WARN:0]...cap_msmf.cpp(438) …. terminating async callback

When the frame size is incorrect:

cv2.error: OpenCV(4.5.2) :-1: error: (-5:Bad argument) in function 'VideoWriter'
> Overload resolution failed:
>  - Can't parse 'frameSize'. Sequence item with index 0 has a wrong type
>  - VideoWriter() missing required argument 'frameSize' (pos 5)
>  - VideoWriter() missing required argument 'params' (pos 5)
>  - VideoWriter() missing required argument 'frameSize' (pos 5)

expand your knowledge

summarize

In this blog, you learned to use the video capture object to read and display video streams from three different sources. You even saw how to use the video capture object to retrieve important metadata from the video stream. We also demonstrated how to use the video-writer object to write a video stream to disk. You may also find it helpful to resize video frames or annotate them with shapes and text. To do this, only a single image frame needs to be modified.

Now that you know how to read and write videos, and are familiar with using OpenCV , get up to speed. And keep learning.

 

Guess you like

Origin blog.csdn.net/lvmengzou/article/details/125231125