Skip to main content

Overview

The OpenCV Python bindings provide a Pythonic interface to OpenCV’s C++ API. The bindings are automatically generated and offer excellent performance while maintaining ease of use. All functions work seamlessly with NumPy arrays.

Installation

The easiest way to install OpenCV for Python:
pip install opencv-python
The opencv-python package includes prebuilt binaries for Windows, macOS, and Linux. No compilation required.

Version Requirements

  • Python 3.6 or higher
  • NumPy (automatically installed as a dependency)

Building from Source

For custom builds or the latest development version:
# Clone the repository
git clone https://github.com/opencv/opencv.git
cd opencv

# Create build directory
mkdir build && cd build

# Configure with Python support
cmake -DBUILD_opencv_python3=ON \
      -DPYTHON3_EXECUTABLE=$(which python3) \
      -DPYTHON3_NUMPY_INCLUDE_DIRS=$(python3 -c "import numpy; print(numpy.get_include())") \
      ..

# Build
make -j$(nproc)

# Install
sudo make install

Quick Start

Importing OpenCV

import cv2 as cv
import numpy as np
The module is imported as cv2 for historical reasons. This naming convention is standard across all OpenCV Python code.

Verify Installation

import cv2 as cv

print(f"OpenCV version: {cv.__version__}")
print(f"NumPy version: {np.__version__}")

# Check available modules
print(cv.getBuildInformation())

Core Concepts

NumPy Integration

OpenCV images are represented as NumPy arrays:
import cv2 as cv
import numpy as np

# Load image as NumPy array
img = cv.imread('image.jpg')

print(f"Image shape: {img.shape}")  # (height, width, channels)
print(f"Data type: {img.dtype}")    # uint8
print(f"Image size: {img.size}")    # total pixels

# Create blank image
blank = np.zeros((480, 640, 3), dtype=np.uint8)

# All NumPy operations work on images
img_float = img.astype(np.float32) / 255.0
mean_color = np.mean(img, axis=(0, 1))

Image Format: BGR vs RGB

OpenCV uses BGR color order by default, not RGB. Convert when working with other libraries like Matplotlib or PIL.
import cv2 as cv
import matplotlib.pyplot as plt

# Read image (BGR format)
img_bgr = cv.imread('image.jpg')

# Convert to RGB for matplotlib
img_rgb = cv.cvtColor(img_bgr, cv.COLOR_BGR2RGB)

plt.imshow(img_rgb)
plt.show()

Code Examples

Reading and Writing Images

import cv2 as cv

# Read image
img = cv.imread('input.jpg')

if img is None:
    print('Could not open or find the image')
    exit(0)

# Read in grayscale
gray = cv.imread('input.jpg', cv.IMREAD_GRAYSCALE)

# Save image
cv.imwrite('output.jpg', img)

# Save with quality settings (JPEG)
cv.imwrite('output.jpg', img, [cv.IMWRITE_JPEG_QUALITY, 90])

Video Capture and Display

import cv2 as cv

# Open webcam
cap = cv.VideoCapture(0)

# Or open video file
# cap = cv.VideoCapture('video.mp4')

if not cap.isOpened():
    print("Cannot open camera")
    exit()

while True:
    # Capture frame-by-frame
    ret, frame = cap.read()
    
    if not ret:
        print("Can't receive frame. Exiting...")
        break
    
    # Convert to grayscale
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    
    # Display the frame
    cv.imshow('frame', gray)
    
    # Press 'q' to quit
    if cv.waitKey(1) == ord('q'):
        break

# Release resources
cap.release()
cv.destroyAllWindows()

Face Detection

import cv2 as cv
import numpy as np

def detect_faces(img, cascade):
    """Detect faces in an image using Haar Cascade."""
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    gray = cv.equalizeHist(gray)
    
    faces = cascade.detectMultiScale(
        gray,
        scaleFactor=1.3,
        minNeighbors=4,
        minSize=(30, 30),
        flags=cv.CASCADE_SCALE_IMAGE
    )
    
    return faces

def draw_faces(img, faces):
    """Draw rectangles around detected faces."""
    for (x, y, w, h) in faces:
        cv.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)

# Load cascade classifier
cascade = cv.CascadeClassifier(
    cv.samples.findFile('haarcascades/haarcascade_frontalface_alt.xml')
)

# Open camera
cam = cv.VideoCapture(0)

while True:
    ret, img = cam.read()
    if not ret:
        break
    
    faces = detect_faces(img, cascade)
    draw_faces(img, faces)
    
    cv.imshow('facedetect', img)
    
    if cv.waitKey(5) == 27:  # ESC key
        break

cam.release()
cv.destroyAllWindows()

Image Processing Pipeline

import cv2 as cv
import numpy as np

# Read image
src = cv.imread('input.jpg')

# Convert to grayscale
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

