一、 前言
图像的灰度直方图
灰度直方图是关于灰度级分布的函数,是对图像中灰度级分布的统计。灰度直方图是将数字图像中的所有像素,按照灰度值的大小,统计其出现的频率。灰度直方图是灰度级的函数,它表示图像中具有某种灰度级的像素的个数,反映了图像中某种灰度出现的频率。【from百度百科】
计算直方图
1.使用opencv的函数
cv2.calcHist(images, channels, mask, histSize, ranges)
- 参数1:要计算的原图,以方括号的传入,如:[img]。
- 参数2:类似前面提到的dims,灰度图写[0]就行,彩色图B/G/R分别传入[0]/[1]/[2]。
- 参数3:要计算的区域ROI,计算整幅图的话,写None。
- 参数4:也叫bins,子区段数目,如果我们统计0-255每个像素值,bins=256;如果划分区间,比如0-15,16-31…240-255这样16个区间,bins=16。
- 参数5:range,要计算的像素值范围,一般为[0,256)。
eg:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('test.jpg')
# hist是256x1数组,每个值对应于该图像中具有相应像素值的像素数
hist = cv.calcHist([img],[0],None,[256],[0,256])
# 绘制直方图
plt.plot(hist)
plt.show()
2. 使用Numpy函数
bincount(x, weights=None, minlength=None)
相对应的函数详解可参考:numpy.bincount详解
eg:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('test.jpg')
# ravel()函数将二维矩阵展平变成一维数组
hist = np.bincount(img.ravel(), minlength=256)
# 绘制直方图
plt.plot(hist)
plt.show()
二、 OTSU算法简介
OTSU算法是一种图像二值化算法。其算法假设图像中存在一个阈值 T ,判断图像中每个像素与T的大小关系,可以将所有像素分为背景 C0 和 前景 C1 两类,且当选取到最佳T阈值时,背景部分与前景部分的差别最大,而OTSU 算法利用最大类间方差来衡量这一差别。由于OTSU算法采用了最大类间方法的思想,因此该算法也被OTSU最大类间方差法
缺点:对图像噪声敏感;只能针对单一目标分割;当目标和背景大小比例悬殊、类间方差函数可能呈现双峰或者多峰,这个时候效果不好
三、 数学原理
该算法的原理主要涉及 均值、方差等概念和部分公式的推导
-
将图片的像素值分为 [1, 2, …, L] 个水平,用ni 表示各个水平像素值的像素个数,那么很容易得到总像素个数N为:N = n1 + n2 + … + nL
-
利用像素值对应个数与总数的商作为某个像素值出现的概率,定义pi
p i = n i / N , p i ≥ 0 , ∑ i = 1 L p i = 1 (1) p_i = n_i/N, p_i ≥ 0, \sum_{i=1}^L p_i = 1 \tag1 pi=ni/N,pi≥0,i=1∑Lpi=1(1) -
定义两个量w0 , w1为C0,C1的局部概率之和,并且得到二者的关系
w 0 = P r ( C 0 ) = ∑ i = 1 k p i = w ( k ) (2) w_0 = Pr(C_0) = \sum_{i=1}^k p_i = w(k) \tag2 w0=Pr(C0)=i=1∑kpi=w(k)(2)
w 1 = P r ( C 1 ) = ∑ i = k + 1 L p i = 1 − w ( k ) (3) w_1 = Pr(C_1) = \sum_{i=k+1}^L p_i = 1 - w(k) \tag3 w1=Pr(C1)=i=k+1∑Lpi=1−w(k)(3) -
由此我们得到总的数学期望【期望是平均数随样本趋于无穷的极限,所以可以将期望 ≈ 均值】和C0 , C1各自的数学期望并指出三者的关系,式中 i 代表像素值,除于各自概率的和用于进行归一。
u 0 = ∑ i = 1 k P r ( i ∣ C 0 ) = ∑ i = 1 k i ∗ p i / w 0 = u ( k ) w ( k ) (4) u_0 = \sum_{i=1}^k Pr(i|C_0) = \sum_{i=1}^k i * p_i / w_0 = \frac{u(k)}{w(k)} \tag4 u0=i=1∑k