Chapter 3, Webcams and Videos

Author

Susan Eileen Fox

Published

September 28, 2025

This chapter will introduce two main new concepts, one from Python and one from OpenCV. The Python concepts is indefinite looping (also called while loops). Unlike a for loop, which repeats a fixed number of times, while loops repeat until some condition changes. They can repeat any number of times, including zero times! The OpenCV concept is working with video. You might think of video as a completely different medium from regular still images, but to OpenCV, a video is just a series of images, and we can process them one by one.

This chapter will just touch on while loops, as there are readings elsewhere that will also cover them.

1 Indefinite looping

The for loop you learned earlier is an example of definite looping, because the number of iterations is defined by the size of the data it loops over (or built in to the result of the range function). We can shorten a for loop by breaking out of it early, but it is difficult (though at times not impossible) to make a for loop iterate more times than it might initially have seemed.

There are circumstances when we don’t know exactly how many times we need to repeat: getting data in a stream, reading inputs interactively from a user, repeating a calculation until its value hits some threshold. For those, we need an indefinite loop: one where the loop continues until some condition either is reached, or ceases to apply. For example, in getting inputs from a user, we want to loop until the user decides they are done adding values. The while loop is Python’s form for indefinite looping.

1.1 What is a while loop, and why do we need another kind of loop?

