GLCM (Grey-Level Co-occurrence Matrix - Haralick) texture measures in Python. Built with Eigen.
The package is managed with uv. A base install builds the C++ core and pulls numpy:
uv syncThe xarray.DataArray frontend is optional. Enable it with the xarray extra:
uv sync --extra xarrayStart from a 2-D image. Here is a smooth gradient with a little noise, so texture varies across space.
import numpy as np
import glcmpy
# random generation
rng = np.random.default_rng(0)
# generate image
image = (np.add.outer(np.arange(128), np.arange(128)) / 2.0) + rng.normal(0, 5, (128, 128))Pick an odd window_size (the neighbourhood scanned around each pixel) and call a measure. The result is a new array of the same shape. The input is not changed.
contrast = glcmpy.contrast(image, window_size=5)Directions are given in radians (0 = right, pi/4 = top-right, pi/2 = up, 3*pi/4 = top-left). Passing several angles averages the result, which makes it rotation-robust:
correlation = glcmpy.correlation(
image,
window_size=5,
angles=(0.0, np.pi / 4, np.pi / 2, 3 * np.pi / 4),
)With the xarray extra installed, the same measures accept a DataArray directly and return a new DataArray. Dimensions, coordinates and attributes are preserved, the measure parameters are recorded under glcm_* keys, and the input is never modified:
import xarray as xr
# define xarray data
raster = xr.DataArray(image, dims=("y", "x"), name="reflectance")
# calculate variance
texture = glcmpy.variance(raster, window_size=5) # new DataArray; `raster` untouchedThe core works on integer grey levels in [0, n_grey). By default each measure quantizes the input first (rescale=True, n_grey=1000). If your data already holds integer grey levels, pass rescale=False. You can also pre-quantize explicitly:
# quantize
levels = glcmpy.quantize(image, n_grey=64, value_range=(0.0, 1.0))
# apply contrast
contrast = glcmpy.contrast(levels, n_grey=64, rescale=False)Runnable jupytext scripts live in examples/
(install the extras with uv sync --group examples):
examples/textures-numpy.py, maps three measures over a four-texture image and plots them.examples/textures-xarray.py, runs a measure on a labelledDataArrayand shows that structure is preserved.
Uses uv + scikit-build-core + nanobind. Eigen is fetched automatically at build time (no system install needed).
uv sync --group dev --extra xarray
uv run ruff check . && uv run ruff format --check .
uv run mypy glcmpy
uv run pytestTo build the glcmpy documentation, you can use the following command:
uv run python scripts/build-docs.py # build the pdoc site into ./siteWe would like to thank the developers and contributors of the sits R package for their work on GLCM methods. The glcmpy is a standalone port of the texture functions from the sits R package.
Code is licensed under the GNU General Public License v2.0. See the LICENSE file. The texture math is ported from the sits R package.