---
kind: concept
slug: gray-level-co-occurrence-matrix
title: Gray-level co-occurrence matrix
summary: >-
  Counts how often two grey levels sit at a fixed offset in an image, then reads texture from that table with statistics such as contrast, energy and homogeneity. Variants differ in scale (pyramid or blur), in what they combine with (LBP, edges, difference images) and in how many values they produce. The one cited review runs no experiments of its own.
tags: [computer-vision, texture, feature-extraction]
papers: ["1904.06554"]
related: [wavelet-transform]
status: draft
updated_at: 2026-10-19
---

## Overview

A gray-level co-occurrence matrix (GLCM) records how often a pixel with grey
level i has a neighbour with grey level j at a chosen offset [arxiv:1904.06554
§II.A.2] [arxiv:1904.06554 fig. 5]. The matrix is then normalised to
probabilities p_ij and summarised by a few statistics. Those statistics
describe how grey levels are arranged relative to each other, not just how
often each level occurs. That is the difference from a grey-level histogram,
which ignores pixel positions [arxiv:1904.06554 §II.A].

The method is usually credited to Haralick [arxiv:1904.06554 §II.A.2]. The
only source on this page is a 2019 survey of texture classification. It
describes the GLCM and several variants that build on it, but it reports no
new experiments [arxiv:1904.06554 §VI].

## Variants

### Single-scale GLCM with six statistics

Build one matrix per offset and direction, normalise it, and compute six
statistics: contrast, correlation, energy, homogeneity, entropy and maximum
probability [arxiv:1904.06554 eq. 7] to [arxiv:1904.06554 eq. 12]. The
review shows four directions, 0, 45, 90 and 135 degrees [arxiv:1904.06554
fig. 6]. Its displacement is inconsistent, see Contradictions. Card:
[Texture image analysis and texture classification methods - A review](/papers/1904.06554).

### Pyramid GLCM

The image is reduced to five layers, and a matrix is taken on each layer in
four directions. Twelve characteristics are computed per matrix [arxiv:1904.06554
§III.A, fig. 14]. The review gives a total of 48 values, which is four
directions times twelve characteristics; it does not say how the five layers
are combined into those 48 values. Card: [Texture image analysis and texture
classification methods - A review](/papers/1904.06554).

### Gaussian-blur GLCM

The same five-layer structure, but the layers come from blurring the image
with a Gaussian filter instead of building a pyramid. The review reports
the same 48-value total [arxiv:1904.06554 §III.A, fig. 14]. The filter
width is not stated. Card: [Texture image analysis and texture classification
methods - A review](/papers/1904.06554).

### SEGL: LBP, GLCM and edges

Computes a local binary pattern image first, then a GLCM on that output in
eight directions, then a Sobel edge map of the GLCM output. Seven statistics
are taken per matrix, entropy, energy, contrast, homogeneity, correlation,
average and variance, giving 56 values in total [arxiv:1904.06554 §III.B,
fig. 15]. Card: [Texture image analysis and texture classification methods -
A review](/papers/1904.06554).

### GLCM of the image and its difference image

Two matrices are built, one from the input and one from a difference image.
Four statistics are taken from each: contrast, correlation, energy and
homogeneity [arxiv:1904.06554 §III.F, fig. 18]. The review gives no offset
values for this method. Card: [Texture image analysis and texture
classification methods - A review](/papers/1904.06554).

### GLCM energy inside energy variation

Energy variation takes the GLCM energy, the LBP energy and the edge energy of
the input, each compared with the input's own energy [arxiv:1904.06554 §III.C,
eq. 27, eq. 28]. Here GLCM is one of three operators, not a standalone
feature set. Card: [Texture image analysis and texture classification methods -
A review](/papers/1904.06554).

## When to use which

The review gives no accuracy that isolates a single GLCM variant. Each row of
its comparison table uses its own dataset, classifier and protocol, and the
text does not state most of them [arxiv:1904.06554 §VI, tab. 4]. Choose a
variant from the constraints below, not from the review's numbers.

| Situation | Use | Why |
|---|---|---|
| One scale of texture, small feature vector wanted | Single-scale GLCM | Six statistics per matrix [arxiv:1904.06554 eq. 7] to [arxiv:1904.06554 eq. 12]; four directions give 24 values |
| Texture at several scales, more compute available | Pyramid GLCM | Five layers and four directions; 48 values in total [arxiv:1904.06554 §III.A] |
| Multi-scale wanted without a pyramid | Gaussian-blur GLCM | Same count, with blurring instead of pyramid reduction [arxiv:1904.06554 fig. 14]; filter width not stated |
| A combined feature set from edges and local patterns | SEGL | Adds LBP and edge stages, 56 values [arxiv:1904.06554 §III.B] |
| Need the difference between neighbouring grey levels | GLCM with difference image | Two matrices, eight values [arxiv:1904.06554 §III.F] |