A while loop has a simpler structure than a for loop (in fact, you can duplicate the behavior of a for loop with a while loop, using accumulator variables. After the keyword while, we put a boolean expression. So long as that boolean expression evaluates to True (or any non-False value), the loop will continue.

while <boolean expression>:
    <indented statements>

Before each pass through the loop, the while statement evaluates the boolean expression over again. If the result is not True then the code stops looping and jumps to the next statement after the indented lines of the loop body. If the result is True, then the body of the loop is executed, and we repeat the process.

Note: If we want a while loop to be able to end, then the boolean expression must include a variable whose value changes (or at least has the possibility of changing) during the

What is the difference between an if statement and a while statement?

An if statement doesn’t repeat, it chooses among possible multiple code blocks, and performs one code block at most one time. A while loop repeats: it has one code block, and it repeats (1) evaluating the test expression, and (2) performing its code block, until the test expressions evaluates to False.

1.2 The break and continue statements

There are two statements, break and continue that can alter the behavior of a loop. These apply to both for loops and while loops; we just haven’t introduced them before this point.

Key points:

  • Both statements must occur inside a for or while loop (directly inside, in the same script or function)
  • If there are nested loops, these statements only affect the closest, innermost loop that contains them
  • The break statement causes the loop to end immediately
  • The continue statement causes Python to skip the rest of the loop body, and return to the next iteration of the loop
  • Usually, break and continue statements occur inside an if statement that is inside the loop body (otherwise the loop would end on the first iteration)

Examine the examples below before proceeding.

Bad uses of break and continue: the examples below show what happens if break or continue are placed, without being guarded by an if statement, inside a loop.

for i in range(5):
    print(i, "   (before break)")
    break
    print("after break")
print("---")
for i in range(5):
    print(i, "   (before continue)")
    continue
    print("after contine")
0    (before break)
---
0    (before continue)
1    (before continue)
2    (before continue)
3    (before continue)
4    (before continue)

Using break and continue in a single loop: The first example stops the while loop if the user enters 'quit', and the second example skips negative numbers in adding up the contents of a list.

names = []
while True:   # A way to specify "loop forever"
    nextName = input("Enter the next name, or quit to end: ")
    if nextName == 'quit':
        break
    names.append(nextName)
print(names)
total = 0
for v in [25, 101, 3, -2, 40, -35, -1023]:
    if v < 0:
        continue
    total = total + v
print(total)
169

**Using break and continue in nested loops: The first example uses break to stop the inner loop whenever the inner loop variable is greater than the outer loop variable.

for i in range(4):
    print("i =", i)
    for j in range(4):
        print("  j =", j)
        if j > i:
            break
        print("  i - j =", i - j)
i = 0
  j = 0
  i - j = 0
  j = 1
i = 1
  j = 0
  i - j = 1
  j = 1
  i - j = 0
  j = 2
i = 2
  j = 0
  i - j = 2
  j = 1
  i - j = 1
  j = 2
  i - j = 0
  j = 3
i = 3
  j = 0
  i - j = 3
  j = 1
  i - j = 2
  j = 2
  i - j = 1
  j = 3
  i - j = 0

The second example uses continue instead, causing the inner loop to continue, without completing the last step.

for i in range(4):
    print("i =", i)
    for j in [2, 0, 1, 3]:
        print("  j =", j)
        if j > i:
            continue
        print("  i - j =", i - j)
i = 0
  j = 2
  j = 0
  i - j = 0
  j = 1
  j = 3
i = 1
  j = 2
  j = 0
  i - j = 1
  j = 1
  i - j = 0
  j = 3
i = 2
  j = 2
  i - j = 0
  j = 0
  i - j = 2
  j = 1
  i - j = 1
  j = 3
i = 3
  j = 2
  i - j = 1
  j = 0
  i - j = 3
  j = 1
  i - j = 2
  j = 3
  i - j = 0

1.2.1 Strategic use of infinite loops

One of the examples above showed how to build an infinite loop. If a while loop has True as the boolean expression for its test, then it cannot every stop looping naturally. However, we can include conditions checked by if statements inside the loop, and we can break out of the loop when we need to.

while True:
    ...
    if <test>:
        break
    ...

Remember that the test of a while loop is evaluated before running the loop even one time. This means that (1) we have to have all values for the boolean expression ready to evaluate before the loop, and (2) there is a chance that the loop body will not even execute one time. The infinite loop form above (while True) ensures that the body of the loop will execute at least once, allowing us to delay the evaluation of the test condition until later inside the loop.

2 Connecting to a built-in webcam

Working with frames from a video instead of individual iamges opens up a new set of interesting problems, and lets us dynamically test the computer vision methods we study. OpenCV can connect directly to the built-in webcams that most laptops have, or to external USB cameras, or to video files stored in the AVI format.

If you do not have a working webcam, ask your instructor for help!

To connect to a video camera or stored video file, we will create a video capture object. This object handles the communications with the operating system to access the camera or file. It has methods that let us read the frames of the video stream, and to read or adjust some of the camera’s properties. The table below lists the main functions and methods you will need.

Examples Meaning
cap = cv2.VideoCapture(0) Creates a VideoCapture object connected to specified camera
cap.isOpened() Boolean method returns true if camera connection succeeded
ret, image = cap.read() Method returns two values, a code to tell if the image was read successfully, and an image from the video stream
cap.release() Method disconnects from camera

The VideoCapture function constructs and returns a video capture object. It takes one required input: a number, to connect to a webcam on the computer, or a path and filename for an AVI video file. A built-in webcam typically has number zero, but the number assigned to an external webcams depends on the internal hardware connections. You may need to experiment to figure out the right number.

The main method we will use is read, which reads one frame from the camera. There are two return values for this method. The first is a boolean, True if the frame was read without issues, and False if it failed to read a frame. We can check this to determine if we have an actual image, before trying to work with it. The second returned value is the image itself, or None if no frame was read.

The script below shows a basic program that will connect to a built-in camera, and read and display frames until the program can’t access the camera. Notice the following changes from earlier programs:

  • We use the infinite, indefinite loop form
  • We use the not ret boolean expression to determine if no camera frame was read, and we break out of the loop if none
  • Our call to waitKey here has an input, a positive number!
import cv2

vidCap = cv2.VideoCapture(0)
while True:
    ret, img = vidCap.read()
    if not ret:
        break
    cv2.imshow("Webcam", img)
    cv2.waitKey(10)

vidCap.release()

It is time to learn more about what waitKey can do. We already have seen that if we call waitKey and pass it no input, or an input of zero, the function pauses the program until the user types a keyboard key. Now, we learn that we can pass a positive integer to waitKey. When we do that, the function pauses for the given number of milliseconds to see if the user will press a key. If they do not press a key in that time, then the function returns and the program resumes. This way, we can show a video stream in a natural way.

Try this program on your own before proceeding.

2.1 Allow the user to quit the program

The sample program in the previous section had one major flaw: there was no way to quit the program without using the Stop button in Pycharm. Otherwise, the program would run until the camera itself disconnected. We would like to add a mechanism for the user to quit the program, and also for us to interact with programs like this while they are running. We can do this by using the return value of the waitKey function.

We have ignored the return value of waitKey up to this point. But it does return a value, one of these two:

  • It returns -1 if the user pressed no key
  • It returns a number representing the keyboard key pressed by the user

Remember the ASCII table, which maps small integers to keyboard characters. The original ASCII values, developed for English uses, used the numbers from 0 to 127. The extended ASCII set adding character bindings for the numbers from 128 to 255, including many more common international symbols that use the same general alphabet. In recent years, Unicode has become popular, as it has the capacity to represent multiple alphabets, but the basic English/roman alphabet symbols, as defined by the ASCII table, are still the same in Unicode.

The waitKey function returns the decimal integer associated with the key the user hit (or -1 if no key was pressed). Look at the Dec column in the table. We need to be able to convert that number into the corresponding character. Python provides two helpful functions for just this purpose: chr converts an integer between 0 and 255 into the character equivalent, and ord converts a character into its integer equivalent.

The example program below adds in lines that:

  • Save the return value of waitKey into a variable
  • Check if that variable was -1 (in which case it does nothing)
  • If not, then it converts the value to a character with chr
  • It prints the character value, along with its numeric value
  • If the user typed a 'q', then it breaks out of the loop
import cv2

cap = cv2.VideoCapture(0)

while True:
    ret, img = cap.read()
    if not ret:
        break
        
    cv2.imshow("Webcam", img)
    x = cv2.waitKey(10)
    if x != -1:
        ch = chr(x)
        print(x, chr(x))
        if ch == 'q':
            break

cap.release()

3 Reading frames from a video file

There are multiple formats for video files. Only some of them can be read by OpenCV, and which ones may be dependent on your version of Python and your operating system. Most videos in .AVI format (an MJPEG format) work with OpenCV, as do .MP4 files, at least on some machines. OpenCV does not process the audio from these video files, just the images.

To read frames from a video file, we just change the call to VideoCapture to pass a string containing the path and filename of the video we want to view. Below is a simple example using one of the videos in the SampleVideos folder.

import cv2

cap = cv2.VideoCapture("SampleVideos/StreetScene.avi")

while True:
    ret, img = cap.read()
    if not ret:
        break
        
    cv2.imshow("Video", img)
    x = cv2.waitKey(10)
    if x != -1:
        ch = chr(x)
        print(x, chr(x))
        if ch == 'q':
            break

cap.release()

Notice that, other than setting up the VideoCapture object, this code is identical to the code for working with a live web-cam feed. This is very convenient for us!

4 Saving a webcam stream to a video file

Writing a stream of images to a video file is much more complicated than reading a video, or than writing individual images. The VideoWriter object can write frames to a video file. We must know, before we start, how big we want the individual frames to be, and what encoding we want to use. For the .avi format, we use the MJPG encoding.

Build Encoding:
fcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')

Takes in 4 characters that describe the encoding and returns the encoding code to use in creating the VideoWriter

Build writer object:
writ = cv2.VideoWriter('vid.avi', fcc, 40.0, (w, h))

Builds a video writer object based on four required inputs:

  • the filename to save to (including .avi file extension),
  • the fourcc encoding object,
  • the frames per second, and
  • the size of each frame
Write data:
writ.write(frame)

Method writes the given image as the next frame in the video file

Close writer:
writ.release()

Method closes the video file and ends the video writer

In the code below, we first:

  • Set up the web-cam and read a frame, to find out what size it is
  • Set up the encoding for the VideoWriter to be MJPG using a special function VideoWriter_fourcc
  • Create a VideoWriter object with a specified filename, encoding, and size
  • Loop over frames from the web-cam until the user says to quit, or the camera stops producing frames
  • Write each frame to the VideoWriter` object, and display it
  • After the loop ends, we release both camera and video writer objects (very important step!)
cap = cv2.VideoCapture(0)

# First determine the size of frames
r, f = cap.read()
cv2.imshow("Video", f)
cv2.waitKey(0)
(hgt, wid, dep) = f.shape
size = (wid, hgt)
print("Sizes:", size)

# Next set up the video writer
filename = "test.avi"
fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
writ = cv2.VideoWriter(filename, fourcc, 25.0, size, 1)

while cap.isOpened():
    r, f= cap.read()
    if not r:
        break
    writ.write(f)
    cv2.imshow("Video", f)
    x = cv2.waitKey(1)
    if x >= 0 and chr(x) == 'q':
        break

cap.release()
writ.release()

Notice that we could process the webcam stream of images any way we like: changing its size, or running image processing or computer vision functions on it. We can write the modified images to our video file. Just remember that the VideoWriter expects BGR images, and will treat the image array as if it were BGR, no matter what.