# Apply Gaussian blur
blurred = cv.GaussianBlur(gray, (5, 5), 0)

# Edge detection
edges = cv.Canny(blurred, 50, 150)

# Find contours
contours, hierarchy = cv.findContours(
    edges, 
    cv.RETR_EXTERNAL, 
    cv.CHAIN_APPROX_SIMPLE
)

# Draw contours on original image
result = src.copy()
cv.drawContours(result, contours, -1, (0, 255, 0), 2)

# Save result
cv.imwrite('output.jpg', result)

Histogram Calculation and Visualization

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# Load image
src = cv.imread('image.jpg')

# Split into color channels
bgr_planes = cv.split(src)

# Calculate histograms
histSize = 256
histRange = (0, 256)

b_hist = cv.calcHist(bgr_planes, [0], None, [histSize], histRange)
g_hist = cv.calcHist(bgr_planes, [1], None, [histSize], histRange)
r_hist = cv.calcHist(bgr_planes, [2], None, [histSize], histRange)

# Plot histograms
plt.figure(figsize=(10, 6))
plt.plot(b_hist, color='b', label='Blue')
plt.plot(g_hist, color='g', label='Green')
plt.plot(r_hist, color='r', label='Red')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.legend()
plt.show()

Working with ROI (Region of Interest)

import cv2 as cv
import numpy as np

# Load image
img = cv.imread('image.jpg')

# Define ROI using NumPy slicing
height, width = img.shape[:2]
roi = img[100:300, 200:400]  # [y1:y2, x1:x2]

# Modify ROI
roi[:] = (0, 255, 0)  # Fill with green

# Copy ROI to another location
img[50:250, 450:650] = roi

# Create ROI mask
mask = np.zeros(img.shape[:2], dtype=np.uint8)
cv.circle(mask, (width//2, height//2), 100, 255, -1)

# Apply mask
masked_img = cv.bitwise_and(img, img, mask=mask)

cv.imshow('Result', masked_img)
cv.waitKey(0)

Image Transformations

import cv2 as cv
import numpy as np

img = cv.imread('image.jpg')

# Resize
resized = cv.resize(img, (640, 480))
# Or scale by factor
scaled = cv.resize(img, None, fx=0.5, fy=0.5)

# Rotate
height, width = img.shape[:2]
center = (width // 2, height // 2)
angle = 45
scale = 1.0

rotation_matrix = cv.getRotationMatrix2D(center, angle, scale)
rotated = cv.warpAffine(img, rotation_matrix, (width, height))

# Flip
flipped_horizontal = cv.flip(img, 1)
flipped_vertical = cv.flip(img, 0)
flipped_both = cv.flip(img, -1)

# Crop using NumPy slicing
cropped = img[100:400, 200:500]

Advanced Features

Working with Multiple Images

import cv2 as cv
import glob

# Process all images in a directory
image_paths = glob.glob('images/*.jpg')

for path in image_paths:
    img = cv.imread(path)
    
    # Apply processing
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    blurred = cv.GaussianBlur(gray, (5, 5), 0)
    
    # Save result
    output_path = path.replace('images/', 'output/')
    cv.imwrite(output_path, blurred)

Performance Tips

import cv2 as cv
import numpy as np
import time

# Use optimized NumPy operations
img = cv.imread('large_image.jpg')

# Efficient: Vectorized operation
start = time.time()
result = img * 0.5
print(f"Vectorized: {time.time() - start:.4f}s")

# Inefficient: Loop over pixels (avoid this!)
start = time.time()
result = img.copy()
for i in range(img.shape[0]):
    for j in range(img.shape[1]):
        result[i, j] = img[i, j] * 0.5
print(f"Loop: {time.time() - start:.4f}s")

# Use in-place operations when possible
img *= 0.5  # Modifies img directly, no new array

# Pre-allocate arrays
output = np.empty_like(img)
cv.cvtColor(img, cv.COLOR_BGR2GRAY, dst=output[:,:,0])

Package Structure

The Python bindings are organized to mirror the C++ API:
import cv2 as cv

# Core functionality
mat = cv.Mat()
version = cv.__version__

# Image processing
blurred = cv.GaussianBlur(img, (5, 5), 0)

# Video I/O
cap = cv.VideoCapture(0)

# Feature detection
orb = cv.ORB_create()

# DNN module
net = cv.dnn.readNet('model.onnx')

# Find sample data files
path = cv.samples.findFile('lena.jpg')

Common Issues

AttributeError: If you get “module ‘cv2’ has no attribute”, make sure you’re using the correct module name and that the feature is included in your OpenCV build.

Virtual Environments

# Create virtual environment
python -m venv opencv_env

# Activate
source opencv_env/bin/activate  # Linux/macOS
# or
opencv_env\Scripts\activate  # Windows

# Install OpenCV
pip install opencv-python

Resources

Next Steps