opencv-python
opencv-python packages the OpenCV C++ computer vision library as pre-built, CPU-only Python wheels, so pip install works without compiling anything. You import it as cv2, images are plain numpy arrays, and it covers image and video I/O, camera capture, resizing and color conversion, filtering, thresholding, contours, feature detection, Haar cascades, and the DNN module for running trained models. The current wheels track OpenCV 5.0 and support Python 3.7 through 3.14.
The standard way to get OpenCV into Python, and the pre-built wheels save you a genuine CMake ordeal. Install the headless variant on servers, and reach for Pillow when you are only resizing thumbnails.
Use it if
- You do classic computer vision work: contours, homography, template matching, filtering, or camera and video frame processing
- You preprocess images or video frames for ML models and need fast CPU operations backed by optimized C++
- You want face or object detection with bundled Haar cascade files (cv2.data.haarcascades) or DNN-module inference without installing a deep learning framework
- You need GPU acceleration: the wheels are CPU-only, and CUDA support means compiling OpenCV from source with CMake, which routinely takes hours and real debugging
- You deploy to Docker or servers with this default package: it pulls GUI and X11 dependencies you do not need; opencv-python-headless is the right variant there
- Your image needs are simple (open, resize, crop, convert, save): Pillow is far lighter and has a friendlier API
- You depend on patented extras like SURF: non-free algorithms are excluded from these binaries and require a custom build
Setup reality
pip install opencv-python just works on mainstream platforms because wheels exist for everything current. The traps: there are four package variants (main, contrib, headless, contrib-headless) that all install the same cv2 namespace, and installing more than one silently corrupts your environment, so pick exactly one. pip older than 19.3 cannot use the manylinux2014 wheels and falls back to a source build that fails or takes hours. On Windows you may need the Visual C++ redistributable, and N editions need the Media Feature Pack. cv2.imshow does nothing in headless installs, and everyone gets bitten once by BGR channel order.
Patterns
Read and write an imageread-write-image
import cv2
img = cv2.imread('photo.jpg') # BGR numpy array
if img is None:
raise FileNotFoundError('photo.jpg missing or unreadable')
cv2.imwrite('out.png', img)imread returns None instead of raising on a bad path or unsupported format; always check before using the array.
Convert BGR to RGB for other librariesbgr-to-rgb
import cv2
img = cv2.imread('photo.jpg')
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# now safe for matplotlib, PIL, or ML frameworks
import matplotlib.pyplot as plt
plt.imshow(rgb)OpenCV loads images as BGR; feeding them to RGB-expecting code produces blue-tinted output, the most common cv2 bug.
Resize an imageresize-image
import cv2
img = cv2.imread('photo.jpg')
small = cv2.resize(img, (640, 360), interpolation=cv2.INTER_AREA)
double = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)The size tuple is (width, height) while numpy shape is (height, width); INTER_AREA shrinks best, INTER_CUBIC enlarges best.
Read frames from a camera or video filevideo-capture
import cv2
cap = cv2.VideoCapture(0) # or 'clip.mp4'
while True:
ret, frame = cap.read()
if not ret:
break
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()imshow needs the GUI build; on headless installs it raises an error, so process frames without display there.
Write frames to a video filewrite-video
import cv2
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('out.mp4', fourcc, 30.0, (1280, 720))
for frame in frames:
out.write(frame) # frames must match (1280, 720), BGR
out.release()If the frame size does not match the size passed to VideoWriter, frames are dropped silently and the file plays empty.
Draw boxes and labels on an imagedraw-annotations
import cv2
cv2.rectangle(img, (50, 50), (220, 180), (0, 255, 0), 2)
cv2.putText(img, 'cat 0.97', (50, 40),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)Drawing functions modify the array in place; call img.copy() first if you need the original.
Threshold a grayscale imagethreshold-image
import cv2
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
adaptive = cv2.adaptiveThreshold(
gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2)Otsu picks the global threshold for you; use adaptive thresholding when lighting varies across the image.
Find and draw contoursfind-contours
import cv2
contours, hierarchy = cv2.findContours(
binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
big = [c for c in contours if cv2.contourArea(c) > 500]
cv2.drawContours(img, big, -1, (0, 0, 255), 2)findContours expects a binary image (threshold or Canny output first) and finds white objects on a black background.
Detect faces with a bundled Haar cascadeface-detect-haar
import cv2
cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)All package variants ship the cascade XML files; cv2.data.haarcascades is the path shortcut. Expect false positives versus DNN detectors.
Blur an image and detect edgesblur-and-edges
import cv2
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)Blur before Canny or sensor noise becomes edges; kernel sizes must be odd numbers.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| pillow | PyPI | You just need to open, resize, convert, and save images without CV machinery |
| scikit-image | PyPI | You prefer algorithm-focused image processing with an idiomatic numpy/scipy API |
| opencv-python-headless | PyPI | Same library for servers and Docker, minus the GUI dependency chain |