在此列出,后面将直接使用,不再赘述
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def show(img):
if img.ndim == 2:
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
else:
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()
算法描述:根据图像灰度直方图,人工寻找阈值
算法特点:适用双峰图像
导入图片
img = cv.imread('pic/eagle.jpg', 0)
show(img)
plt.hist(img.ravel(), 256, [0, 256])
plt.show()
plt.hist(img.flatten(), np.arange(-0.5, 256, 1), color='g')
plt.show()
_, img_bin = cv.threshold(img, 125, 255, cv.THRESH_BINARY)
show(img_bin)
论文:AUTOMATIC MEASUREMENT OF SISTER CHROMATID EXCHANGE FREQUENCY
算法思想:几何法,适用单峰图像
img = cv.imread('pic/blossom', 0)
show(img)
plt.hist(img.flattern(), np.arange(-0.5, 256, 1), color='g')
plt.show()
th, img_ = cv.threshold(img, 0, 255, cv.THRESH_TRIANGLE)
print(th)
show(np.hstack([img, img_bin])
三角法自动寻找阈值,第二个参数随便写就行
前景为 > T >T >T的部分,背景为 < T
<T 的部分
a = np.random.randint(0, 10, (4, 4))
a[a <= 5]
a[a <= 5].mean()
img = cv.imread('pic/eagle', 0)
T = img.mean()
while True:
t0 = img[img < T].mean() // 背景平均灰度值
t1 = img[img >= T].mean() // 前景平均灰度值
t = (t0 + t1) / 2
print(T, t)
if T == t: // 可适当放宽条件, abs(T-t) < 1
break
T = t
T = int(T) // 浮点数没有用
ptint(f"Best Threshold = {T}")
Best Threshold = 120
算法思想:最大类间方差
对于给定阈值 T T T,可以将图像分为目标和背景。其中背景点数占图像比例为 p 0 p_0 p0,平均灰度值为 m 0 m_0 m0。而且标定数占图像比例为 p 1 p_1 p1,平均灰度值为 m 1 m_1 m1,其中满足
p 0 + p 1 = 1 p_0+p_1=1 p0+p1=1
整幅图像的平均灰度值为常数,跟阈值无关,且为
m ˉ = p 0 m 0 + p 1 m 1 \bar m = p_0m_0+p_1m_1 mˉ=p0m0+p1m1
类间方差为
σ 2 = p 0 ( m 0 − m ˉ ) 2 + p 1 ( m 1 − m ˉ ) 2 \sigma^2=p_0(m_0-\bar m)^2+p_1(m_1-\bar m)^2 σ2=p0(m0−mˉ)2+p1(m1−mˉ)2
代入 p 0 + p 1 = 1 和 m ˉ p_0+p_1=1和\bar m p0+p1=1和mˉ可简化为
σ 2 = p 0 p 1 ( m 0 − m 1 ) 2 \sigma^2=p_0p_1(m_0-m_1)^2 σ2=p0p1(m0−m1)2
遍历灰度值,找出能使 σ 2 \sigma^2 σ2最大的值
img = cv.imread('pic/eagle.jpg', 0)
th, img_bin = cv.threshod(img, -1, 255, cv.THRESH_OTSU)
print(th)
show(img_bin)
img = cv.imread('pic/eagle', 0)
Sigma = -1
T = 0
for t in range(0, 256):
bg = img[img <= t]
obj = img[img > t]
p0 = bg.size / img.size
p1 = obj.size / img.size
m0 = 0 if obj.size==0 else bg.mean()
m1 = 0 if obj.size==0 else obj.mean()
sigma = p0*p1*(m0-m1)**2
if sigma > Sigma:
Sigma = sigma
T = t
算法思想:局部二值化
全局二值化容易受阴影影响,所以可以局部二值化。自适应阈值分割的本质就是局部二值化。
注:邻域大小一般要大于目标大小,但也不能太大,否则效果不好。
img = cv.imread('pic/page', 0)
show(img)
img_bin = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 21, 6)
show(img_bin)
一. 通过超参数C实现
img = cv.imrad('pic/page', 0)
C = 0
winSize = 21 // 和一个字体差不多大
img_blur = cv.blur(img, (winSize, winSize))
show(img > img_blur)
C = 6
img_bin = np.uint8(img>img_blur.astype(np.int) - C) * 255
show(img_bin)
img = cv.imread('pic/page.jpg', 0)
alpha = 0.15
winSize = 21
img_blur = cv.GaussianBlur(img, (winSize, winSize), 5)
img_bin = np.uint8(img > (1-alpha) * img_blur) * 255
show(img_bin)