Skip to main content
Yanked

This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.1.2 instead.
Reason given by maintainers: missing wheels

ahe

PyPI

A minimalist Python library for (Contrast Limited) (Adaptive) Histogram Equalization, combining the expressiveness of a user-friendly Python interface with the raw power of a low-level implementation.

Development status

ahe is currently in alpha. Fundational features are available, and expected to be stable, but the software as a whole may not be feature complete yet.

Installation

$ python -m pip install ahe

Usage

Simple Histogram Equalization

We'll start by defining an image composed of noise.

import ahe
import numpy as np

image_shape = (128, 128)
prng = np.random.default_rng(0)
image = np.clip(
    prng.normal(
        loc=0.5,
        scale=0.25,
        size=np.prod(image_shape),
    ).reshape(image_shape),
    a_min=0.0,
    a_max=1.0,
)

Non-adaptive histogram equalization is performed as follow

image_eq = ahe.equalize_histogram(image)

This method is least expensive in terms of strain put on hardware resources. However, as a single histogram is computed and adjusted over the entire image, this technique is known to amplify noise in near-uniform regions.

Adaptive Histogram equalization (AHE)

Adaptive Histogram Equalization (AHE) was designed to overcome this limitation by instead computing more localized (and numerous) histograms, improving the local contrast in all regions, at the cost of a reduced efficiency. As illustrated in the following, there are two main variants of AHE, sliding-tile and tile-interpolation. As the names suggest, both methods rely on the use of of tiles, also known as contextual regions, that define sub-domains in which different histograms are computed and applied.

Prioritizing accuracy: sliding-tile

True AHE is intrinsically an expensive operation to perform, as it requires computing a different histogram per pixel. One efficient (although still costly) way to accomplish this, originally proposed by Pizer et al. (1987), reduces the redundancy in intermediate computations and is known as the sliding-tile variant of AHE. Here's how to use it in ahe

image_eq = ahe.equalize_histogram(
    image,
    adaptive_strategy={
        "kind": "sliding-tile",
        "tile-size": 15,
    },
)

While an exact implementation of AHE, this option remains resource-demanding and is not recommended for production.

Prioritizing performance: tile-interpolation

Alternatively, very similar results can be obtained at a fraction of the cost using an approximative method known as the tile-interpolation variant of AHE, also introduced by Pizer et al. (1987). In this method, an image is split into equal-sized sub domains (tiles), which may be specified either from a tile size

image_eq = ahe.equalize_histogram(
    image,
    adaptive_strategy={
        "kind": "tile-interpolation",
        "tile-size": 16,
    },
)

or as a number of tiles to split the domain into (in each direction)

image_eq = equalize_histogram(
    image,
    adaptive_strategy={
        "kind": "tile-interpolation",
        "tile-into": 8,
    },
)

General rules for tiling schemes

In all AHE strategies, all tiles created will be the exact same size, regardless of the pixel's relative position in the image. The whole domain is generally padded internally in order to respect this rule. The exact method used for padding is controlled by the boundaries keyword argument.

Both 'tile-size' and 'tile-into' will accept either a shape as a pair of integers (n, m), or a single integer n, which is a shorthand for (n, n), as illustrated above.

Migrating from scikit-image

TL;DR

Put simply, if all your project needs from scikit-image is skimage.exposure.equalize_(adapt)hist, ahe provides a faster, more lightweight and portable replacement. The following contains a much more detailed explanation of the differences. You can also jump to the final Migration Guide.

Disclaimer: missing features

The following features from skimage.exposure.equalize_(adapt)hist are currently missing from ahe:

  • masking
  • multi-channel images objects (from PIL) or arrays. The expectation is that this should be easy to re-implement on the user side.
  • higher dimensionality: ahe currently only supports 2D input and outputs. The algorithms can be generalized to work in any dimensionality. Please open an issue

Some, though not all of the above are already planned. Don't hesitate to request the others (or anything else that could be in scope) by opening an issue.

Dependency Minimalism

