---
kind: concept
slug: local-binary-patterns
title: Local binary patterns
summary: >-
  Encodes each pixel as a binary code by comparing it with neighbours on a circle, then describes a texture by those codes. Variants add rotation invariance (minimum over circular shifts), uniform-pattern labels that shrink the histogram, or combination with co-occurrence and edge features. The one cited source is a 2019 survey with no experiments of its own, so no LBP-only accuracy is given.
tags: [computer-vision, texture, feature-extraction]
papers: ["1904.06554"]
related: [gray-level-co-occurrence-matrix]
status: draft
updated_at: 2026-10-19
---

## Overview

A local binary pattern (LBP) describes the neighbourhood of each pixel as a
binary number. The centre value is compared with P neighbours sampled on a
circle of radius R. A neighbour brighter than the centre contributes a 1 and
otherwise a 0, and the bits are weighted by powers of two [arxiv:1904.06554
§II.A.3] [arxiv:1904.06554 eq. 13, eq. 14]. Each bit is a comparison with the centre value, so the code
is built from the ordering of neighbour values, not from their absolute
levels [arxiv:1904.06554 eq. 14]. The review's own description of how the
codes are summarised for a texture is brief; the histogram step in the
pseudocode below is the usual practice and is not spelled out in the card.

The method is credited to Ojala et al. for the multiresolution and
rotation-invariant forms [arxiv:1904.06554 §II.A.3]. The only source on this
page is a 2019 survey of texture classification, which describes LBP and
reports no new experiments [arxiv:1904.06554 §VI].

## Variants

### Basic LBP code

Fixed bit order: the bit for neighbour p has weight 2^p, so each of the 2^P
codes is distinct [arxiv:1904.06554 eq. 13]. Neighbours that fall between
pixel centres are read by interpolation [arxiv:1904.06554 fig. 8]. The
survey does not fix P and R as one setting; it shows several circular
neighbourhoods [arxiv:1904.06554 fig. 8]. Card: [Texture image analysis and
texture classification methods - A review](/papers/1904.06554).

### Rotation-invariant LBP

Each P-bit code is rotated right by every shift from 0 to P-1, and the
smallest resulting value is kept [arxiv:1904.06554 eq. 15]. Two images of the
same texture rotated against each other then give the same code at each
pixel. The review calls almost all of the methods it covers rotation
invariant, but this claim is qualitative and the comparison table does not
record rotation tests for every row [arxiv:1904.06554 §VII]. Card: [Texture
image analysis and texture classification methods - A
review](/papers/1904.06554).

### Uniform LBP

A code is uniform when its circular 0/1 transition count is at most a
threshold U_T. Each uniform code gets a label equal to its number of ones,
from 0 to P. All other codes share one extra label, P+1 [arxiv:1904.06554
eq. 16, eq. 17]. This reduces the histogram from 2^P bins to P+2 bins
(computed from eq. 17). The review says the usual threshold is P/4, citing
Ojala et al. [arxiv:1904.06554 §II.A.3]. This page has not checked that
citation; see Pitfalls. Card: [Texture image analysis and texture
classification methods - A review](/papers/1904.06554).

### LBP combined with other descriptors

Several of the review's combined methods use LBP as one stage. SEGL applies
LBP first, then a co-occurrence matrix in 8 directions, then Sobel edges,
with seven statistics per matrix and 56 values per image [arxiv:1904.06554
§III.B, fig. 15]. The review's binary Gabor pattern is a related design:
eight Gabor filters give eight bits per pixel, which are weighted and
minimised over rotations [arxiv:1904.06554 §III.D, eq. 29, eq. 30]. That
method is not LBP and is named here only for comparison. Card: [Texture
image analysis and texture classification methods - A
review](/papers/1904.06554).

## When to use which

The review gives no LBP-only accuracy. The rows of its comparison table
name methods that use LBP-based descriptors, but the card does not attribute
any row to LBP alone, and the rows differ in dataset, classifier and
protocol [arxiv:1904.06554 §VI, tab. 4]. The guidance below is therefore
based on what each variant computes, not on measured accuracy.

