160. 图像处理之OTSU 方法

9. 阈值处理与边缘检测索引

一、全局阈值处理 Otsu 方法

  • 阈值处理本质上是对像素进行分类的统计决策问题。

  • OTSU 方法又称大津算法,使用最大化类间方差(intra-class variance)作为评价准则,基于对图像直方图的计算,可以给出类间最优分离的最优阈值。
    任取一个灰度值 T,可以将图像分割为两个集合 F 和 B,集合 F、B 的像素数的占比分别为 pF、pB,集合 F、B 的灰度值均值分别为 mF、mB,图像灰度值为 m,定义类间方差为:



    使类间方差 ICV 最大化的灰度值 T 就是最优阈值。
    因此,只要遍历所有的灰度值,就可以得到使 ICV 最大的最优阈值 T。

二、函数

  • OpenCV 提供了函数 cv.threshold 可以对图像进行阈值处理,将参数 type 设为 cv.THRESH_OTSU,就可以使用使用 OTSU 算法进行最优阈值分割。

三、例程

  • 11.17:OTSU 最优全局阈值处理
import cv2
import numpy as np
from matplotlib import pyplot as plt

# 11.17 OTSU 最优全局阈值处理
img = cv2.imread(r"E:/OpenCV/Fig1039a.jpg", flags=0)

deltaT = 1  # 预定义值
histCV = cv2.calcHist([img], [0], None, [256], [0, 256])  # 灰度直方图
grayScale = range(256)  # 灰度级 [0,255]
totalPixels = img.shape[0] * img.shape[1]  # 像素总数
totalGray = np.dot(histCV[:,0], grayScale)  # 内积, 总和灰度值
T = round(totalGray/totalPixels)  # 平均灰度
while True:
    numC1, sumC1 = 0, 0
    for i in range(T): # 计算 C1: (0,T) 平均灰度
        numC1 += histCV[i,0]  # C1 像素数量
        sumC1 += histCV[i,0] * i  # C1 灰度值总和
    numC2, sumC2 = (totalPixels-numC1), (totalGray-sumC1)  # C2 像素数量, 灰度值总和
    T1 = round(sumC1/numC1)  # C1 平均灰度
    T2 = round(sumC2/numC2)  # C2 平均灰度
    Tnew = round((T1+T2)/2)  # 计算新的阈值
    print("T={}, m1={}, m2={}, Tnew={}".format(T, T1, T2, Tnew))
    if abs(T-Tnew) < deltaT:  # 等价于 T==Tnew
        break
    else:
        T = Tnew

# 阈值处理
ret1, imgBin = cv2.threshold(img, T, 255, cv2.THRESH_BINARY)  # 阈值分割, thresh=T
ret2, imgOtsu = cv2.threshold(img, T, 255, cv2.THRESH_OTSU)  # 阈值分割, thresh=T
print(ret1, ret2)

plt.figure(figsize=(7,7))
plt.subplot(221), plt.axis('off'), plt.title("Origin"), plt.imshow(img, 'gray')
plt.subplot(222, yticks=[]), plt.title("Gray Hist")  # 直方图
histNP, bins = np.histogram(img.flatten(), bins=255, range=[0, 255], density=True)
plt.bar(bins[:-1], histNP[:])
plt.subplot(223), plt.title("global binary(T={})".format(T)), plt.axis('off')
plt.imshow(imgBin, 'gray')
plt.subplot(224), plt.title("OTSU binary(T={})".format(round(ret2))), plt.axis('off')
plt.imshow(imgOtsu, 'gray')
plt.tight_layout()
plt.show()

三、资料

youcans_的博客:
https://blog.csdn.net/youcans/article/details/124281210
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容