学习资料参考:
张平.《OpenCV算法精解:基于Python与C++》.[Z].北京.电子工业出版社.2017.
前言
在对图像进行阈值分割之时,所选取的分割阈值应使前景区域的平均灰度、背景区域的平均灰度与整幅图像的平均灰度之间的差异最大,这种差异用区域的方差来表示。
原理详解
假设输入图像为,高为
、宽为
,
代表归一化的图像的灰度直方图,
代表灰度值等于
的像素点个数在图像中所占的比率,其中k在0到255的范围。
实现步骤
-
计算灰度直方图的累加直方图
-
计算灰度直方图的一阶累积距
-
计算图像
总体的灰度平均值mean
-
将每一个灰度级作为阈值时,前景区域的平均灰度、背景区域的平均灰度与整幅图像的平均灰度的方差。
-
找到最大的方差,其中该方差对应的k就是Otsu选取的阈值。
Python实现
import numpy as np
import cv2
import math
image = cv2.imread(r"C:\Users\1\Pictures\test.jpg", 0)
rows, cols = image.shape[:2]
gray_hist = np.zeros([256], np.uint64)
for i in range(rows):
for j in range(cols):
gray_hist[image[i][j]] += 1
uniformGrayHist = gray_hist / float(rows * cols)
# 计算零阶累积距和一阶累积距
zeroCumuMomnet = np.zeros(256, np.float32)
oneCumuMomnet = np.zeros(256, np.float32)
for k in range(256):
if k == 0:
zeroCumuMomnet[k] = uniformGrayHist[0]
oneCumuMomnet[k] = (k) * uniformGrayHist[0]
else:
zeroCumuMomnet[k] = zeroCumuMomnet[k - 1] + uniformGrayHist[k]
oneCumuMomnet[k] = oneCumuMomnet[k - 1] + k * uniformGrayHist[k]
# 计算类间方差
variance = np.zeros(256, np.float32)
for k in range(255):
if zeroCumuMomnet[k] == 0 or zeroCumuMomnet[k] == 1:
variance[k] = 0
else:
variance[k] = math.pow(oneCumuMomnet[255] * zeroCumuMomnet[k] - oneCumuMomnet[k], 2) / (
zeroCumuMomnet[k] * (1.0 - zeroCumuMomnet[k]))
# 找到阈值
threshLoc = np.where(variance[0:255] == np.max(variance[0:255]))
thresh = threshLoc[0][0]
# 阈值处理
threshold = np.copy(image)
threshold[threshold > thresh] = 255
threshold[threshold <= thresh] = 0
cv2.imshow("test", threshold)
cv2.waitKey(0)
运行结果
原图
处理后的图像
文章出处登录后可见!
已经登录?立即刷新