visual-logging
A simple way to generate beautiful html logs with embedded images for CV purposes.
visual-logging piggybacks on the standard logging module and allows you to use the sick power of logging to debug your computer vision application on a whole new level: OpenCV images (well, technically numpy arrays), PIL images and matplotlib figures get embedded into your html logs as inline images.
You can read about it in detail in a great blog post visual-logging, my new favorite tool for debugging OpenCV and Python apps written by Adrian Rosebrock.
Installation
pip install visual-logging
No extra dependencies — whichever of OpenCV, PIL/Pillow and matplotlib you already have installed are picked up automatically (numpy arrays render through PIL when OpenCV isn't around). Requires Python 3.9+.
Usage example (see demo.py)
import logging
from vlogging import HTMLFileHandler, VisualRecord
import cv2 # or PIL.Image, or matplotlib — whatever you use
logger = logging.getLogger("demo")
logger.setLevel(logging.DEBUG)
logger.addHandler(HTMLFileHandler("test.html", title="My debug log"))
cv_image = cv2.imread("lenna.jpg")
logger.debug(VisualRecord(
"Hello from OpenCV", cv_image, "This is an OpenCV image", fmt="png"))
# Mix images of different origins in one record, downscale the big ones
# to at most 320x240 to keep the log small:
logger.warning(VisualRecord(
"Hello from all", [cv_image, pil_image, mpl_figure],
fmt="png", max_size=(320, 240)))
# Ordinary log calls work too, and land in the same page:
logger.info("Processed frame %d", 42)
logging.shutdown() # flushes and closes the html file
Open test.html in a browser and enjoy: HTMLFileHandler writes a styled, self-contained page — records are color-coded by log level with timestamps and logger names, plain messages are escaped, and exceptions logged with logger.exception(...) include their traceback. Records are flushed as they happen, so you can watch the page mid-run.
Everything composes the stdlib way: HTMLFileHandler is a logging.FileHandler that installs a VisualFormatter (a logging.Formatter) by default — use either piece on its own if you prefer. Passing a VisualRecord to a plain FileHandler still produces bare html fragments, exactly as in 1.x.
In Jupyter, a VisualRecord displays itself inline — no logging setup needed:
VisualRecord("Detected edges", edges_img, "Canny output")
VisualRecord arguments
| Argument | Meaning |
|---|---|
title |
Header of the log record |
imgs |
A single image or a list of images: OpenCV/numpy arrays, PIL images and matplotlib figures in any combination |
footnotes |
Optional text rendered as <pre> under the images |
fmt |
Image format to embed: png (default), jpeg, webp — anything your imaging library can encode |
max_size |
Optional (width, height) tuple: images bigger than that are downscaled proportionally before embedding (matplotlib figures by lowering the render dpi), to keep log files readable and small |
Changelog
2.0
- Modern packaging (
pyproject.toml), Python 3.9+ only,py.typedtype hints - New
HTMLFileHandler+VisualFormatter: styled, self-contained html pages with level colors, timestamps, escaped plain-text records and tracebacks - New
max_sizeoption to downscale embedded images (all renderers) VisualRecorddisplays inline in Jupyter notebooks- numpy arrays render via PIL when OpenCV is not installed
- Embedded images use
loading="lazy", so huge logs open fast - matplotlib support no longer relies on the deprecated
pylabmodule - Tests run on GitHub Actions against Python 3.9–3.13; releases publish to PyPI from tags via trusted publishing
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file visual_logging-2.0.tar.gz.
File metadata
- Download URL: visual_logging-2.0.tar.gz
- Upload date:
- Size: 7.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97ebdf80c1274ec9ceea1fc6c3ab170046ed46188b8fe7b0bb353555fb2e3ced
|
|
| MD5 |
589bea0ee131477365158bff3474452e
|
|
| BLAKE2b-256 |
b58952268c7dada531bfc5162f3641ecbee33e4032b815566f67df0afee17759
|
Provenance
The following attestation bundles were made for visual_logging-2.0.tar.gz:
Publisher:
publish.yml on dchaplinsky/visual-logging
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
visual_logging-2.0.tar.gz -
Subject digest:
97ebdf80c1274ec9ceea1fc6c3ab170046ed46188b8fe7b0bb353555fb2e3ced - Sigstore transparency entry: 2199550192
- Sigstore integration time:
-
Permalink:
dchaplinsky/visual-logging@1ede3c702528a23240f298d65ec2d36bdfff1b99 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/dchaplinsky
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1ede3c702528a23240f298d65ec2d36bdfff1b99 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file visual_logging-2.0-py3-none-any.whl.
File metadata
- Download URL: visual_logging-2.0-py3-none-any.whl
- Upload date:
- Size: 8.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2524193b971472326f6deaea9f50eb97ffc8deb08606a1e758a605bcfa4c86dd
|
|
| MD5 |
c67bb14c0ad36e20c413fae6affc64a5
|
|
| BLAKE2b-256 |
056df5d6be585b7dbbfabb4132497b03bac0fce6efadadd05a7fb212caf82e19
|
Provenance
The following attestation bundles were made for visual_logging-2.0-py3-none-any.whl:
Publisher:
publish.yml on dchaplinsky/visual-logging
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
visual_logging-2.0-py3-none-any.whl -
Subject digest:
2524193b971472326f6deaea9f50eb97ffc8deb08606a1e758a605bcfa4c86dd - Sigstore transparency entry: 2199550224
- Sigstore integration time:
-
Permalink:
dchaplinsky/visual-logging@1ede3c702528a23240f298d65ec2d36bdfff1b99 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/dchaplinsky
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1ede3c702528a23240f298d65ec2d36bdfff1b99 -
Trigger Event:
workflow_dispatch
-
Statement type: