# -- coding:utf-8 --
# 图像阈值
# 目标:
# 简单阈值,自适应阈值,Otsu’s 二值化
# 函数:cv2.threshold(),cv2.adaptiveThreshold ()
#
# 简单阈值
# 使用cv2.threshold()函数,需要四个参数
# 参数1:一个灰度图
# 参数2:一个阈值(0~255)
# 参数3:一个新值(0~255)
# 参数4:提供了处理阈值的方法:
# cv2.THRESH_BINARY:二值阈值化,超过阈值置新值,低于阈值值0
# cv2.THRESH_BINARY_INV:反向二值阈值化并反转
# cv2.THRESH_TOZERO:超过阈值置0
# cv2.THRESH_TOZERO_INV:低于阈值置0
# cv2.THRESH_TRUNC:截断阈值化,超过阈值的则变为阈值
# 返回两个值,第一个是阈值, 第二个是图像
#
# import cv2
# # import numpy as np
# # 用来展示图片,接受的是一个图片列表
# def showImg(img):
# count = 0
# for i in img:
# cv2.imshow("res"+str(count), i)
# count += 1
# if cv2.waitKey(0) & 0xFF == 27:
# cv2.destroyAllWindows()
# return
# # 返回一个灰度图
# def returnGrayImg(a_file):
# img = cv2.imread(a_file, cv2.IMREAD_GRAYSCALE)
# return cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_CUBIC)
#
# img = cv2.imread("02.jpg",cv2.IMREAD_GRAYSCALE)
# rows, cols = img.shape
# res = cv2.resize(img,None, fx=0.5, fy=0.5, interpolation=cv2.INTER_CUBIC)
# # 原图太大,我先缩小,在处理,即res为我所需要的图
#
# ret1, res1 = cv2.threshold(res, 177, 145, cv2.THRESH_BINARY)
# ret2, res2 = cv2.threshold(res, 177, 145, cv2.THRESH_BINARY_INV)
# ret3, res3 = cv2.threshold(res, 177, 145, cv2.THRESH_TOZERO)
# ret4, res4 = cv2.threshold(res, 177, 145, cv2.THRESH_TOZERO_INV)
# ret5 , res5 = cv2.threshold(res, 177, 145, cv2.THRESH_TRUNC)
# img_list = [res, res1, res2, res3, res4, res5]
# showImg(img_list)
#
# 自适应阈值
# 当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值
# 此时的阈值是根据图像上的每一个小区域计算与其对应的阈值
# 因此在同一幅图像上的不同区域采用的是不同的阈值
# 从而使我们能在亮度不同的情况下得到更好的结果
# 这种方法需要我们指定三个参数,返回值只有一个
# • Adaptive Method - 指定计算阈值的方法:
# – cv2.ADAPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值
# – cv2.ADAPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口
# • Block Size - 邻域大小(用来计算阈值的区域大小)
# • C - 这就是是一个常数,阈值就等于的平均值或者加权平均值减去这个常数
#
# img = returnGrayImg("02.jpg")
# res1 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY, 11, 2)
# res2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 11, 2)
# showImg([img,res1,res2])
#
# Otsu's二值化
#
# 例如一个双峰图,Otsu 算法就是要找到一个阈值(t), 使得同一类加权方差最小,
# 也就是在两个峰之间找到一个阈值 t,将这两个峰分开,并且使每一个峰内的方差最小。
# import cv2
# import numpy as np
#
# def otsu(img):
# if len(img.shape) != 2:
# img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# blur = cv2.GaussianBlur(img, (5, 5), 0)
#
# hist = cv2.calcHist([blur], [0], None, [256], [0, 256])
# hist_norm = hist.ravel() / hist.max()
# Q = hist_norm.cumsum()
#
# bins = np.arange(256)
#
# fn_min = np.inf
# thresh = -1
# for i in xrange(1, 256):
# p1, p2 = np.hsplit(hist_norm, [i]) # probabilities
# q1, q2 = Q[i], Q[255] - Q[i] # cum sum of classes
# b1, b2 = np.hsplit(bins, [i]) # weights
#
# # finding means and variances
# m1, m2 = np.sum(p1 * b1) / q1, np.sum(p2 * b2) / q2
# v1, v2 = np.sum(((b1 - m1) ** 2) * p1) / q1, np.sum(((b2 - m2) ** 2) * p2) / q2
# # calculates the minimization function
# fn = v1*q1 + v2*q2
# if fn < fn_min:
# fn_min = fn
# thresh = i
# # find otsu's threshold value with OpenCV function
# # ret, otsu = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# return cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
#
# old_img = cv2.imread("02.jpg")
# a_img = cv2.resize(old_img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_CUBIC)
# ret, otsu = otsu(a_img)
# print ret
# cv2.imshow("show", otsu)
# if cv2.waitKey(0) & 0xFF == 27:
# cv2.destroyAllWindows()