AI & Computer Vision, lesson 2 of 52
Python & OpenCV: Set Up Your Computer-Vision Workshop
Introduction
In lesson 1 you saw that a picture is just a grid of numbers. Today you get your hands on those numbers. You'll set up Python on your laptop, install OpenCV (the most widely used computer-vision library), and write a program that shows your webcam live, with a frame counter and a banner drawn on top.
Every project in this course starts from the code you write today, so take it slowly and make sure each step works before moving on.
By the end of this lesson you'll be able to:
- make a virtual environment and install packages into it with
pip - point VS Code at that environment
- open your webcam from Python and show it in a window
- draw text and shapes on every frame
- measure how many frames per second (FPS) your camera gives you
- close the camera properly when you quit
Each project has its own venv, so each keeps the version it needs. Your prompt shows (venv) when it's switched on.
Working principle
Virtual environments
A virtual environment (or venv) is a private copy of Python just for one project. Without one, every project shares the same packages, and sooner or later two projects need different versions of the same package. Those clashes are very hard to fix.
The rule for this course: one project, one virtual environment. When it's switched on, your terminal prompt starts with (venv).
| Windows | macOS and Linux | |
|---|---|---|
| Create | python -m venv venv | python3 -m venv venv |
| Switch on | .\venv\Scripts\activate | source venv/bin/activate |
| Switch off | deactivate | deactivate |
pip
pip downloads Python packages from the internet (from PyPI, the Python Package Index). Only use it when (venv) is in your prompt, so packages land in your project and not in your whole computer.
pip install opencv-python numpy matplotlib # the packages for this unit
pip freeze > requirements.txt # write down what you installed
pip install -r requirements.txt # rebuild the same set on another laptopThe webcam loop
A video is just pictures shown quickly, one after another. So every live computer-vision program is a loop: grab a frame, do something with it, show it, repeat.
import cv2
cap = cv2.VideoCapture(0) # open webcam number 0 (try 1 or 2 if you have more than one)
while True:
ret, frame = cap.read() # ret: did it work? frame: the picture, shape (height, width, 3)
if not ret:
break
cv2.imshow("Webcam feed", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break # press Q to quit
cap.release()
cv2.destroyAllWindows()| Line | What it does |
|---|---|
cv2.VideoCapture(0) | Opens the webcam. cap.isOpened() tells you if it worked. |
cap.read() | Grabs the next frame. If the camera disconnects, ret becomes False, so always check it. |
cv2.imshow("title", frame) | Shows the frame in a window with that title. |
cv2.waitKey(1) | Waits 1 millisecond for a key press. This is also what lets the window redraw, so the loop needs it. |
cap.release() | Gives the camera back to your computer. Without it, the camera stays locked. |
cv2.destroyAllWindows() | Closes the windows. |
A video is pictures shown quickly. The loop goes round about 30 times a second. Here it's slowed right down.
Drawing on a frame
You draw straight onto the frame before you show it. Every label, box and alert in this course is drawn like this.
cv2.putText(
frame,
"Hello, CV!",
(30, 50), # where: x, y in pixels from the top-left corner
cv2.FONT_HERSHEY_SIMPLEX, # the font
1.2, # size
(0, 255, 0), # colour: green
2, # thickness
cv2.LINE_AA, # smooth edges
)Watch out: OpenCV colours are BGR, not RGB. Blue comes first and red comes last.
| Colour | BGR |
|---|---|
| Green | (0, 255, 0) |
| Red | (0, 0, 255) |
| Blue | (255, 0, 0) |
| Yellow | (0, 255, 255) |
| White | (255, 255, 255) |
| Black | (0, 0, 0) |
What you'll need
- A laptop with a webcam (Windows, macOS or Linux)
- Python 3.10 or newer. On Windows, tick Add python.exe to PATH when you install it.
- VS Code with the Python, Pylance and Jupyter extensions from Microsoft
- An internet connection for the installs (the programs themselves run offline)
Set up step by step
Tick off each step before you go on to the next one.
- Open a terminal. Windows: press Win+R, type
cmd, press Enter. macOS: Cmd+Space, type Terminal. Linux: Ctrl+Alt+T. - Make a project folder. Type
mkdir cv_course, thencd cv_course. - Create the virtual environment. Windows:
python -m venv venv. macOS and Linux:python3 -m venv venv. A folder calledvenvappears. - Switch it on. Windows:
.\venv\Scripts\activate. macOS and Linux:source venv/bin/activate. Check: your prompt now starts with(venv). If it doesn't, stop and fix this first. - Install the packages. Type
pip install opencv-python numpy matplotliband wait for "Successfully installed". - Open the folder in VS Code. Type
code .(or open VS Code and use File → Open Folder). - Choose the right Python. Press Ctrl+Shift+P, type Python: Select Interpreter, and pick the one inside
venv. Check: the bar at the bottom of VS Code showsvenv. - Install Jupyter for the next lessons. Type
pip install notebook. You'll use notebooks from lesson 3.
Build it
Make a new file called webcam_lab.py in your cv_course folder. Build it in four steps, and run it after each one.
Step 1: check the install
import cv2
import numpy as np
print(f"OpenCV version: {cv2.__version__}")
print(f"NumPy version: {np.__version__}")You should see two version numbers. OpenCV should be 4.5 or newer (if not, run pip install --upgrade opencv-python). If you get ModuleNotFoundError, your venv isn't switched on.
Step 2: open the webcam
Replace everything in the file with this:
import cv2
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("ERROR: Cannot open webcam. Try camera 1 or 2.")
raise SystemExit
print("Webcam opened. Press Q to quit.")
while True:
ret, frame = cap.read()
if not ret:
print("ERROR: No frame received.")
break
cv2.imshow("My webcam", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()You should see yourself in a window. Click on the window and press Q to quit.
Step 3: add an FPS counter and a banner
Now draw on every frame. Notice two things: prev_time is set before the loop, and the navy banner has its biggest number first, because colours are BGR.
import time
import cv2
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("ERROR: Cannot open webcam. Try camera 1 or 2.")
raise SystemExit
prev_time = time.time()
show_gray = False
print("Press Q to quit, G to switch black-and-white on and off.")
while True:
ret, frame = cap.read()
if not ret:
print("ERROR: No frame received.")
break
# frames per second = 1 second divided by the time since the last frame
now = time.time()
fps = 1.0 / (now - prev_time + 1e-9)
prev_time = now
# read the keyboard once per loop
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
if key == ord("g"):
show_gray = not show_gray
if show_gray:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) # back to 3 channels so we can still draw in colour
h, w = frame.shape[:2]
cv2.rectangle(frame, (0, 0), (w, 40), (90, 30, 10), -1) # navy banner (-1 = filled)
cv2.putText(frame, f"FPS: {fps:.1f}", (10, 28),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2, cv2.LINE_AA)
cv2.putText(frame, f"{w}x{h}", (w - 110, 28),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 200, 200), 1, cv2.LINE_AA)
cv2.imshow("My webcam", frame)
cap.release()
cv2.destroyAllWindows()You should see a navy banner with a green FPS number and your camera's size, like 640x480. Press G and the picture turns black and white. Between 15 and 30 FPS is normal for a laptop webcam.
Step 4 (extra): a colour picker
Make a second file, sampler.py. Click anywhere on the video to print the colour of that pixel. You'll meet the second colour code, HSV, in lesson 4.
import cv2
clicked = None # the last place you clicked
def on_mouse(event, x, y, flags, param):
global clicked
if event == cv2.EVENT_LBUTTONDOWN:
clicked = (x, y)
cap = cv2.VideoCapture(0)
cv2.namedWindow("Sampler")
cv2.setMouseCallback("Sampler", on_mouse)
while True:
ret, frame = cap.read()
if not ret:
break
if clicked is not None:
x, y = clicked
b, g, r = frame[y, x]
hsv = cv2.cvtColor(frame[y:y + 1, x:x + 1], cv2.COLOR_BGR2HSV)[0, 0]
print(f"({x}, {y}) BGR = ({b}, {g}, {r}) HSV = {tuple(int(v) for v in hsv)}")
cv2.circle(frame, (x, y), 6, (0, 255, 255), 2)
clicked = None
cv2.imshow("Sampler", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()You should see a yellow circle where you clicked, and the colour numbers in the terminal. Try clicking your shirt, then the wall.
If it goes wrong
| What you see | Why | Fix |
|---|---|---|
ModuleNotFoundError: No module named 'cv2' | The venv isn't switched on, or OpenCV went somewhere else | Check for (venv) in the prompt, then pip install opencv-python again |
| The window opens but it's black | Another app is using the camera | Close the browser, Zoom, Teams or any other camera app, then try again |
| "Cannot open webcam" | Wrong camera number, or no webcam found | Try cv2.VideoCapture(1) or (2) |
| The window freezes | waitKey is missing, or set to 0 | Put cv2.waitKey(1) inside the loop. 0 means "wait forever". |
python is not recognised | Python isn't on your PATH | Try python3. On Windows, reinstall Python and tick "Add to PATH". |
| FPS shows 0.0 or a giant number | prev_time is set inside the loop | Move prev_time = time.time() above while True: |
| VS Code says the module is missing, but the terminal works | VS Code is using the wrong Python | Ctrl+Shift+P, Python: Select Interpreter, pick the venv one |
| Your navy banner is red | You wrote the colour as RGB | OpenCV is BGR. Navy is (90, 30, 10): blue first. |
Try it
- Add a frame counter to the banner: start
frame_count = 0before the loop and add 1 each time round. - Draw a box in the middle of the frame with
cv2.rectangle(). Work out the corners fromwandh. - Show the time on screen with
time.strftime("%H:%M:%S"). - Harder: make the S key save the current frame as a photo with
cv2.imwrite("snap.jpg", frame). You'll use this idea for collecting data in Unit 3.
Check what you learnt
What does cap.release() do?
Why does the loop need cv2.waitKey(1)?
You wanted red text but it came out blue. What went wrong?
What is inside the venv folder?
How can your program check that the webcam opened before it starts the loop?
Conclusion
You've built your computer-vision workshop: a virtual environment with OpenCV in it, VS Code pointed at the right Python, and a webcam loop that grabs, draws on and shows every frame. Almost every program in this course is this same loop with something new added in the middle.
What next?
Next: Python & NumPy crash course: an image is an array. The frame you just showed is a NumPy array. You'll learn to crop it, flip it and brighten it with a few lines of code.

