OpenCV: the toolbox
The most widely used image-processing library: installation, the thirty functions that matter, and the traps everyone falls into once.
The idea
OpenCV is a collection of roughly 2,500 optimised image functions. You rarely use more than thirty, but those thirty cover almost every practical task: load, rotate, scale, blur, find edges, count shapes, read text, read video.
Installation
pip install opencv-python numpyOn a headless server use opencv-python-headless instead. Installing both causes
crashes that are hard to attribute.
The thirty functions that matter
| Area | Functions |
|---|---|
| In and out | imread, imwrite, VideoCapture, imshow |
| Geometry | resize, warpAffine, warpPerspective, rotate, flip |
| Colour | cvtColor, inRange, split, merge |
| Filters | GaussianBlur, medianBlur, bilateralFilter, filter2D |
| Thresholding | threshold, adaptiveThreshold |
| Morphology | erode, dilate, morphologyEx |
| Edges and shapes | Canny, Sobel, findContours, HoughLinesP |
| Features | ORB_create, SIFT_create, BFMatcher, findHomography |
| Models | dnn.readNet, dnn.blobFromImage |
A full example: counting receipts
import cv2, numpy as np
img = cv2.imread("receipts.jpg")
if img is None:
raise SystemExit("image not found - check the path")
grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(grey, (7, 7), 0)
# Otsu picks the threshold itself, from the histogram.
_, binary = cv2.threshold(blur, 0, 255,
cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 9))
binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel) # close holes
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
large = [c for c in contours if cv2.contourArea(c) > 5000]
print("receipts found:", len(large))No machine learning here, and it solves a task for which a model is often proposed.
Axis orders
The most common cause of silent bugs is three libraries using three conventions.
| Context | Order | Example |
|---|---|---|
| NumPy shape of an image | (height, width, channels) | img.shape == (1080, 1920, 3) |
cv2.resize | (width, height) | cv2.resize(img, (1920, 1080)) |
| Points in OpenCV | (x, y) that is (column, row) | cv2.circle(img, (x, y), …) |
| NumPy indexing | [y, x] that is [row, column] | img[y, x] |
| PyTorch tensor | (batch, channels, height, width) | torch.Size([8, 3, 224, 224]) |
An image that looks squashed after resizing is practically always a swapped
(w, h).
Performance
- Set
cv2.setNumThreads(1)when you already parallelise at process level, otherwise the thread pools compete. - Skip video frames with
cap.grab()and only callcap.retrieve()when needed. That saves the decode. - For many small images
cv2.UMatuses OpenCL without any code change. - Use
cv2.imencoderather thanimwritewhen the result goes into a database or over the network anyway.
Running models inside OpenCV
The dnn module reads ONNX, Caffe and Darknet models and runs them without
PyTorch. For edge devices and slim containers that is often the most practical
route, because a 40-megabyte install suffices instead of several gigabytes.
net = cv2.dnn.readNetFromONNX("model.onnx")
blob = cv2.dnn.blobFromImage(img, scalefactor=1/255.0, size=(640, 640),
swapRB=True, crop=False) # swapRB: BGR -> RGB
net.setInput(blob)
out = net.forward()swapRB=True is not optional here: nearly every published model was trained on
RGB while OpenCV delivers BGR. Without the swap, quality drops measurably and no
error is reported.
Related courses and sources
OpenCV tutorials
The official guides to filters, edges, features and calibration, each with runnable Python code.
For anyone writing image processing themselves; every example runs.
opencv-python
The package that brings OpenCV into a Python environment. One command, and classical image processing is available.
One command, and classical image processing is available in your own environment.