ahe has no runtime dependencies beyond numpy. Additionally, its binaries are orders of magnitude lighter than scikit-image's, as well as future-compatible with yet-unreleased versions of Python.

Shows a bar chart comparing wheel sizes

(*: numpy itself, as the common dependency to ahe and scikit-image, is excluded from this graph)

Better performance

Shows a bar chart comparing wheel sizes

Interface Consistency

scikit-image's implementation of histogram equalization methods are exposed as two different functions: skimage.exposure.equalize_hist and skimage.exposure.equalize_adapthist. Only the former supports masking, and only the latter supports clipping. ahe.equalize_histogram provides a consistent feature set, independent of the adaptive strategy selected, or lack thereof.

Furthermore, implicit, default behavior can be hard to reproduce explicitly. For instance, equalize_adapthist will, by default, create tiles by dividing the image in 8 along each direction, but only exposes a kernel_size argument to override this; as a result, one needs to re-implement division logic if they need something very similar to the default, but with any other value than 8.

In stark contrast, ahe.equalize_histogram's adaptive_strategy argument supports all these applications:

  • adaptive_strategy=None (default) corresponds to skimage.exposure.equalize_hist
  • adaptive_strategy={'kind': 'tile-interpolation', 'tile-into': 8} corresponds to skimage.exposure.equalize_adapthist's default, but the exact divisor(s) used can easily be adjusted
  • adaptive_strategy={'kind': 'tile-interpolation', 'tile-size': 64} is akin to using skimage.exposure.equalize_adapthist's kernel_size argument.

Last but not least, equalize_hist does not support contrast limitation, while equalize_adapthist enables it by default (clip_limit defaults to 0.01), and things get messy when you actually want to disable it:

  • clip_limit's name is not descriptive and only makes sense if you already know what it does under the hood. ahe's equivalent parameter is named max_normalized_bincount, which is more verbose, but also more explicit about what the number represents.
  • clip_limit (a.k.a max_normalized_bincount) is effectively a fraction; only values within the open interval ]0.0, 1.0] are meaningful, but clip_limit=0.0 is allowed, and effectively disable all clipping, which means it's equivalent to 1.0, further mystifying the underlying behavior and meaning of the parameter. Another way to phrase this is that the results change discontinuously at 0.0, which is very close to the default value and should be easy to reason about.
  • results for clip_limit=1.0 (or 0.0, as we just saw), are actually incorrect at a level that is visible to the naked eye (aliasing may be prominent). In comparison, ahe does not enable contrast limitation by default: such flagrant defects would be immediately visible in tests.

Conservation of transformation invariants

ahe.equalize_histogram also provides stricter guarantees regarding the transformation's geometric invariants. Outputs are guaranteed to be invariant (to machine precision) to left/right and top/ bottom symmetries. In contrast, skimage.exposure.equalize_adapthist's outputs are subject to biases on, because it does not enforce symmetry in its internal tiling scheme (as of scikit-image v0.26.0). This improved tiling scheme comes at the cost of stricter requirements in ahe.equalize_histogram: the tile-interpolation strategy only supports tiles and images with even sizes in both directions.

Additional features

ahe.equalize_histogram supports more tiling scheme than skimage.exposure.equalize_hist and skimage.exposure.equalize_adapthist combined, within a consistent interface and a unified feature set. In particular, it offers an exact implementation of Adaptive Histogram Equalization implemented as a sliding-tile, while skimage.exposure.equalize_adapthist only supports tile-interpolation (also available in ahe), which is generally faster, but also a less accurate approximation of a true AHE.

ahe.equalize_histogram also supports periodic boundary conditions, which can be specified as boundaries='periodic'.

Migration Guide

This section provides some practical examples of scikit-image applications and their equivalent in ahe.

Notes

  • in ahe, the default nbins is generally aligned with scikit-image's (256), except for kernels (or tiles) spanning less than 256 pixels. For maximum compatibility, specifying an explicit value is recommended.
  • ahe.equalize_histogram's max_normalized_bincount represents the same parameter as skimage.exposure.equalize_adapthist's clip_limit, but their default values differ: max_normalized_bincount defaults to 1.0 (no contrast limitation), while scikit-image's clip_limit default to 0.01
  • "kernel", "tile" and "contextual region" are different names for the same concept.

