Skip to main content

OpenCV Calibration Audit

PyPI Version Python Versions License

Audit OpenCV checkerboard calibration datasets, reject weak or duplicate views, visualize image-plane coverage, calibrate a monocular pinhole camera, and create an explainable offline report.

Unlike a short cv2.calibrateCamera() script, this package inspects the input dataset first. It records why each image was accepted, warned, rejected, or unreadable and exports both human-readable and machine-readable evidence. Analysis is local and contains no telemetry or network requests.

Installation

python -m pip install opencv-calibration-audit

Python 3.10–3.13 is supported. The implementation uses findChessboardCornersSB. CI explicitly tests OpenCV 4.11.0.86 and the latest OpenCV 5.x release; the default dependency is the headless OpenCV wheel. Version 0.2.0 was the first functional audit MVP. Earlier 0.1.x packages were development scaffolds and should not be installed.

Five-minute quick start

calibration-audit analyze ./calibration_images \
  --cols 9 \
  --rows 6 \
  --square-size 30 \
  --unit mm \
  --output ./audit_result

--cols and --rows always mean inner corners, not squares. A target with 10 × 7 squares has 9 × 6 inner corners.

Example terminal summary:

Quality gates: PASSED
Accepted views: 12
OpenCV RMS: 0.284931 px
Report: audit_result/report.html

Useful stricter options:

calibration-audit analyze ./calibration_images \
  --cols 9 --rows 6 --square-size 30 --unit mm \
  --recursive \
  --min-valid-images 12 \
  --min-board-area 0.05 \
  --max-per-view-error 1.0 \
  --fail-on-warning \
  --output ./audit_result

The command will not overwrite a non-empty output directory unless --overwrite-output is supplied.

Example report

This report was generated from the three redistributable real-camera OpenCV fixtures included with the test suite:

calibration-audit analyze ./real_checkerboards \
  --cols 9 --rows 6 --square-size 30 --unit mm \
  --min-valid-images 3 --min-board-area 0.01 \
  --output ./audit_result
Quality gates: PASSED
Accepted views: 3
OpenCV RMS: 0.203403 px
Report: audit_result/report.html

Annotated per-image decisions in the v0.2.1 report

Open the self-contained example report or inspect its summary.json.

Python API

from pathlib import Path

from calibration_audit import AuditConfig, PatternSpec, audit_dataset

config = AuditConfig(
    pattern=PatternSpec(
        cols=9,
        rows=6,
        square_size=30.0,
        unit="mm",
    ),
    min_valid_images=12,
)

result = audit_dataset(
    image_directory=Path("./calibration_images"),
    config=config,
)

print(result.summary)
result.write_outputs(Path("./audit_result"))

Library functions raise typed CalibrationAuditError subclasses and never call sys.exit().

Output

audit_result/
├── report.html
├── summary.json
├── images.csv
├── calibration.yaml
├── accepted.txt
├── rejected.txt
├── report-manifest.json
└── assets/
    ├── coverage_heatmap.png
    ├── reprojection_errors.png
    └── thumbnails/

report.html embeds its charts, CSS, and annotated per-image previews and works offline without a CDN. Filenames and decision messages are escaped. Each image shows the decision stage, reason severity, message, measured value, and threshold or rule. summary.json contains typed reason codes, the OpenCV runtime version, configuration, dataset metrics, quality gates, calibration parameters, and per-image results. report-manifest.json identifies generator-owned files so overwrite removes stale assets without touching unrelated files. calibration.yaml uses an OpenCV-friendly matrix layout; it does not claim ROS camera-info compatibility.

What is measured

  • Detection rate: complete detections divided by readable images.
  • Sharpness: variance of Laplacian globally and inside the detected board. With no user threshold, only clear dataset-relative outliers are warned.
  • Exposure: mean grayscale intensity and near-black/near-white ratios.
  • Board geometry: normalized center, physical target area, rotation, signed perspective imbalance, and physical-boundary border distance. The physical boundary is estimated one square beyond the outer detected inner corners. The sharpness ROI remains the conservative inner-corner hull.
  • Coverage: occupied board-center cells in a 4 × 3 image-plane grid plus corner-observation density.
  • Diversity: board-area distribution, occupied scale bins, smallest circular rotation range, and horizontal/vertical perspective ranges. For example, 179° and -179° span approximately 2°; the four cardinal orientations span a smallest covering arc of 270°.
  • Duplicate pose: normalized position, log-area, rotation, and perspective thresholds. The sharper of two near-identical views is kept.
  • Calibration: OpenCV pinhole RMS, camera matrix, distortion coefficients, extrinsics, and per-view reprojection statistics.

