Skip to main content

A opinionated tool for coercing data into something displayable

Project description

img-show

img-show is a thin, opinionated wrapper around OpenCV for displaying images. It accepts NumPy arrays, PyTorch tensors, and PIL images; auto-coerces shapes, dtypes, and channel orders; resizes windows to fit the screen; alpha-composites RGBA over a checkerboard; and renders inline as PNG when running inside a Jupyter notebook.

Installation

img-show depends only on NumPy at install time. OpenCV is selected through one of four mutually-exclusive extras so you can match it to your environment (desktop, server, or contrib build):

pip install img-show[opencv]                  # standard build with GUI
pip install img-show[opencv-contrib]          # standard + contrib modules
pip install img-show[opencv-headless]         # no GUI (servers, CI, Jupyter-only)
pip install img-show[opencv-contrib-headless] # headless + contrib modules

Pick exactly one. The extras are mutually exclusive at the resolver level (uv enforces this via a conflicts entry); installing two OpenCV variants side-by-side results in a broken cv2 import.

If you already manage cv2 yourself (for example with a system package or a custom wheel), install the bare package:

pip install img-show

img-show will detect the existing cv2 import at runtime.

Requirements

  • Python >= 3.10
  • NumPy >= 1.24.4
  • OpenCV >= 4.5.4.60 (provided by one of the extras above)
  • Tkinter (used only to query screen size; if unavailable a 1920x1080 fallback is used)

Optional dependencies

  • PIL / Pillow — enables passing PIL.Image.Image objects directly; not required for NumPy or PyTorch inputs.
  • PyTorch — enables passing torch.Tensor objects directly.
  • IPython — required only when running inside a Jupyter notebook; used for inline PNG rendering.

Quick start

import numpy as np
from img_show import show_img

img = np.random.rand(256, 256, 3)
show_img(img)

Capability detection

At import time img-show probes the runtime environment and exposes two read-only flags:

from img_show import HAS_CV2, IS_HEADLESS

HAS_CV2      # bool         — True when cv2 is importable
IS_HEADLESS  # bool | None  — True for headless cv2 builds,
             #                False for GUI builds,
             #                None when cv2 is missing or the provider
             #                cannot be identified

Headless detection uses importlib.metadata.packages_distributions() to look up which PyPI distribution provides the cv2 import name. The check is fast and runs once at import.

Use these flags to branch your own code if you want to avoid RuntimeError from the display functions:

from img_show import HAS_CV2, IS_HEADLESS, show_img

if HAS_CV2 and IS_HEADLESS is False:
    show_img(my_image)
else:
    # fall back to saving or logging the array
    ...

Function requirements

Each public function has a different capability surface. The table below describes what must be available for each function to succeed:

Function cv2 required GUI build required Display required Works in Jupyter
coerce_img no no no yes
show_img yes yes (outside Jupyter only) yes (outside Jupyter only) yes (renders inline as PNG)
show_imgs yes yes (outside Jupyter only) yes (outside Jupyter only) yes (renders inline as PNG)
close_all yes no no yes (no-op if no windows)

When a requirement is unmet, the function raises RuntimeError at call time with a message that tells the user which extra to install. coerce_img is the only function that always works, because it is pure NumPy.

Jupyter inline rendering

When img-show detects a ZMQInteractiveShell (the standard Jupyter kernel), show_img and show_imgs encode each image to PNG with cv2.imencode and emit it through IPython.display.Image, captioned by the window name. The GUI and display requirements are skipped on this path, so a headless OpenCV build inside Jupyter is fully supported.

# In a Jupyter cell
from img_show import show_img
show_img(my_image, window_name='Step 3 output')

Usage

Multiple input types

import numpy as np
import torch
from PIL import Image
from img_show import show_img

show_img(np.random.rand(256, 256, 3))                # NumPy array
show_img(torch.randn(3, 256, 256))                   # PyTorch tensor (channels-first)
show_img(Image.open('photo.png'))                    # PIL image

PIL images use RGB channel order; img-show reorders them to BGR for correct OpenCV display. NumPy and PyTorch inputs are assumed to be BGR already (or single-channel) and pass through unchanged.

Shape coercion

Singleton dimensions are squeezed automatically, and channels-first layouts are transposed to channels-last:

show_img(np.random.rand(1, 256, 256, 3))      # leading singleton stripped
show_img(np.random.rand(1, 1, 3, 256, 256))   # channels-first detected and fixed
show_img(np.random.rand(256, 256, 1))         # grayscale with trailing singleton

Dtype normalization

The table below describes the dtype that coerce_img returns. The display path (show_img / show_imgs) then converts every result to uint8 before handing it to OpenCV — uint16 is scaled by 1/257, floats in [0, 1] are scaled by 255, and anything else is clipped into [0, 255].

