大津二值化算法 ( Otsu's binarization ) 自动确定二值化图像时的阈值

大津算法,也被称作最大类间方差法,是一种自动确定二值化阈值的算法。

在这里作者不介绍算法推导的过程,算法推导过程网络上有许多介绍,这里只给出算法最终推导出的结论:

S_{b}^{2} = \omega _{0} * \omega _{1} * (M_{0} - M_{1})^{2}

使得左侧 S_{b}^{2}的值最大,就可以得到最好的二值化阈值 t

其中,\omega _{0}和 \omega _{1}是被阈值分开的两个类中的像素数占总像素数的比率。M_{0}和 M_{1}分别是这两个类的像素值的平均值。


废话不多说,直接上python代码:

import cv2

import numpy as np

def BGR2GRAY(img):

    b = img[:, :, 0].copy()

    g = img[:, :, 1].copy()

    r = img[:, :, 2].copy()

    # Gray scale

    out = 0.2126 * r + 0.7152 * g + 0.0722 * b

    out = out.astype(np.uint8)

    return out

# Otsu Binarization

def otsu_binarization(img, th=128):

    max_sigma = 0

    max_t = 0

    # determine threshold

    for _t in range(1, 255):

        v0 = out[np.where(out < _t)]

        m0 = np.mean(v0) if len(v0) > 0 else 0.

        w0 = len(v0) / (H * W)

        v1 = out[np.where(out >= _t)]

        m1 = np.mean(v1) if len(v1) > 0 else 0.

        w1 = len(v1) / (H * W)

        sigma = w0 * w1 * ((m0 - m1) ** 2)

        if sigma > max_sigma:

            max_sigma = sigma

            max_t = _t

    # Binarization

    print("threshold >>", max_t)

    th = max_t

    out[out < th] = 0

    out[out >= th] = 255

    return out

# Read image

img = cv2.imread("../paojie.jpg").astype(np.float32)

H, W, C =img.shape

# Grayscale

out = BGR2GRAY(img)

# Otsu's binarization

out = otsu_binarization(out)

# Save result

cv2.imwrite("out.jpg", out)

cv2.imshow("result", out)

cv2.waitKey(0)

cv2.destroyAllWindows()

输出:

threshold >> 157

 

大津二值化算法 ( Otsu's binarization ) 自动确定二值化图像时的阈值_第1张图片

原图

 

大津二值化算法 ( Otsu's binarization ) 自动确定二值化图像时的阈值_第2张图片

大津二值化后图像


当然,opencv已经为我们实现了 Otsu's binarization 算法,我们可以直接调用它:

import cv2

import numpy as np

def BGR2GRAY(img):

    b = img[:, :, 0].copy()

    g = img[:, :, 1].copy()

    r = img[:, :, 2].copy()

    # Gray scale

    out = 0.2126 * r + 0.7152 * g + 0.0722 * b

    out = out.astype(np.uint8)

    return out

# Read image

img = cv2.imread("../paojie.jpg").astype(np.float32)

# Grayscale

out = BGR2GRAY(img)

# Otsu's binarization of Opencv

ret2,th2 = cv2.threshold(out,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

print("threshold >>", ret2)

# Save result

cv2.imwrite("out.jpg", th2)

cv2.imshow("result", th2)

cv2.waitKey(0)

cv2.destroyAllWindows()


结果类似

threshold >> 156.0

输出图像在此不予展示


参考:https://www.cnblogs.com/wojianxin/p/12493658.html

参考:https://www.jianshu.com/p/67522af22197

 

你可能感兴趣的:(数字图像处理入门)