HE

from skimage.exposure import equalize_hist

result = equalize_hist(array)

# becomes
import ahe

result = ahe.equalize_histogram(array, nbins=256)

AHE with implicit kernel size

from skimage.exposure import equalize_adapthist

result = equalize_adapthist(array, clip_limit=1.0)

# becomes
import ahe

result = ahe.equalize_histogram(
    array,
    nbins=256,
    adaptive_strategy={
        "kind": "tile-interpolation",
        "tile-into": 8,  # or (8, 8)
    },
)

CLAHE with explicit kernel size

from skimage.exposure import equalize_adapthist

result = equalize_adapthist(array, kernel_size=64)

# becomes
import ahe

result = ahe.equalize_histogram(
    array,
    nbins=256,
    adaptive_strategy={
        "kind": "tile-interpolation",
        "tile-size": 64,  # or (64, 64)
    },
    max_normalized_bincount=0.01,
)

References

  1. Pizer, Stephen M. et al. (1987). Adaptive Histogram Equalization and Its Variations. Compute Vizion, Graphics, and Image Processing, 39, 355-368

Metadata

Release files for ahe 0.1.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 ahe 0.1.1
File Size Uploaded
ahe-0.1.1.tar.gz 48.4 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for ahe 0.1.1
File
ahe-0.1.1-cp315-abi3.abi3t-win_amd64.whl CPython 3.15 abi3, abi3t Windows x86-64 Details
ahe-0.1.1-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl CPython 3.15 abi3, abi3t Linux musl 1.2+ x86-64 Details
ahe-0.1.1-cp315-abi3.abi3t-macosx_11_0_arm64.whl CPython 3.15 abi3, abi3t macOS 11.0+ ARM64 Details
ahe-0.1.1-cp311-abi3-win_arm64.whl CPython 3.11 abi3 Windows ARM64 Details
ahe-0.1.1-cp311-abi3-musllinux_1_2_aarch64.whl CPython 3.11 abi3 Linux musl 1.2+ ARM64 Details
ahe-0.1.1-cp311-abi3-manylinux_2_28_x86_64.whl CPython 3.11 abi3 Linux glibc 2.28+ x86-64 Details
ahe-0.1.1-cp311-abi3-manylinux_2_28_aarch64.whl CPython 3.11 abi3 Linux glibc 2.28+ ARM64 Details
ahe-0.1.1-cp311-abi3-macosx_10_12_x86_64.whl CPython 3.11 abi3 macOS 10.12+ x86-64 Details

Total release size: 2.2 MB

Release files / ahe-0.1.1.tar.gz

Download URL ahe-0.1.1.tar.gz
Size 48.4 kB
Tags Source
SHA-256 checksum
How to use checksums
7b0d6ff8c767a0bdc238e80c927095f17fa7cd73c7d819cba4367661542def44
BLAKE2b-256 checksum
How to use checksums
be2c372e9a184a8d4f1afbb99c48d838aae8148baa0969d24ad7823ed32024c7
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 Oct 15, 2026.

Transparency log

Release files / ahe-0.1.1-cp315-abi3.abi3t-win_amd64.whl

Download URL ahe-0.1.1-cp315-abi3.abi3t-win_amd64.whl
Size 161.0 kB
Tags CPython 3.15 Windows x86-64 abi3 abi3t
SHA-256 checksum
How to use checksums
39d62cfb69a00255d72a223ff9743dc638cfcbb4e9f7c3888bc14768dd1dec7a
BLAKE2b-256 checksum
How to use checksums
09385215dbe642511263f347a761486c6b8d2bc05b6d416520fbef2b25e1d5be
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 Oct 15, 2026.

Transparency log

Release files / ahe-0.1.1-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl

