大津法(Python實現)

在計算機視覺和圖像處理中,大津法被用於自動獲取圖像的閾值,或者將灰度圖像轉換爲二值化圖像。該算法假設圖像包含兩個類別的像素(前景像素和背景像素),而後它計算一個最優的閾值用於分離前景和背景,使得前景和背景的類間方差最小。

下面定義類間方差的計算公式:
假設咱們使用閾值T將灰度圖像分割爲前景和背景
size:圖像總像素個數
u:圖像的平均灰度
w0:前景像素點佔整幅圖像大小的比例
u0:前景像素點的平均值
w1:背景像素點佔整幅圖像大小的比例
u0:背景像素點的平均值
g:類間方差

u = w0 * u0 + w1 * u1  (1)
g = w0*(u - u0)^2 + w1*(u - u1)^2 (2)
將(1)代入(2)得:
g = w0 * w1 * (u0 - u1)^2

採用遍歷的方法,遍歷全部閾值,當g最大時,該閾值就是咱們所求的認爲最合適的閾值了。
偷偷告訴你,opencv有自帶的使用大津法閾值化的方法,以下:
cv2.threshold(img, th1, max_val, cv2.THRESH_OTSU)
使用參數cv2.THRESH_OTSU後,前面的th1就無效了。

如下是我本身寫的Python版函數:
import numpy as np

def OTSU_enhance(img_gray, th_begin=0, th_end=256, th_step=1):
    assert img_gray.ndim == 2, "must input a gary_img"

    max_g = 0
    suitable_th = 0
    for threshold in xrange(th_begin, th_end, th_step):
        bin_img = img_gray > threshold
        bin_img_inv = img_gray <= threshold
        fore_pix = np.sum(bin_img)
        back_pix = np.sum(bin_img_inv)
        if 0 == fore_pix:
            break
        if 0 == back_pix:
            continue

        w0 = float(fore_pix) / img_gray.size
        u0 = float(np.sum(img_gray * bin_img)) / fore_pix
        w1 = float(back_pix) / img_gray.size
        u1 = float(np.sum(img_gray * bin_img_inv)) / back_pix
        # intra-class variance
        g = w0 * w1 * (u0 - u1) * (u0 - u1)
        if g > max_g:
            max_g = g
            suitable_th = threshold
    return suitable_th