Vision Systems & Engineering

OpenCV

The open-source C++ library of computer vision and image processing functions, with Python bindings that work on NumPy arrays; its modules, conventions, versions from 1.0 to 5.0, contrib modules and licence.

beginner

OpenCV (Open Source Computer Vision Library) is a library of computer vision and image processing functions, written in C++ with bindings for Python, Java and JavaScript. It began at Intel in 1999 and was developed with support from Willow Garage and the company Itseez. It is distributed under the Apache 2 licence from version 4.5.0 and under a BSD licence before that. In Python it is the package cv2, whose functions take and return NumPy arrays. It covers filtering, colour conversion, geometric transforms, contours, feature detection and matching, camera calibration, stereo, optical flow, object detection and inference with trained neural networks.

This article is about the library: its modules, how the Python bindings map onto NumPy, the conventions that catch new users, and the history of its versions and licence. The methods it implements are explained in their own articles, such as image filtering, the Canny edge detector and camera calibration. Every version statement and example here was checked against OpenCV 5.0.0 (released 6 June 2026) and the opencv-python 5.0.0.93 wheel, as of October 2026. The official documentation at docs.opencv.org could not be read by automated access while this article was written, so the API statements come from the header files and documentation sources in the repository at the 5.0.0 tag.

Purpose

Gary Bradski, then a researcher in Intel’s Microprocessor Research Laboratory, introduced the library in a November 2000 article. He described it as aimed at making computer vision accessible to programmers working on real-time human-computer interaction and mobile robotics, and wrote that it shipped with source code and hand-tuned assembly-language binaries for Intel processors, so that users could both learn from it and use its performance. It then had more than 500 functions, mostly in C, and covered segmentation, detection, recognition and tracking of objects, people and faces, camera calibration, stereo vision and 2D and 3D shape reconstruction. The evolution proposal for the later change to Apache 2 explains the choice of a permissive licence: it says the GPL was not appropriate for OpenCV because the project wanted to accelerate commercial applications as well as research.

Its modules serve three kinds of use. Most of them are a toolbox of classical algorithms with optimized implementations. A few (imgcodecs, videoio, highgui) are the input and output layer of a vision program, reading images, video files and camera streams and displaying results. And the dnn module is an inference runtime that runs trained networks, from ONNX and other formats, without a deep-learning framework.

Core Capabilities

OpenCV is split into modules, each a separate library in C++ and a header such as opencv2/imgproc.hpp. The modules in the main repository at the 5.0.0 tag are:

Module Contents (5.0.0)
core The n-dimensional array cv::Mat, basic types, arithmetic, linear algebra, the discrete Fourier transform, file storage (XML, YAML, JSON)
imgproc Linear and non-linear filtering, morphology, geometric transforms (resize, affine and perspective warps, remapping), colour conversion, histograms, edges, contours, drawing
imgcodecs Reading and writing image files
videoio Reading video files and camera streams, writing video
highgui Simple windows, trackbars and mouse events
video Optical flow, background subtraction, object tracking
features Feature detectors, descriptors and matchers (named features2d before 5.0)
flann Approximate nearest-neighbour search
geometry 2D and 3D geometry: homographies, pose from points, robust estimation, convex hulls, polygon fitting (split from calib3d and imgproc in 5.0)
calib Camera and stereo calibration (from calib3d)
stereo Stereo correspondence (from calib3d)
ptcloud Point clouds, visual odometry, volume (TSDF) integration (new in 5.0)
objdetect QR and barcode readers, ArUco and ChArUco markers, a neural face detector
dnn Loading and running trained neural networks
photo Denoising, inpainting, HDR, colour correction
stitching Panorama stitching

The repository also holds the language bindings (python, java, js, objc), a test framework (ts) and world, an option that builds all modules into one library. The 5.0 summary and migration guide give the reorganization: the calib3d module of 2.x to 4.x was split into geometry, calib, stereo and ptcloud; features2d was renamed features and gained learned local features (ALIKED and DISK) and an Annoy-based nearest-neighbour index; the machine-learning module ml and the graph engine G-API moved to the contrib repository; and the Haar cascade and HOG detectors (CascadeClassifier, HOGDescriptor), which the Viola–Jones and histogram of oriented gradients articles describe, moved to the contrib module xobjdetect. In C++, the old header opencv2/calib3d.hpp still exists and includes geometry.hpp, calib.hpp and stereo.hpp. In Python, a function exported to the bindings stays at cv2.<name> whatever module it now lives in; the header parser skips declarations not marked for export, so calibrateHandEye and calibrateRobotWorldHandEye, declared in calib.hpp with plain CV_EXPORTS, are absent from cv2 in the 5.0.0.93 wheel.