Download URL ahe-0.1.1-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl
Size 474.1 kB
Tags CPython 3.15 Linux musl 1.2+ x86-64 abi3 abi3t
SHA-256 checksum
How to use checksums
0d27f2c451476e2bc8009ca6e9d142c80bca7844303bd2dcae56a04d74301329
BLAKE2b-256 checksum
How to use checksums
af15517b0c1652e72b32c1b868be88af290573d4553e5fb7bf6c55e74d587a76
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 Oct 15, 2026.

Transparency log

Release files / ahe-0.1.1-cp315-abi3.abi3t-macosx_11_0_arm64.whl

Download URL ahe-0.1.1-cp315-abi3.abi3t-macosx_11_0_arm64.whl
Size 230.1 kB
Tags CPython 3.15 abi3 abi3t macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f6f007c6f9739adc92dc9153ff75a03f4a8cb90d9bf94db85eb2aec6862d703b
BLAKE2b-256 checksum
How to use checksums
f73c2a45a3602a805c30ac418ff56d68a35e637d0b66bd227e866496602e3608
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 Oct 15, 2026.

Transparency log

Release files / ahe-0.1.1-cp311-abi3-win_arm64.whl

Download URL ahe-0.1.1-cp311-abi3-win_arm64.whl
Size 153.0 kB
Tags CPython 3.11 Windows ARM64 abi3
SHA-256 checksum
How to use checksums
f3345aa021dbbc2aacb1d96fcdf929486451df60bd91fa0c15202da8a59eaa59
BLAKE2b-256 checksum
How to use checksums
30142d8951fac359e37030fc1adf9bd0d4e3c7860c626824d7aae6551ce93ec3
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 Oct 15, 2026.

Transparency log

Release files / ahe-0.1.1-cp311-abi3-musllinux_1_2_aarch64.whl

Download URL ahe-0.1.1-cp311-abi3-musllinux_1_2_aarch64.whl
Size 428.7 kB
Tags CPython 3.11 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
fe346c846c985d87f55d14c6dfe5cbf8bf1cef949582dcd17f9f83e69d458186
BLAKE2b-256 checksum
How to use checksums
3dab9296c3b2dcf371f3ca0d37b19765c6a5ab28ec2675cf86549dbc05f417e9
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 Oct 15, 2026.

Transparency log

Release files / ahe-0.1.1-cp311-abi3-manylinux_2_28_x86_64.whl

Download URL ahe-0.1.1-cp311-abi3-manylinux_2_28_x86_64.whl
Size 261.6 kB
Tags CPython 3.11 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
793e228d5168ec45fbd07afd9c452737c7d14dd3eb89489c9ecb7b1b96596186
BLAKE2b-256 checksum
How to use checksums
30de644f0158ecc80e778803074578c4fc7e32aac5002995719bd3b27f735b46
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 Oct 15, 2026.

Transparency log

Release files / ahe-0.1.1-cp311-abi3-manylinux_2_28_aarch64.whl

Download URL ahe-0.1.1-cp311-abi3-manylinux_2_28_aarch64.whl
Size 251.0 kB
Tags CPython 3.11 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
e4b5f8be996eba64a6ee55730874013b388f56f20a8f9979d63fc454973eb47d
BLAKE2b-256 checksum
How to use checksums
67a63c0400977363451163e591e1b1d424fa77ed28ffbbb853a14b2bfdbc0ba1
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 Oct 15, 2026.

Transparency log

Release files / ahe-0.1.1-cp311-abi3-macosx_10_12_x86_64.whl

Download URL ahe-0.1.1-cp311-abi3-macosx_10_12_x86_64.whl
Size 241.4 kB
Tags CPython 3.11 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
0c69f9c0abc7eb6e1d341e180e344fb452b39d9d99ecb4128852992778a8ccd3
BLAKE2b-256 checksum
How to use checksums
85ea59383fc971001c99d25ffb878dfd6b9bc3cb362b9c3b507debbc6c45c7b1
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 Oct 15, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.2

17 release files

This release

0.1.1 This release

9 release files

0.1.0

10 release files

0.0.3

1 release file

0.0.2

1 release file

0.0.1

1 release file

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