Thresholding - iffatAGheyas/computer-vision-handbook GitHub Wiki

✂️ Thresholding (Global, Adaptive, Otsu) :contentReference[oaicite:0]{index=0}

Thresholding converts a grayscale image into a binary mask by classifying each pixel as foreground or background based on its intensity.


1. Global Thresholding

Apply a single threshold T across the entire image:

dst(x, y) =
  255  if src(x, y) > T
    0  otherwise
  • src(x, y): original pixel value

  • T: chosen threshold (e.g. 127)

🐍 Code Example

import cv2
import matplotlib.pyplot as plt

# Load image in grayscale
img_gray = cv2.imread("bird.jpg", cv2.IMREAD_GRAYSCALE)

# Apply global threshold (T=127)
_, thresh_global = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)

# Display result without axes
plt.imshow(thresh_global, cmap="gray")
plt.title("Global Threshold (T=127)")
plt.axis("off")
plt.show()

image

2. Adaptive Thresholding

Under uneven lighting, a single global threshold may fail. Adaptive methods compute a threshold for each local region.

Types:

  • cv2.ADAPTIVE_THRESH_MEAN_C
    Local mean of the neighbourhood.
  • cv2.ADAPTIVE_THRESH_GAUSSIAN_C
    Weighted sum (Gaussian) of the neighbourhood—more robust to noise.

🐍 Code Example

import cv2
import matplotlib.pyplot as plt

# Parameters
block_size = 11  # neighbourhood size (odd)
C = 2            # constant to subtract

# Adaptive Mean Thresholding
adaptive_mean = cv2.adaptiveThreshold(
    img_gray, 255,
    cv2.ADAPTIVE_THRESH_MEAN_C,
    cv2.THRESH_BINARY,
    block_size, C
)

# Adaptive Gaussian Thresholding
adaptive_gauss = cv2.adaptiveThreshold(
    img_gray, 255,
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
    cv2.THRESH_BINARY,
    block_size, C
)

# Display side-by-side without axes
plt.figure(figsize=(12, 4))

plt.subplot(1, 2, 1)
plt.imshow(adaptive_mean, cmap="gray")
plt.title("Adaptive Mean")
plt.axis("off")

plt.subplot(1, 2, 2)
plt.imshow(adaptive_gauss, cmap="gray")
plt.title("Adaptive Gaussian")
plt.axis("off")

plt.tight_layout()
plt.show()

Parameters

Parameter Description
blockSize Neighbourhood size used to compute each threshold
C Constant subtracted from the mean or weighted sum

image

3. Otsu’s Thresholding — Automatic Global Threshold

When you don’t know the best threshold, Otsu’s method finds it automatically by minimising intra-class variance.

What It Does

  • Analyses the image histogram
  • Chooses the threshold that best separates foreground & background

🐍 Code Example

import cv2
import matplotlib.pyplot as plt

# Otsu’s Thresholding (T is ignored)
_, thresh_otsu = cv2.threshold(
    img_gray, 0, 255,
    cv2.THRESH_BINARY + cv2.THRESH_OTSU
)

plt.imshow(thresh_otsu, cmap="gray")
plt.title("Otsu’s Thresholding")
plt.axis("off")
plt.show()

image

🔍 Comparison

Method Best For Manual Tuning?
Global Uniform lighting ✅ Yes
Adaptive Uneven lighting, shadows ✅ Yes
Otsu’s Bimodal histograms ❌ No

Summary

Method OpenCV Function
Global Threshold cv2.threshold()
Adaptive Threshold cv2.adaptiveThreshold()
Otsu’s Method cv2.threshold(... + cv2.THRESH_OTSU)