The modules map onto most of the classical methods on this site. imgproc holds the Gaussian filter, bilateral filter and median filter, the Sobel operator, mathematical morphology, histogram equalization, thresholding, the watershed transform, image pyramids, image warping and the Harris corner detector. features holds SIFT and ORB for feature detection and feature matching. geometry estimates a homography, solves Perspective-n-Point and runs RANSAC. calib implements camera calibration from images of a known target, with models of lens distortion. stereo has block matching and semi-global matching. video has the pyramidal Lucas–Kanade tracker for optical flow estimation. photo has non-local means denoising. The cv::Mat array itself is a digital image in memory: rows, columns, channels and a fixed element type.

The dnn module loads models in ONNX, TensorFlow and TensorFlow Lite formats in 5.0.0, prepares inputs with blobFromImage and runs them. OpenCV 5.0 added a second inference engine, which the release summary says handles dynamic shapes and subgraphs better and runs on the CPU only; readNet tries it first and falls back to the older engine, and an ONNX Runtime back end can be compiled in. The Caffe and Darknet readers were removed in 5.0.

Minimal Example

The example runs a classical pipeline on a rendered image with known ground truth. NumPy renders a white card with a checkerboard, seen in perspective, adds Gaussian noise, and OpenCV finds the card and rectifies it: Gaussian smoothing, Canny edges, the outer contour (by the border-following algorithm of Suzuki and Abe, which findContours uses in this mode), a polygon fit by the Douglas–Peucker algorithm, sub-pixel corner refinement and a perspective warp. The functions come from two modules, which makes no difference in Python: GaussianBlur, Canny, dilate, findContours, cornerSubPix and warpPerspective are in imgproc, while contourArea, arcLength, approxPolyDP and getPerspectiveTransform are in geometry. The run used OpenCV 5.0.0 (opencv-python 5.0.0.93) and NumPy 2.5.4, and printed the same output twice.

import cv2
import numpy as np

print("OpenCV", cv2.__version__, "| NumPy", np.__version__)

# Render a 640x480 scene with NumPy: a 300x200 card with a checkerboard,
# seen in perspective. H_true maps card coordinates (u, v) to image (x, y).
W, H = 300, 200
card = np.float32([[0, 0], [W, 0], [W, H], [0, H]])
true_corners = np.float32([[150, 90], [470, 130], [430, 380], [120, 330]])
H_true = cv2.getPerspectiveTransform(card, true_corners)

