对于给定的阈值\(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)指出,进群答案:数字图像处理。在本文评论指出可能导致回复很晚。
 
                    
                     
                    
                 
                    
                 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号