Practical limits that follow from the definition:

- **Memory grows with the square of the grey-level count.** A k-bit image has
  L = 2^k levels, so the matrix is L by L [arxiv:1904.06554 fig. 5]. Quantising
  to fewer levels cuts the matrix size, but the review does not say how this
  affects accuracy.
- **Rotation.** The review calls almost all methods rotation invariant, but this is a
  qualitative claim, and the table does not record rotation tests for every
  row [arxiv:1904.06554 §VII]. The four fixed directions are not stated to
  give rotation invariance on their own. Test with rotated copies of your own
  data.
- **Data and classifier.** The review's comparison uses k-nearest neighbour,
  SVM, naive Bayes, decision trees and neural networks, and says the best k
  depends on the data [arxiv:1904.06554 §V]. Choose the classifier by testing
  on your own data.

## Implementation sketch

The common core is one normalised matrix per offset, followed by statistics
read from that matrix. The variants differ in which offsets they use, how
they scale the image, and what they add.

```pseudocode
# Co-occurrence matrix for one offset  [arxiv:1904.06554 §II.A.2]
# Input:  image with L grey levels (L = 2^k), offset (dr, dc)
# Output: normalised matrix P, shape (L, L)
def glcm(image, levels, dr, dc):
    # count pairs (i, j): pixel at (r, c) has level i, pixel at (r+dr, c+dc)
    # has level j. The review does not fix the sign convention of the
    # offset [arxiv:1904.06554 fig. 6]; check it against your library.
    counts = zeros(levels, levels)
    for each (r, c) where (r + dr, c + dc) is inside the image:
        counts[image[r, c], image[r + dr, c + dc]] += 1
    # normalise so that entries sum to 1  [arxiv:1904.06554 §II.A.2]
    return counts / sum(counts)
```

```pseudocode
# Six statistics from P  [arxiv:1904.06554 eq. 7] to [arxiv:1904.06554 eq. 12]
# Input:  normalised matrix P, shape (L, L)
# Output: dict of six values
def glcm_stats(P):
    # row and column means and standard deviations  [arxiv:1904.06554 §II.A.2]
    mu_i, mu_j, sigma_i, sigma_j = row_and_column_moments(P)
    # contrast: squared level difference weighted by p_ij  [eq. 7]
    # The review's typesetting of eq. 7 reads |i - i|^2; the intended term
    # is |i - j|^2 (see Contradictions).
    contrast = sum(P[i, j] * (i - j) ** 2 for i, j in all_pairs)
    # correlation, normalised by the row and column standard deviations  [eq. 8]
    correlation = sum(P[i, j] * (i - mu_i) * (j - mu_j)
                      for i, j in all_pairs) / (sigma_i * sigma_j)
    # energy: sum of squared probabilities  [eq. 9]
    energy = sum(P[i, j] ** 2 for i, j in all_pairs)
    # homogeneity: weights entries near the diagonal  [eq. 10]
    homogeneity = sum(P[i, j] / (1 + abs(i - j)) for i, j in all_pairs)
    # entropy with base-2 logarithm  [eq. 11]. Handling of zero entries
    # is not stated.
    entropy = -sum(P[i, j] * log2(P[i, j]) for i, j in all_pairs)
    # maximum probability  [eq. 12]
    max_p = max(P)
    return contrast, correlation, energy, homogeneity, entropy, max_p
```

Pyramid and blur variants wrap `glcm` in a loop over five image layers, and
a final step combines the outputs into the 48-value vector. The review does
not give that combination step [arxiv:1904.06554 §III.A].

## Contradictions

- **Displacement.** The text under the example matrix gives a displacement of
  1 pixel [arxiv:1904.06554 §II.A.2]. The direction figure and its caption
  give 3 pixels [arxiv:1904.06554 fig. 6]. The review does not resolve this.
  Pick a value and check it against the original GLCM sources.
- **Contrast formula.** Eq. 7 is typeset with |i − i|^2, which is zero for
  every entry. The intended term is almost certainly |i − j|^2, the usual form
  of contrast [arxiv:1904.06554 eq. 7]. Check this against Haralick's original
  paper before implementing.
- **Pyramid count.** Five layers, four directions and 12 statistics per matrix
  would give 240 values, not the stated 48 [arxiv:1904.06554 §III.A]. The
  review does not say how the layer outputs are combined.

No conflicting results across papers: the page draws on one source.

## Papers

- [Texture image analysis and texture classification methods - A review](/papers/1904.06554): 2019 survey of texture descriptors. Describes the GLCM, its six statistics and the variants above, with no experiments of its own.
