Opencv-python script with argparse

Introduction

In previous posts:

I documented my installation of opencv-python , showed how to get video capture going, and covered saving video streams to mp4. In this post, I'll focus on addding command line arguments to the previous script using argparse. As before, this post focuses on using these scripts on Pop!_OS (Ubuntu) 22.04 (not MAC/Windows).

The script

Let's start with the full script, given below (also available at this github repo ). This is almost exactly the same as the the script in the previous post because all of the same things need to be done. The changes here focus on using argparse to add command line options and help.

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2024 Christopher C. Strelioff <chris.strelioff@gmail.com>
#
# Distributed under terms of the MIT license.

"""
script03.py

Adding command line argprase to script that does video capture and writing
video files on Pop_OS! (Ubuntu) 22.04 operating system.

Following documentation at:
https://docs.opencv.org/4.x/dd/d43/tutorial_py_video_display.html

"""

import numpy as np
import cv2

#
# command line argument processing
#
import argparse
parser = argparse.ArgumentParser(prog='./script03.py')
# save a video file?
parser.add_argument('-s', '--save', help='save a video file', dest='save', action='store_true')
# assign a file name, default is video.mp4
parser.add_argument('-f', '--file', help='filename for video, should be mp4', dest='file', default='video.mp4')
# parse arguments & provide message at terminal
args = parser.parse_args()
if (args.save == True):
print(f'...saving video to {args.file}.')
else:
print('...not saving video to file.')
print('Hit "q" to quit.')

# pass argument 0 for device index (1st camera)
vcap = cv2.VideoCapture(0);
if not vcap.isOpened():
print("Can't open camera!")
exit()

# get height and width of capture
width = int(vcap.get(3))
height = int(vcap.get(4))

# bool for isColor is optional, BUT defaults to True!
# - doing grayscale in the loop, so have to set to false!
isColor = False

# create VideoWrite if -s or --save flags passed
if (args.save):
# create VideoWriter
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# using file name in args.file
output = cv2.VideoWriter(args.file, fourcc, 20.0, (width, height), isColor)

# loop until
# - error reading frame from camera
# - or, user hits 'q'
while True:
# read a frame
ret, frame = vcap.read();

# ret == True if frame read correctly
if not ret:
print("Can't read frame, exiting...")
break

# process frame
# - change BGR -> GRAY (video should be grayscale)
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# display resulting fram
cv2.imshow('frame', gray_frame)

if (args.save):
# write to the output is -s or --save flag passed
output.write(gray_frame)

# listen for 'q' press to exit
if cv2.waitKey(1) == ord('q'):
break

# everything done
# - release capture
# - release video writer
# - destroy all windows
vcap.release()

if (args.save):
# run is -s or --save flags passed
output.release()

cv2.destroyAllWindows()

setup

The first addition to the script from the previous post is importing and setting up the options for argparse:

  • Import argparse and set the name of the "program" using:
    import argparse
    parser = argparse.ArgumentParser(prog='./script03.py')
  • Add an argument to save the video stream as a file using -s or --save (defaults to False):
    # save a video file?
    parser.add_argument('-s', '--save', help='save a video file', dest='save', action='store_true')
  • Add an argument to set the file name -f or --file (defaults to video.mp4):
    # assign a file name, default is video.mp4
    parser.add_argument('-f', '--file', help='filename for video, should be mp4', dest='file', default='video.mp4')
  • Parse the passed arguments using:
    args = parser.parse_args()
  • Finally, for this first part, check the "save" argument and print info to the terminal for the user:
    if (args.save == True):
    print(f'...saving video to {args.file}.')
    else:
    print('...not saving video to file.')
    print('Hit "q" to quit.')

All together, this looks like:

#
# command line argument processing
#
import argparse
parser = argparse.ArgumentParser(prog='./script03.py')
# save a video file?
parser.add_argument('-s', '--save', help='save a video file', dest='save', action='store_true')
# assign a file name, default is video.mp4
parser.add_argument('-f', '--file', help='filename for video, should be mp4', dest='file', default='video.mp4')
# parse arguments & provide message at terminal
args = parser.parse_args()
if (args.save == True):
print(f'...saving video to {args.file}.')
else:
print('...not saving video to file.')
print('Hit "q" to quit.')

saving a file?

There are parts of the script that only needed to run if a video file is is being written to disk. This affects the script in a few places:

  • Before the while True: loop there is a section of the script that initializes a VideoWriter. This only needs to happen if the -s, or --save flag was used:
    # create VideoWrite if -s or --save flags passed
    if (args.save):
    # create VideoWriter
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    # using file name in args.file
    output = cv2.VideoWriter(args.file, fourcc, 20.0, (width, height), isColor)
  • Inside the while True: loop, output only needs to be written if requested:
    if (args.save):
    # write to the output is -s or --save flag passed
    output.write(gray_frame)
  • Finally, after the while True: loop, cleanup needs to happen if a video file was written:
    if (args.save):
    # run is -s or --save flags passed
    output.release()

using the script

Because this script uses opencv-python, the virtual environment created in an early post needs to be active before we can run the script with the new argparse abilties. For example, to show the help, try:

$ workon opencv
(opencv) $ ./script03.py --help
usage: ./script03.py [-h] [-s] [-f FILE]

options:
-h, --help show this help message and exit
-s, --save save a video file
-f FILE, --file FILE filename for video, should be mp4
(opencv) $

Finally, an example of running the script and choosing a file name would look like:

(opencv) $ ./script03.py -s -f my-video.mp4
...saving video to my-video.mp4.
Hit "q" to quit.
(opencv) $ l
my-video.mp4 script03.py
(opencv) $

That's it! Listing the directory contents, it is clear that my-video.mp4 was created.