| Situation | Use | Why |
|---|---|---|
| Texture always appears in one orientation | Basic LBP code [arxiv:1904.06554 eq. 13] | The code is the most direct form, with no minimum over rotations |
| Texture can appear at any orientation | Rotation-invariant LBP [arxiv:1904.06554 eq. 15] | The minimum over rotations removes the orientation of the texture from the code |
| Histogram size or feature length matters | Uniform LBP [arxiv:1904.06554 eq. 17] | P+2 bins instead of 2^P (computed from eq. 17); the review does not state how this changes accuracy |
| One descriptor is not enough | LBP as a stage in a combined method, e.g. SEGL [arxiv:1904.06554 §III.B] | Adds co-occurrence and edge statistics; the review reports 56 values per image |
| Need evidence of noise robustness | Check the source papers | The review says most methods are sensitive to noise [arxiv:1904.06554 §VII], but the card gives no LBP-specific noise result |
| Need a fair accuracy comparison | Run your own benchmark | The review's numbers come from different datasets, classifiers and protocols [arxiv:1904.06554 §VI, tab. 4] |

## Implementation sketch

Language-agnostic pseudocode of the common core, with notes on where variants
differ. Same style as paper cards: Python-flavoured, lines of at most 80
characters, a `# comment` line above each step (with its citation), short
trailing comments only for shapes or units.

```pseudocode
# LBP code for one pixel, P neighbours, radius R  [arxiv:1904.06554 eq. 13, eq. 14]
# Input:  gray image, pixel (x, y), P, R
# Output: integer in [0, 2^P - 1]
def lbp_code(image, x, y, P, R):
    center = image[x, y]
    code = 0
    for p in range(P):
        # sample point on the circle, interpolated if off-grid  [fig. 8]
        neighbour = sample_circle(image, x, y, R, p)
        # bit is 1 when the neighbour is strictly brighter  [eq. 14]
        bit = 1 if neighbour > center else 0
        # weight bit p by 2^p  [eq. 13]
        code = code + bit * 2 ** p
    return code

# Rotation-invariant and uniform label  [eq. 15] [eq. 16] [eq. 17]
# Input:  P-bit code, P, threshold U_T (paper's usual value: P/4, unverified)
# Output: label in [0, P + 1]
def lbp_uniform_label(code, P, threshold):
    # minimum over all circular right-shifts  [eq. 15]
    smallest = min(rotate_right(code, i, P) for i in range(P))
    # count 0/1 transitions around the circle  [eq. 16]
    transitions = count_circular_transitions(smallest, P)
    if transitions <= threshold:
        # uniform: label is the number of ones  [eq. 17]
        return count_ones(smallest, P)
    # every other pattern shares one label  [eq. 17]
    return P + 1

# Texture descriptor: histogram of labels over the image  [§II.A.3]
# Input:  gray image, P, R, threshold
# Output: histogram with P + 2 bins (uniform variant)
def lbp_histogram(image, P, R, threshold):
    hist = zeros(P + 2)
    for each pixel (x, y) inside the border:
        code = lbp_code(image, x, y, P, R)
        label = lbp_uniform_label(code, P, threshold)
        hist[label] += 1
    # normalise so images of different sizes compare  [§II.A.3]
    return hist / sum(hist)
```

Where variants differ: the basic variant skips `lbp_uniform_label` and uses
the raw code as the bin index, which gives 2^P bins. The rotation-invariant
variant keeps the minimum over shifts but skips the uniform rule. The
histogram normalisation step is a common practice the survey does not spell
out; check it against the classifier you use.

## Contradictions

None known. Only one source is cited, and its own text is the basis for every
claim here.

## Papers

- [Texture image analysis and texture classification methods - A review](/papers/1904.06554): a 2019 survey that describes LBP and its rotation-invariant and uniform forms, plus the combined methods that use LBP, and lists the benchmark datasets. It reports no new experiments.
