DIP+CV · Programming Exercise

EP04_02 — 📊 Otsu’s Automatic Thresholding

4.9.2 EP04_02 📊 Otsu’s Automatic Thresholding

Manually choosing the threshold \(T\) works when illumination is stable, but in digital microscopy and blood smear inspection, each sample has different contrast — a fixed threshold would fail from image to image. Otsu’s method solves this by autonomously finding the threshold that maximizes the statistical separation between the two pixel classes, making segmentation automatic and adaptive. See Figure 4.31 for a simulation of this EP.

4.9.2.1 📋 Implementation Guidelines

  1. Dimensions: Read the integers \(L\) (rows) and \(C\) (columns).

  2. Data: Read the integer values of the original matrix row by row.

  3. Histogram: Build the histogram \(h[i]\), \(i=0,\dots,255\), counting how many pixels have value \(i\).

  4. Threshold search: For each candidate \(T\) from \(1\) to \(255\), compute the between-class variance: \[ \sigma_B^2(T) = \frac{n_0 \cdot n_1}{N^2}\,(m_0 - m_1)^2 \] where \(n_0,n_1\) are the numbers of pixels with values \(<T\) and \(\geq T\), \(m_0,m_1\) are their means, and \(N=L\times C\).

  5. Selection: The optimal threshold \(T^*\) is the one that maximizes \(\sigma_B^2(T)\) (in case of a tie, keep the first one found).

  6. Application: Binarize the image using T*, applying: \[ p' = \begin{cases} 255, & \text{if } p > T^* \\ 0, & \text{if } p \le T^* \end{cases} \]

4.9.2.2 📌 Computational Constraints

  • Valid candidates: Ignore \(T\) that leaves \(n_0=0\) or \(n_1=0\) (empty class).
  • Tie-breaking: Always keep the first \(T\) that reached the maximum value of \(\sigma_B^2\).
  • Type: \(T^*\) and the output matrix must be integers.
  • OpenCV convention: The binarization follows cv2.THRESL_BINARY; pixels with value exactly equal to \(T^*\) become black.

4.9.2.3 🧠 Theoretical Background

Concept Meaning Impact
High \(\sigma_B^2(T)\) Classes well separated at \(T\) \(T\) is a good threshold candidate
Bimodal histogram Two distinct “peaks” Otsu finds the valley between them
Unimodal histogram A single “peak” Otsu still chooses some \(T\), but the segmentation is unreliable

4.9.2.4 📦 Input and Output Specification (VPL)

Input:

  • Line 1: Integer \(L\).
  • Line 2: Integer \(C\).
  • Following lines: Integer elements of the original matrix.

Output:

  • Binarized matrix with \(L\) rows and \(C\) columns, values \(0\) or \(255\).

4.9.2.5 📌 Examples

Input Output Observation
4
4
12 12 12 200
12 12 200 200
12 200 200 200
200 200 200 200
0 0 0 255
0 0 255 255
0 255 255 255
255 255 255 255
Clear bimodal histogram: 12 and 200
1
2
10 250
0 250 Only two values: \(T^*\) falls on the largest one
📊 EP04_02 Simulator: Automatic Otsu T* = argmax σ²_B(T)

👆 Left click darkens (−25) and right click lightens (+25) the input pixels. Watch the optimal threshold T* adjust dynamically to the histogram.

T* = −

Original Input (Clickable)
Otsu Result (p')
Figure 4.31: EP04_02 Simulator: Automatic Otsu Thresholding (T* = argmax σ²_B(T))
%%writefile EP04_02.cpp
// your solution
Overwriting EP04_02.cpp
TestSuite("EP04_02.cpp").run()
✔️ EP04_02.cases already exists in casos/
📋 5 case(s) loaded from casos/EP04_02.cases

🔍 Testing C++: EP04_02.cpp
⚠️ EP04_02.cpp: Empty file (fewer than 3 lines). Tests skipped.