對於給定的閾值\(T\),可以將圖像分為目標和背景。其中背景點數占圖像比例為 \(p_0\),平均灰度值為 \(m_0\)。而目標點數占圖像比例為 \(p_1\),平均灰度值為 \(m_1\),其中滿足
\[p_0 + p_1 = 1 \]
整幅圖像的平均灰度值為常數,跟閾值無關,且為
\[\overline m = p_0m_0 + p_1m_1 \]
類間方差為
\[\sigma^2 = p_0(m_0 - \overline m)^2 + p_1(m_1 - \overline m)^2 \]
代入 \(p_0 + p_1 = 1\) 和 \(\overline m\),可化簡為
\[\sigma^2 = p_0p_1(m_0 - m_1)^2 \]
遍歷灰度值,找出能使 \(\sigma^2\) 最大的值。
大津法步驟
(1) 初始化方差為 \(S = -1\);
(2) 對灰度值為 \(0~255\) 的整數的圖像, 遍歷每個灰度值 \(T\),每次做第(3)步操作;
(3) 計算以 \(T\) 為閾值時候的類間方差,如果大於 \(S\),更新 \(S\) 並記錄 \(T\);
(4) 獲得使類間方差最大的 \(S\)。
效果
實現
1. 調用 OpenCV庫
img = cv.imread(img_path, 0) # img_path 為圖片路徑
th, img_bin = cv.threshold(img, -1, 255, cv.THRESH_OTSU) # img_bin 為二值化結果
2. 自己實現
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def show(img):
if img.ndim == 2:
plt.imshow(img, cmap='gray')
else:
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()
# 正式開始
img = cv.imread('pic/eagle500x500.jpg', 0)
Sigma = -1
T = 0
for t in range(0, 256):
bg = img[img <= t]
obj = img[img > t]
p0 = bg.size / img.size
p1 = obj.size / img.size
m0 = 0 if bg.size == 0 else bg.mean()
m1 = 0 if obj.size == 0 else obj.mean()
sigma = p0 * p1 * (m0 - m1)**2
if sigma > Sigma:
Sigma = sigma
T = t
T = int(T)
# 此時 T 即為最佳閾值
print(f"Best threshold = {T}")
說明:
- 未經許可,謝絕轉載。
- 本教程為《數字圖像處理Python OpenCV實戰》的配套代碼相關內容。
免費視頻教程為0-6章(標題號≤6),可在此處點擊觀看。
所有課件及源代碼可在此處下載:
鏈接:https://pan.baidu.com/s/198PySe_vebO3e06idHSQ6g
提取碼:11o4
有問題可在QQ群(1079300899)指出,進群答案:數字圖像處理。在本文評論指出可能導致回復很晚。