Per-view reprojection RMSE is:

sqrt(mean((projected_x - observed_x)^2 + (projected_y - observed_y)^2))

Horizontal perspective is (top - bottom) / max(top, bottom) and vertical perspective is (left - right) / max(left, right), so their signs retain tilt direction. The coverage and diversity assessments are heuristics, not a calibration certificate. Sharpness values are especially dependent on resolution, target scale, focus, and lens characteristics.

The default near-duplicate component thresholds are: normalized center distance 0.03, absolute log-area distance 0.08, wrapped rotation distance 5°, and combined perspective distance 0.08. These are typed policy values in the Python API. The default relative-sharpness warning threshold is 0.35 × the dataset median.

Decisions and exit codes

Every rejection includes a stable reason code, severity, message, measured value, and relevant threshold. High reprojection-error views are flagged after the initial calibration and are not silently removed or recalibrated. Per-view reprojection error is in-sample: it is computed after fitting on the same accepted images and is not independent validation.

Code Meaning
0 Audit completed and quality gates passed
1 Audit completed but a configured quality gate failed
2 Invalid arguments or invalid input dataset
3 Unexpected processing/calibration failure

Tracebacks are hidden by default and shown only with --log-level DEBUG.

Input behavior

Supported formats are JPEG, PNG, BMP, TIFF, and WebP. Unsigned 8-bit inputs are analyzed directly. Unsigned 16-bit inputs, including TIFF, use the fixed mapping value / 257 to 8-bit analysis pixels; per-image min/max stretching is not used. Original dtype and bit depth remain in per-image metrics. Signed and floating-point images are rejected as unsupported.

Files are processed in deterministic sorted order. Unreadable images are reported individually. Mixed readable resolutions fail clearly and list their resolution groups. Source images are never deleted, moved, rewritten, or otherwise modified. Recursive discovery ignores symlinks that resolve outside the requested input tree and rejects any output path that resolves inside the input tree, preventing an earlier report from becoming calibration input.

Limitations

The MVP supports standard black-and-white checkerboards, monocular calibration, and the pinhole camera model. It does not support stereo or fisheye calibration, ChArUco/ArUco, circle grids, live capture, ROS output, a GUI, PDF reports, automatic view pruning, or input-file modification.

To generate a print-accurate target, use the companion opencv-chessboard-generator.

Development

python -m pip install -e ".[dev]"
ruff check .
mypy .
pytest --cov=calibration_audit --cov-report=term-missing
python -m build
twine check dist/*

CI tests Python 3.10–3.13 plus explicit OpenCV 4.11 and 5.x jobs. After a successful main CI run, auto-release.yml creates the version tag and GitHub Release when the version in pyproject.toml has not already been released. It then dispatches the separate release.yml PyPI Trusted Publishing workflow. Manually published GitHub Releases also trigger release.yml. Commits that retain an already released version are safely skipped.

License

MIT. See LICENSE.

Metadata

Release files for opencv-calibration-audit 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for opencv-calibration-audit 0.2.1
File Size Uploaded
opencv_calibration_audit-0.2.1.tar.gz 30.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for opencv-calibration-audit 0.2.1
File Interpreter ABI Platform
opencv_calibration_audit-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 63.6 kB

Release files / opencv_calibration_audit-0.2.1.tar.gz

Download URL opencv_calibration_audit-0.2.1.tar.gz
Size 30.9 kB
Tags Source
SHA-256 checksum
How to use checksums
84ee88f98905e01d81e37e2c6ff834ebf3eeada72e5832229eccb54992598ace
BLAKE2b-256 checksum
How to use checksums
1253992e817e0b8d956535db08c0f4a225d5999984b389c2a0472bb0b7a38e09
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.

Transparency log

Release files / opencv_calibration_audit-0.2.1-py3-none-any.whl

Download URL opencv_calibration_audit-0.2.1-py3-none-any.whl
Size 32.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9b4034f295f81d61d46f7c0cdc2c93ef2cf52e7bab04c4445c1029d47967198b
BLAKE2b-256 checksum
How to use checksums
dcb80ea2a0e5122ae34f24516af7900513a4b51ade3345a0d2f93014255ebbed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.2

2 release files

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page