def pattern(u, v):   # white card, 25-pixel margin, 5x3 checkerboard inside
    inside = (u >= 0) & (u < W) & (v >= 0) & (v < H)
    board = (u >= 25) & (u < W - 25) & (v >= 25) & (v < H - 25)
    dark = board & ((((u - 25) // 50).astype(int) + ((v - 25) // 50).astype(int)) % 2 == 1)
    return np.where(inside, np.where(dark, 60.0, 220.0), 20.0)

ss = 4  # 4x4 samples per pixel; OpenCV puts pixel centres at integer (x, y)
ys, xs = (np.mgrid[0:480 * ss, 0:640 * ss] + 0.5) / ss - 0.5
pts = np.stack([xs, ys, np.ones(xs.shape)], -1)
uvw = pts @ np.linalg.inv(H_true).T
img = pattern(uvw[..., 0] / uvw[..., 2], uvw[..., 1] / uvw[..., 2])
img = img.reshape(480, ss, 640, ss).mean(axis=(1, 3))

def noisy(seed):
    rng = np.random.default_rng(seed)
    return np.clip(img + rng.normal(0, 8, img.shape), 0, 255).astype(np.uint8)

def find_card(gray, verbose=False):
    # Classical pipeline: smooth, edges, outer contour, quadrilateral, corners.
    blur = cv2.GaussianBlur(gray, (5, 5), 1.2)
    edges = cv2.Canny(blur, 50, 150)
    closed = cv2.dilate(edges, np.ones((3, 3), np.uint8))   # close 1-pixel gaps
    contours, _ = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    big = max(contours, key=cv2.contourArea)
    quad = cv2.approxPolyDP(big, 0.02 * cv2.arcLength(big, True), True).reshape(-1, 2)
    # Order the corners TL, TR, BR, BL from x + y and y - x (points are (x, y)).
    s, d = quad.sum(1), np.diff(quad, axis=1).ravel()
    rough = np.float32([quad[s.argmin()], quad[d.argmin()],
                        quad[s.argmax()], quad[d.argmax()]])
    found = cv2.cornerSubPix(blur, rough.reshape(-1, 1, 2).copy(), (5, 5), (-1, -1),
                             (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 50, 0.01))
    if verbose:
        print("edge pixels:", int((edges > 0).sum()), "| outer contours:", len(contours),
              "| polygon vertices:", len(quad))
        print("corner errors (px), polygon:     ",
              np.round(np.linalg.norm(rough - true_corners, axis=1), 2))
    return found.reshape(-1, 2)

gray = noisy(0)
print("image shape (rows, cols):", gray.shape, gray.dtype)
found = find_card(gray, verbose=True)
print("corner errors (px), cornerSubPix:",
      np.round(np.linalg.norm(found - true_corners, axis=1), 2))

H_est = cv2.getPerspectiveTransform(found, card)
rectified = cv2.warpPerspective(gray, H_est, (W, H))       # dsize is (width, height)
vs, us = np.mgrid[0:H, 0:W]
truth = pattern(us, vs)
diff = np.abs(rectified.astype(float) - truth)
print("rectified shape:", rectified.shape, "| |error| median %.1f, 99th percentile %.1f"
      % (np.median(diff), np.percentile(diff, 99)))

worst = [np.linalg.norm(find_card(noisy(k)) - true_corners, axis=1).max() for k in range(20)]
print("worst corner error over noise seeds 0-19: %.2f to %.2f px" % (min(worst), max(worst)))
OpenCV 5.0.0 | NumPy 2.5.4
image shape (rows, cols): (480, 640) uint8
edge pixels: 2703 | outer contours: 1 | polygon vertices: 4
corner errors (px), polygon:      [1. 1. 1. 1.]
corner errors (px), cornerSubPix: [0.31 0.29 0.28 0.22]
rectified shape: (200, 300) | |error| median 4.0, 99th percentile 89.0
worst corner error over noise seeds 0-19: 0.27 to 0.41 px

The Canny edges include the checkerboard’s inner edges, but RETR_EXTERNAL keeps only outer boundaries, so a single contour comes back, and the Douglas–Peucker fit reduces it to four vertices. The polygon’s corners are exactly one pixel off. Our reading is that the dilation that closes small gaps in the edge map moves the outer boundary one pixel outwards, so the integer contour lies just outside the card. cornerSubPix then moves each corner to the point from which the vectors to its neighbours are orthogonal to the image gradients there, as its documentation describes, and the error falls to about a third of a pixel; over 20 noise seeds the worst corner ranged from 0.27 to 0.41 pixels. The rectified card matches the noise-free pattern to a median of 4 grey levels. The added noise alone has a median absolute value of about 5.4 (0.674σ0.674\sigma for σ=8\sigma = 8), and we read the smaller residual as the effect of bilinear interpolation, which averages neighbouring pixels. The large errors in the tail are expected along the checkerboard’s edges, where an interpolated pixel mixes the two grey levels and the point-sampled reference takes one of them (also our reading).

With four corners getPerspectiveTransform solves the homography exactly. With more correspondences, for example matched features, findHomography fits it by least squares or robustly with RANSAC and its variants; the homography article derives the estimation. The renderer puts pixel centres at integer coordinates because that is how warpPerspective samples (its documented formula evaluates the source at the mapped integer destination coordinates); rendering with centres at half-integers would have added a constant half-pixel offset to every corner.

Conventions and Pitfalls

Three conventions differ from those of NumPy, Pillow or many deep-learning pipelines.

Channel order. The imgcodecs documentation states that decoded colour images have their channels in B, G, R order (the 5.0.0 header also defines a flag, IMREAD_COLOR_RGB, that asks for R, G, B instead), and drawing functions and colour constants follow the same order. The order goes back to the first release: the example code in Bradski’s 2000 article creates its colour images through the Intel Image Processing Library with the colour model “RGB” and the channel sequence “BGR”. Rows and columns. A cv::Mat is indexed by row and column, so a NumPy image has shape (height, width, channels), but points and sizes passed to functions are (x, y) and (width, height): the core documentation’s example creates a 1920 × 1080 image as Size(1920, 1080) with 1,920 columns and 1,080 rows. Saturation. When the result of an operation on 8- or 16-bit data falls outside the type’s range, OpenCV rounds it and clamps it to the range, I=min⁡(max⁡(round⁡(r),0),255)I = \min(\max(\operatorname{round}(r), 0), 255) for 8-bit data, rather than keeping the low bits; the core documentation calls this saturation arithmetic, used throughout the library, and notes that it is not applied to 32-bit integer results. NumPy integer arithmetic wraps around instead.

import io
import cv2
import numpy as np
from PIL import Image

# 1. Channel order: OpenCV reads, writes and draws colour images as B, G, R.
img = np.zeros((2, 3, 3), np.uint8)              # 2 rows, 3 columns, 3 channels
cv2.rectangle(img, (0, 0), (0, 1), (0, 0, 255), -1)   # "red" in BGR, column x = 0
print("pixel [0, 0] stored as", img[0, 0], "(B, G, R)")
ok, png = cv2.imencode(".png", img)
print("PNG decoded by OpenCV:", cv2.imdecode(png, cv2.IMREAD_COLOR)[0, 0],
      "| by Pillow (RGB):", np.asarray(Image.open(io.BytesIO(png.tobytes())))[0, 0])
print("gray, read as BGR:", cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)[0, 0],
      "| same array mislabelled RGB:", cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)[0, 0])
rgb = img[..., ::-1]                              # a view with reversed channels
try:
    cv2.circle(rgb, (1, 1), 1, (255, 0, 0), -1)   # in-place call on a strided view
except cv2.error as e:
    print("drawing on the view:", e.err.splitlines()[1].lstrip(" >-"))
cv2.circle(np.ascontiguousarray(rgb), (1, 1), 1, (255, 0, 0), -1)
print("after np.ascontiguousarray: drawing works")

# 2. Shapes are (rows, cols) = (height, width); points and sizes are (x, y) = (width, height).
small = cv2.resize(np.zeros((480, 640), np.uint8), (320, 240))
print("resize to dsize (320, 240) gives shape", small.shape)

# 3. Saturation: OpenCV clamps to the type's range, NumPy wraps around.
a = np.array([[200, 50]], np.uint8)
b = np.array([[100, 100]], np.uint8)
print("NumPy a + b:", a + b, " cv2.add:", cv2.add(a, b))
print("NumPy a - b:", a - b, " cv2.subtract:", cv2.subtract(a, b))
print("cv2.add of two int64 arrays returns", cv2.add(np.int64([[1]]), np.int64([[1]])).dtype)
pixel [0, 0] stored as [  0   0 255] (B, G, R)
PNG decoded by OpenCV: [  0   0 255] | by Pillow (RGB): [255   0   0]
gray, read as BGR: 76 | same array mislabelled RGB: 29
drawing on the view: Layout of the output array img is incompatible with cv::Mat
after np.ascontiguousarray: drawing works
resize to dsize (320, 240) gives shape (240, 320)
NumPy a + b: [[ 44 150]]  cv2.add: [[255 150]]
NumPy a - b: [[100 206]]  cv2.subtract: [[100   0]]
cv2.add of two int64 arrays returns int32

The PNG file holds a red pixel: Pillow, which works in RGB, decodes it as (255, 0, 0), while OpenCV hands back the same pixel as (0, 0, 255). Nothing in the array records which order it is in, so a wrong label gives no error, only wrong values: the grey level of pure red is 0.299×255≈760.299 \times 255 \approx 76 by the documented weights Y=0.299R+0.587G+0.114BY = 0.299R + 0.587G + 0.114B, and treating the BGR array as RGB weights the red channel as blue and gives 29. The same mistake feeds a network trained on RGB images with red and blue swapped; blobFromImage has swapRB=False as its default, so a BGR frame reaches the model as BGR unless the caller asks for the swap.

Reversing channels with [..., ::-1] makes a NumPy view with a negative stride. The binding code in cv2_convert.cpp copies an input array whose layout cv::Mat cannot represent, which costs time but works, and refuses an output array with such a layout, since writing into a copy would not reach the caller’s data; that is the error the drawing call raises. np.ascontiguousarray makes a contiguous copy, so drawing works but changes the copy, not img. The same code converts 64-bit integer arrays to 32-bit on input, which is why the last line reports int32; values outside the 32-bit range would not survive. The resize line shows the order of dsize, and the saturation lines show 200 + 100 clamping to 255 and 50 − 100 to 0, where NumPy gives 44 and 206.

Ecosystem and Integrations

Python bindings. The cv2 module is generated at build time: a header parser reads the C++ declarations marked for export (CV_EXPORTS_W, CV_WRAP) and a generator writes the wrapper code. Arrays cross the boundary as NumPy arrays (Harris et al. describe the array model), usually without copying when the layout allows it. The 2.1 change log (April 2010) credits James Bowman with the new-style Python wrappers, and the 2.2 change log (December 2010) describes wrappers that cover much more of the 2.x API, need NumPy and take and return ordinary NumPy arrays; the 2.3 beta of June 2011 calls them the cv2 module. The OpenCV-Python tutorials, started by Abid Rahman K. in Google Summer of Code 2013, ship with the library’s documentation.

Packages. The official wheels on PyPI come in four variants that share the cv2 name and must not be installed together: opencv-python (main modules), opencv-contrib-python (main and contrib modules), and headless versions of both without GUI dependencies, for servers and containers. The packaging scripts are under the MIT licence; the wheels also include FFmpeg under the LGPL 2.1, and the non-headless Linux wheels include Qt under the LGPL 3 (README at tag 93, as of October 2026). The 5.0.0.93 release declares Python 3.6 or later (its binary wheels are built for CPython 3.7 and later) and requires NumPy 2 or later on Python 3.9 and newer.

opencv_contrib. The separate repository of extra modules opened with OpenCV 3.0 (alpha August 2014, final June 2015). Its README describes it as the place where new modules, often with unstable APIs and less testing, are developed before they mature and move into the main repository; it is built in by pointing CMake’s OPENCV_EXTRA_MODULES_PATH at it. The dnn module took that path, moving into the main repository in OpenCV 3.3 (August 2017). At the 5.0.0 tag the contrib repository has 62 modules, among them the CUDA modules (cudaarithm, cudafilters, cudaimgproc, cudaoptflow, cudastereo and others), xfeatures2d (SURF, BRIEF, FREAK, DAISY and other descriptors), ximgproc (edge-aware filters), tracking, optflow, sfm, text, face, ml, gapi and xobjdetect. Patented algorithms such as SURF build only with the CMake option OPENCV_ENABLE_NONFREE, which is off by default, and the PyPI wheels do not include them. SIFT moved from contrib to the main repository in 4.4.0 (July 2020); the change log gives the expiry of its patent as the reason.

Acceleration and other languages. Since 3.0, the Transparent API lets ordinary functions run through OpenCL when they are given a cv::UMat instead of a cv::Mat. Each build records the instruction sets, acceleration libraries and image and video back ends it was compiled with; cv2.getBuildInformation() prints them (for the wheel used here, NEON code paths for the Arm CPU and FFmpeg and AVFoundation for video), which is worth checking when an expected codec or back end is missing. Besides Python, the repository builds Java bindings (used on Android), Objective-C bindings and OpenCV.js, which Emscripten compiles to WebAssembly or asm.js to run in web browsers.

Alternatives

Several libraries cover parts of what OpenCV does; which fits depends on the task, and this article does not rank them.

  • scikit-image is an image processing library with a Python API, released under the Modified BSD licence, which its authors describe as implementing algorithms and utilities for research, education and industry.
  • Pillow, a fork of the Python Imaging Library, provides extensive file format support and image processing functions, and decodes colour images in RGB order, as the conventions example shows.
  • Kornia implements differentiable image transformations, camera calibration, epipolar geometry, filtering and edge detection on PyTorch tensors, so that they can be inserted inside neural networks. Its authors, among them Gary Bradski, describe it as inspired by OpenCV (in the arXiv abstract of their paper).

Commercial machine-vision libraries are a further class.

Versions and Compatibility

History

The OpenCV-Python tutorial’s history, in the repository at 5.0.0, says that OpenCV was started at Intel in 1999 by Gary Bradski with a first release in 2000, that Vadim Pisarevsky joined him to manage Intel’s Russian OpenCV team, that the library was used on Stanley, the vehicle that won the 2005 DARPA Grand Challenge, and that development later continued with the support of Willow Garage, the robotics company, under Bradski and Pisarevsky. (The tutorial spells the name “Bradsky”; the 2000 article is signed Gary Bradski.) The version 2.1 change log of April 2010 records the move of the code repository from SourceForge to code.ros.org, and the meeting notes of July 2011 record three teams at Itseez working on OpenCV alongside new functionality developed at Willow Garage. The COPYRIGHT file at 5.0.0 lists the organizations that hold copyright in the code, with years, among them Intel (2000–2022), Willow Garage (2009–2011), Itseez (2008–2016), NVIDIA (2009–2016), AMD (2010–2013), the OpenCV Foundation (2015–2023) and OpenCV AI (2023–2025).

The main versions, from the official change logs and GitHub releases:

Version Date Main changes
1.0 October 2006 The C API of the 1.x series: structures such as IplImage and CvMat, functions with the cv prefix such as cvFindContours
2.0 September 2009 New C++ interface (cv::Mat, automatic memory management) for most functions; new Python interface
2.2 December 2010 Split into the modules core, imgproc, highgui, ml, features2d, video, objdetect, calib3d, flann and others; NumPy-based Python wrappers
3.0 June 2015 (alpha August 2014) opencv_contrib repository; Transparent API (OpenCL through UMat); Python 3 support; bundled subset of Intel IPP
3.3 August 2017 dnn moved from contrib to the main repository
4.0 November 2018 C++11 required; much of the 1.x C API removed; ONNX importer in dnn; G-API module
4.4 July 2020 SIFT moved to the main repository
4.5 October 2020 Licence changed from 3-clause BSD to Apache 2
5.0 June 2026 (alpha December 2024) C++17 and Python 3 required; C API removed; calib3d split and features2d renamed; ml, G-API, Haar and HOG detectors moved to contrib; new types (bfloat16, unsigned and signed 64-bit, unsigned 32-bit, bool) and true 0D and 1D arrays; new DNN engine

Older series were maintained alongside new ones: the 2.4 series has GitHub releases up to 2.4.13.6 (February 2018), and the change logs record 3.4.x releases next to 4.x up to 3.4.20 (June 2023). As of October 2026 both 4.x and 5.x are maintained; the newest releases are 5.0.0 (6 June 2026) and 4.14.0 (19 July 2026), and the 5.0 summary says that improvements developed on 4.x are backported to 5.x.

Moving from 4.x to 5.0

For Python code most of the 5.0 changes are invisible, since exported functions remain at cv2.<name>. The migration guide lists the changes that are not:

  • cv2.ml, cv2.CascadeClassifier and cv2.HOGDescriptor exist only in builds with contrib (in the opencv-python 5.0.0.93 wheel all three are absent);
  • readNetFromCaffe and readNetFromDarknet are gone, and models must be converted to ONNX;
  • a one-dimensional NumPy array passed as an input array now becomes a 1D Mat rather than an N × 1 column, which can change the shape of results;
  • nearest-neighbour resize now follows Pillow’s rounding, so INTER_NEAREST and INTER_NEAREST_EXACT agree, and the bilinear and bicubic modes of warpAffine, warpPerspective and remap no longer use lookup tables, so their output differs slightly from 4.x;
  • putText with the legacy FONT_HERSHEY_* constants now draws with a TrueType renderer and an embedded font (Rubik), so text looks different;
  • VideoCapture.get returns −1 instead of 0 for a property the back end does not support.

The guide warns that pixel-exact test baselines recorded with 4.x may need to be regenerated for the resize and warp changes. C++ code needs a C++17 compiler.

Licence

The library was distributed under a BSD licence from Intel’s release in 2000, according to the evolution proposal for the change, and from 4.5.0 (October 2020) under the Apache License 2.0. The LICENSE file is the 3-clause BSD licence at the 4.4.0 tag and the Apache License 2.0 at 4.5.0 and 5.0.0; the 4.5.0 change log says that all later 4.x and 5.x releases are distributed under Apache 2 and that 3.x would keep the BSD licence. The proposal gives the reason for the change: BSD says nothing about patents, while Apache 2, in the proposal’s informal reading, grants users a licence to contributors’ patents in their contributions and ends that grant for anyone who brings a patent claim over the software. The proposal adds that Apache 2, like BSD, puts no restrictions on the licence of software that depends on the library. Third-party code bundled in binary packages keeps its own licence, as the FFmpeg and Qt notes under Packages show, and patented algorithms in the contrib modules remain behind the non-free build option.

Limitations

  • Breadth over uniformity. Each function supports only some element types and channel counts, and the core documentation says the more complex an algorithm, the fewer formats it accepts (colour conversion supports 8-bit, 16-bit unsigned and 32-bit float data; linear algebra only floating point). Errors appear at run time as cv2.error exceptions, not as type errors before the call.
  • Silent conventions. BGR order, (x, y) points against (row, column) indexing, and saturation are not recorded in the NumPy array, so mixing OpenCV with libraries that use other conventions gives wrong values rather than errors, as the conventions example shows.
  • Inference, not training. The dnn module is an inference engine for networks trained elsewhere, which reach it as ONNX, TensorFlow or TensorFlow Lite files, and as of 5.0.0 its new engine runs on the CPU only; GPU inference needs the classic engine or the ONNX Runtime back end.
  • Contrib quality. Modules in opencv_contrib may have unstable APIs and less testing, by the repository’s own description, and the CUDA modules are among them.
  • Version drift. Module names, defaults and numerical results change between major versions, as the 4.x to 5.0 list above shows, and older material targets older versions: the OpenCV-Python tutorials in the 5.0.0 repository still say they are mainly focused on 3.x. Results that must be reproduced should record the exact OpenCV version and the output of cv2.getBuildInformation(), which lists the optimized code paths and libraries the build uses.

Related

  • Image Filtering

    Computing each output pixel from a neighborhood of input pixels, the family of operations behind smoothing, sharpening, edge detection, and denoising.

  • Edge Detection

    Locating the pixels where image intensity changes sharply, from derivative filters and the Canny detector to learned boundary detectors evaluated against human annotations.

  • Feature Detection

    Finding distinctive, repeatable points and regions in an image, such as corners, blobs, and stable regions, so that the same scene locations can be found again in other images.

  • Camera Calibration

    Estimating a camera's intrinsic parameters, lens distortion, and pose from images of a target with known geometry, usually by a closed-form initialization followed by minimizing reprojection error.

  • Homography

    An invertible projective transformation of the plane, a 3×3 matrix defined up to scale, that relates two images of a planar scene or two images taken by a camera rotating about its center.

  • Digital Image

    A digital image is a grid of samples of a continuous scene, each quantized to a finite set of values and stored as an array of numbers.

References

  1. Bradski, G. (2000). The OpenCV Library. Dr. Dobb's Journal of Software Tools, November 2000 (archived copy of 19 December 2014).
  2. OpenCV (2026). OpenCV 5.0.0 release, GitHub release page, 6 June 2026.
  3. OpenCV (2026). Introduction (core concepts: modules, memory management, saturation arithmetic, pixel types), modules/core/doc/intro.markdown, OpenCV 5.0.0 source code.
  4. OpenCV (2026). Introduction to OpenCV-Python Tutorials, doc/py_tutorials/py_setup/py_intro/py_intro.markdown, OpenCV 5.0.0 source code.
  5. OpenCV wiki. OpenCV 5 (release summary), as of 28 October 2026.
  6. OpenCV wiki. OpenCV 4 to 5 migration guide, as of 28 October 2026.
  7. OpenCV wiki. OpenCV Change Logs (4.11 to 4.14 and 5.0), as of 28 October 2026.
  8. OpenCV wiki. OpenCV Change Logs v2.2–v4.10.
  9. OpenCV wiki. OpenCV Change Logs v1.0–v2.1.
  10. OpenCV wiki. OpenCV meeting notes for 2011.
  11. Pisarevsky, V. OE-32: Change OpenCV License to Apache 2. OpenCV evolution proposal, OpenCV wiki.
  12. OpenCV (2020). LICENSE (3-clause BSD), OpenCV 4.4.0 source code.
  13. OpenCV (2020). LICENSE (Apache License 2.0), OpenCV 4.5.0 source code.
  14. OpenCV (2026). LICENSE (Apache License 2.0), OpenCV 5.0.0 source code.
  15. OpenCV (2026). COPYRIGHT, OpenCV 5.0.0 source code.
  16. OpenCV (2026). Module directory, modules/, OpenCV 5.0.0 source code.
  17. OpenCV (2026). Repository for OpenCV's extra modules (README and modules), opencv_contrib 5.0.0 source code.
  18. OpenCV (2026). Image processing declarations and documentation (Canny, findContours, warpPerspective, resize), modules/imgproc/include/opencv2/imgproc.hpp, OpenCV 5.0.0 source code.
  19. OpenCV (2026). 2D geometry declarations and documentation (approxPolyDP, getPerspectiveTransform), modules/geometry/include/opencv2/geometry/2d.hpp, OpenCV 5.0.0 source code.
  20. OpenCV (2026). Image file reading and writing (imgcodecs) declarations and documentation, modules/imgcodecs/include/opencv2/imgcodecs.hpp, OpenCV 5.0.0 source code.
  21. OpenCV (2026). Color conversions, modules/imgproc/doc/colors.markdown, OpenCV 5.0.0 source code.
  22. OpenCV (2026). NumPy array to cv::Mat conversion in the Python bindings, modules/python/src2/cv2_convert.cpp, OpenCV 5.0.0 source code.
  23. OpenCV (2026). Python binding generator and header parser, modules/python/src2/gen2.py and hdr_parser.py, OpenCV 5.0.0 source code.
  24. OpenCV (2026). DNN module declarations (blobFromImage, readNet functions), modules/dnn/include/opencv2/dnn/dnn.hpp, OpenCV 5.0.0 source code.
  25. OpenCV (2026). opencv-python packaging README (package variants, licensing), opencv-python repository, tag 93 (opencv-python 5.0.0.93).
  26. Harris, C. R., Millman, K. J., van der Walt, S. J., Gommers, R., Virtanen, P., Cournapeau, D., Wieser, E., Taylor, J., Berg, S., Smith, N. J., et al. (2020). Array programming with NumPy. Nature, 585(7825), 357–362.
  27. Suzuki, S. & Abe, K. (1985). Topological Structural Analysis of Digitized Binary Images by Border Following. Computer Vision, Graphics, and Image Processing, 30(1), 32–46.
  28. Douglas, D. H. & Peucker, T. K. (1973). Algorithms for the Reduction of the Number of Points Required to Represent a Digitized Line or its Caricature. Cartographica, 10(2), 112–122.
  29. van der Walt, S., Schönberger, J. L., Nunez-Iglesias, J., Boulogne, F., Warner, J. D., Yager, N., Gouillart, E., Yu, T. & the scikit-image contributors (2014). scikit-image: image processing in Python. PeerJ, 2, e453.
  30. Riba, E., Mishkin, D., Ponsa, D., Rublee, E. & Bradski, G. (2020). Kornia: an Open Source Differentiable Computer Vision Library for PyTorch. IEEE Winter Conference on Applications of Computer Vision (WACV), 3663–3672.
  31. Riba, E., Mishkin, D., Ponsa, D., Rublee, E. & Bradski, G. (2019). Kornia: an Open Source Differentiable Computer Vision Library for PyTorch. arXiv:1910.02190 (abstract).
  32. Pillow (2026). Pillow README, python-pillow/Pillow repository, version 13.0.0.