基于点的全局阈值选取方法:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('grey-gradient.jpg', 0)
ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
基于区域的全局阈值选取方法:
import numpy as np
import cv2
import math
image = cv2.imread(r"./cat/cat1.png", 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)
局部阈值:
import cv2
import numpy as np
from matplotlib import pyplot as plt
# img = cv2.imread('dave.jpg', 0)
img = cv2.imread('../data/sudoku.jpg', 0)
# 中值滤波
img = cv2.medianBlur(img, 5)
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 11 为 Block size 邻域大小 用来计算阈值的区域大小 ,
# 2 为 C值,常数, 阈值就等于的平均值或者加权平均值减去这个常数。
th2=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
th3=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
titles = ['Original Image', 'Global Thresholding (v = 127)',
'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
多阈值法:
import cv2
import numpy as np
# 多阈值处理
def double_threshold_processing(x): # x 为传入的图像
hist = cv2.calcHist([x], [0], None, [256], [0, 256]) # 图像的灰度直方图 shape = (256,1)
grayScale = np.arange(256).reshape(1, -1) # 灰度级 [0,255] shape =(1,256)
sum_pixels = x.shape[0] * x.shape[1] # 图像总共像素点的个数
mG = x.mean() # 整幅图像的平均灰度
T1,T2,varMax = 0,0,0.0 # 双阈值T1、T2,类间方差varMax
for k1 in range(1,254): # k1范围在1 - 253之间 1 ~ L-3
gray_G1 = grayScale[:, :k1 + 1] # 灰度值 0~k1 的子区域G1
hist_G1 = hist[:k1 + 1, :] # 子区域G1的直方图 0~k1 ,对应每个灰度值的像素点
sum_gray_G1 = np.dot(gray_G1, hist_G1) # G1 区域所有像素点灰度值总和 = 灰度值 * 对应像素点的个数
sum_pixels_G1 = sum(hist_G1) # G1 像素数量
P1 = sum_pixels_G1 / sum_pixels # G1 像素占比
m1 = (sum_gray_G1 / sum_pixels_G1) if sum_pixels_G1 > 0 else 0
# G1 像素的平均灰度
for k2 in range(k1+1,255): # k2范围在 k1+1 ~ 254 之间 k1+1 ~ L-2
gray_G3 = grayScale[:,k2:] # 灰度值 k2~L-1 的子区域G3
hist_G3 = hist[k2:,:] # 子区域G3的直方图 k2~L-1 ,对应每个灰度值的像素点
sum_gray_G3 = np.dot(gray_G3,hist_G3) # G3 区域所有像素点灰度值总和 = 灰度值 * 对应像素点的个数
sum_pixels_G3 = sum(hist_G3) # G3 像素数量
P3 = sum_pixels_G3 / sum_pixels # G3 像素占比
m3 = (sum_gray_G3 / sum_pixels_G3) if sum_pixels_G3 > 0 else 0 # G3 平均灰度
P2 = 1.0 - P1 - P3 # G2 区域的像素占比
m2 = ((mG - P1 * m1 - P3 * m3) / P2) if P2 > 0 else 0 # G2 平均灰度
varB = P1 * (m1 - mG) ** 2 + P2 * (m2 - mG) ** 2 + P3 * (m3 - mG) ** 2 # 类间方差
if varB > varMax: # 保存最大的类间方差
T1,T2,varMax = k1,k2,varB
x[x <= T1] = 0
x[(x>T1)&(x<T2)] = 123 # 中间的灰度,可以更改
x[x >= T2] = 255
return T1,T2,x
img = cv2.imread("img.tif",0)
ret1,ret2,dst = double_threshold_processing(img.copy()) # 多阈值处理
print(ret1,ret2)
cv2.imshow('img',np.hstack((img,dst)))
cv2.waitKey()
cv2.destroyAllWindows()