Input dtype coerce_img output
uint8 passed through unchanged
uint16 passed through unchanged (display path will rescale to uint8)
bool scaled to 0/255 uint8
other integer scaled to the 0-1 range as float64
float scaled to 0-1 if out of range or near-constant

Alpha compositing

Four-channel images (RGBA from PIL, or BGRA arrays) are composited over a gray checkerboard at display time. The original four-channel array is preserved by coerce_img; compositing happens only in the display pipeline.

Window sizing

If the image is taller than the screen (minus a 250-pixel toolbar margin) or wider than the screen, a resizable window is created and sized to fit while preserving aspect ratio. Otherwise an auto-sizing window is created.

Multiple images

from img_show import show_imgs

show_imgs(
    [img1, img2, img3],
    window_names=['Original', 'Filtered', 'Diff'],
)

When window_names is omitted the names default to Image 1, Image 2, ... A collision with an already-tracked window appends (2), (3), ...

Keeping windows open

Pass destroy_window=False (or destroy_windows=False) to leave windows open after show_img/show_imgs returns. The names are tracked internally; call close_all to dismiss them later:

from img_show import show_img, close_all

show_img(img1, window_name='Step 1', destroy_window=False)
show_img(img2, window_name='Step 2', destroy_window=False)

# ... later
close_all()

close_all silently ignores windows that have already been closed by other means (for example by clicking the X button).

API reference

show_img(img, window_name=' ', wait_delay=0, do_wait=True, destroy_window=True)

Display a single image. Coerces and prepares the input, then either opens an OpenCV window or renders inline in Jupyter.

Parameter Type Default Description
img Any NumPy array, PyTorch tensor, or PIL image.
window_name str ' ' Window title (also used as the caption in Jupyter).
wait_delay int 0 Milliseconds to wait for a keypress when do_wait=True. 0 waits indefinitely.
do_wait bool True When True, block on cv2.waitKey. When False, paint the window briefly and return.
destroy_window bool True When True, close the window after waiting. When False, leave it open and track it for close_all.

Raises RuntimeError when OpenCV is missing, when a headless build is installed and the call is made outside Jupyter, or when no display environment is available outside Jupyter.

show_imgs(imgs, window_names=None, wait_delay=0, do_wait=True, destroy_windows=True)

Display multiple images. Each image opens its own window (or renders inline in Jupyter).

Parameter Type Default Description
imgs Iterable[Any] Collection of images.
window_names Iterable[str] | None None Names matching imgs. When None, auto-generated as Image 1, Image 2, ...
wait_delay int 0 Same as show_img.
do_wait bool True Same as show_img.
destroy_windows bool True Same as show_img's destroy_window.

Raises ValueError when len(window_names) != len(imgs). Same RuntimeError cases as show_img.

coerce_img(img) -> numpy.ndarray

Convert a NumPy array, PyTorch tensor, or PIL image into a displayable NumPy array. Returns a uint8, uint16, or normalized floating-point array depending on the input. Four-channel inputs remain four-channel; alpha compositing is applied only by the display path.

This function has no runtime requirements beyond NumPy and always works.

close_all() -> None

Close every window opened by show_img or show_imgs with destroy_window=False and clear the tracking set. Already-closed windows are ignored silently.

Raises RuntimeError when OpenCV is missing.

Module attributes

  • HAS_CV2: bool — True when cv2 is importable.
  • IS_HEADLESS: bool | None — True for a headless cv2 build, False for a GUI build, None when cv2 is missing or the provider cannot be identified.
  • open_window_names: set[str] — Names of currently tracked windows. Modified by show_img, show_imgs, and close_all.

License

img-show is licensed under the MIT License.

Author

Ben Elfner

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

img_show-1.0.0.tar.gz (119.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

img_show-1.0.0-py3-none-any.whl (13.7 kB view details)

Uploaded Python 3

File details

Details for the file img_show-1.0.0.tar.gz.

File metadata

  • Download URL: img_show-1.0.0.tar.gz
  • Upload date:
  • Size: 119.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.4

File hashes

Hashes for img_show-1.0.0.tar.gz
Algorithm Hash digest
SHA256 1d2b46bfb38c66f1c4d6beb84bcfe68fc6846ff27d603ffb4324057472b5e534
MD5 6e65f623102995ec227a2c99bcb2deb1
BLAKE2b-256 fb40defa881acc77f65fb9e4f6d4c80ac9ef5906ed0ff1ead6de082ed0013d0f

See more details on using hashes here.

File details

Details for the file img_show-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: img_show-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 13.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.4

File hashes

Hashes for img_show-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3286f40d053f122e187b57d47f75bafaec3ea8ff52436c369af72cae534d5aa7
MD5 bbb778bc26bc65f286b3ed45d4f19de2
BLAKE2b-256 eb2621f6484c3499bd5441c477952c72092d8fcf0e54d57d8812c5adc4f7f055

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page