临时学的,记录一下代码,基于python numpy 实现
Prewitt 等人于六十年代中期提出的直方图双峰法(也称 mode 法) 是典型的全局单阈值分割方法。该方法的基本思想是:假设图像中有明显的目标和背景,则其灰度直方图呈双峰分布,当灰度级直方图具有双峰特性时,选取两峰之间的谷对应的灰度级作为阈值。如果背景的灰度值在整个图像中可以合理地看作为恒定,而且所有物体与背景都具有几乎相同的对比度,那么,选择一个正确的、固定的全局阈值会有较好的效果.算法实现:找到第一个峰值和第二个峰值,再找到第一和第二个峰值之间的谷值,谷值就是那个阀值了。
import numpy as np
# 用于平滑灰度直方图
def smooth1d(line, k_size=11, n=1):
for i in range(n):
line = np.convolve(line, np.ones((k_size,))/k_size, mode='same')
return line
# 寻找峰值,ignore用于忽略部分像素,多峰情况
def findPeak(line, ignore=100):
peak = []
trough = []
for i in range(ignore, len(line) - 1):
if line[i] == 0:
continue
if line[i] > 0 and line[i+1] < 0:
peak.append(i)
elif line[i] < 0 and line[i+1] > 0:
trough.append(i)
return np.array(peak), np.array(trough)
def twoMode(img_gray):
hist, bins = np.histogram(img_gray.ravel(), bins=256, range=(0, 256))
hist = smooth1d(hist, n=3)
s = np.sign(np.diff(np.insert(hist, 0, values=0)))
peak, trough = findPeak(s)
peak = peak[np.argsort(hist[peak])[-2:]]
trough = np.clip(trough, a_min=np.min(peak), a_max=np.max(peak))
trough = trough[np.argmin(hist[trough])]
print('2-mode:', trough)
return trough
1.统计图像灰度直方图,求出图象的最大灰度值和最小灰度值,分别记为ZMAX和ZMIN,令初始阈值T0=(ZMAX+ZMIN)/2;
2. 根据阈值TK将图象分割为前景和背景,计算小于TO所有灰度的均值ZO,和大于TO的所有灰度的均值ZB。
3. 求出新阈值TK+1=(ZO+ZB)/2;
4. 若TK==TK+1,则所得即为阈值;否则转2,迭代计算。
import numpy as np
def iterThresh(img_gray):
zmax = np.max(img_gray)
zmin = np.min(img_gray)
ith_old = 0
ith_new = (zmax + zmin) / 2
while ith_old != ith_new + 1:
zo = np.mean(img_gray[np.where(img_gray > ith_new)])
zb = np.mean(img_gray[np.where(img_gray < ith_new)])
ith_old = ith_new
ith_new = (zo + zb) / 2
print('iter th:', ith_new)
return ith_new
Reference:
[1] 图像分割 传统方法 整理