学习资料参考:
张平.《OpenCV算法精解:基于Python与C++》.[Z].北京.电子工业出版社.2017.
前言
熵算法中的熵,经过资料学习,即信息熵,这是一种量化信息的说法。即把信息中拍出来冗余后的平均信息量称为“信息熵”。感觉不太好懂,先看公式(如下图)
其中
P
(
x
i
)
P(x_i)
P(xi)代表随机事件X为
x
i
x_i
xi的概率。通俗来讲,信息用信息量来衡量,信息量跟具体发生的事件的概率有关。并且从公式可以看出概率越大,时间的信息熵越小。如果要深层次理解,请查其他资料。
将图像
I
I
I当作信源
I
I
I,
n
o
r
m
H
i
s
t
i
normHist_i
normHisti表示归一化的图像灰度直方图,即
i
i
i的范围是0到255,且
n
o
r
m
H
i
s
t
i
normHist_i
normHisti就可看做256个像素值的出现概率。
那么计算步骤如下:
-
计算 I I I的累加概率直方图,记为
-
计算各个灰度级的熵,记为
-
计算使 f ( t ) = f 1 ( t ) + f 2 ( t ) f(t) = f_1(t) + f_2(t) f(t)=f1(t)+f2(t)最大化的 t t t值,该值即为多得到的阈值,即tresh = a r g i m a x ( f ( t ) ) arg_i max(f(t)) argimax(f(t)),其中
import math
import numpy as np
import cv2
image = cv2.imread(r"C:Users1Picturestest.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
# 归一化灰度直方图,即概率直方图
normGrayHist = gray_hist / float(rows * cols)
# 累加直方图
zeroCumuMoment = np.zeros(256, np.float32)
for i in range(256):
if i == 0:
zeroCumuMoment[i] = normGrayHist[i]
else:
zeroCumuMoment[i] = zeroCumuMoment[i - 1] + normGrayHist[i]
# 计算灰度级的熵
entropy = np.zeros(256, np.float32)
for i in range(256):
if i == 0:
if normGrayHist[i] == 0:
entropy[i] = 0
else:
entropy[i] = - normGrayHist[i] * math.log10(normGrayHist[i])
else:
if normGrayHist[i] == 0:
entropy[i] = entropy[i - 1]
else:
entropy[i] = entropy[i - 1] - normGrayHist[i] * math.log10(normGrayHist[i])
# 阈值计算
fT = np.zeros(256, np.float32)
ft1, ft2 = 0.0, 0.0
totalEntroy = entropy[255]
for i in range(255):
maxFront = np.max(normGrayHist[0:i + 1])
maxBack = np.max(normGrayHist[i + 1:256])
if maxFront == 0 or zeroCumuMoment[i] == 0 or maxFront == 1 or zeroCumuMoment[i] == 1 or totalEntroy == 0:
ft1 = 0
else:
ft1 = entropy[i] / totalEntroy * (math.log10(zeroCumuMoment[i]) / math.log10(maxFront))
if maxBack == 0 or 1 - zeroCumuMoment[i] == 0 or maxBack == 1 or zeroCumuMoment[i] == 1:
ft2 = 0
else:
if totalEntroy == 0:
ft2 = (math.log10(1 - zeroCumuMoment[i]) / math.log10(maxBack))
else:
ft2 = (1 - entropy[i] / totalEntroy) * (math.log10(1 - zeroCumuMoment[i]) / math.log10(maxBack))
fT[i] = ft1 + ft2
threshLoc = np.where(fT == np.max(fT))
thresh = threshLoc[0][0]
# 阈值处理
threshold = np.copy(image)
threshold[threshold > thresh] = 255
threshold[threshold <= thresh] = 0
cv2.imshow("test", threshold)
cv2.waitKey(0)
运行结果
原图
处理后的图片



