图像预处理-二值化
图像预处理-二值化二值化,使得图像呈现明显的黑白效果,二值化一方面减少了数据维度,另一方面通过排除原图中噪声带来的干扰,可以凸显有效区域的轮廓结构。目前,二值化的方法主要分为以下几种:全局阈值法(global binarization)固定阈值法otsu法局部阈值法(local binarization)基于深度学习方法全局阈值法1.固定阈值方法对于输入图形中的所有像素点统一使用一个固定阈值g(x
图像预处理-二值化
二值化,使得图像呈现明显的黑白效果,二值化一方面减少了数据维度,另一方面通过排除原图中噪声带来的干扰,可以凸显有效区域的轮廓结构。
目前,二值化的方法主要分为以下几种:
- 全局阈值法(global binarization)
- 固定阈值法
- otsu法
- 局部阈值法(local binarization)
- 基于深度学习方法
全局阈值法
1.固定阈值方法
对于输入图形中的所有像素点统一使用一个固定阈值
g ( x , y ) = { 255 , if f(x, y) ≥ T 0 , else g(x,y) = \begin{cases} 255, & \text{if } \text{f(x, y)} \geq \text{T}\\ 0, & \text{else } \end{cases} g(x,y)={255,0,if f(x, y)≥Telse
T是超参数值,自己指定。
面临的一个问题是,很难为不同的输入图像确定最佳阈值
#!/bin/python
# fileUsing: use threshold value T to binary image
import cv2
from matplotlib import pyplot as plt
image = cv2.imread("img/2-1.png")
# 将输入图像转为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 绘制灰度图
plt.subplot(121), plt.imshow(gray, "gray")
plt.title("input image"), plt.xticks([]), plt.yticks([])
# 对灰度图使用 全局阈值 算法
h, w = gray.shape
T = 100 # set threshold value
for y in range(w):
for x in range(h):
if gray[x][y] < T:
gray[x][y] = 0
else:
gray[x][y] = 255
# 绘制阈值图
plt.subplot(122), plt.imshow(gray, "gray")
plt.title("thread image"), plt.xticks([]), plt.yticks([])
plt.show()
Otsu算法
Otsu算法也称为最大类间方差,是一种自适应的阈值确定方法。
基本思想如下:
将图像的像素分布图画出来,那么图像上应该有两个比较明显的波峰,即对应前景和背景。在这两个波峰之间肯定有一个谷,那么可以将分割阈值设在这里,从而对图像达到一个良好的分割效果。Ostu算法就是基于这样的思想去进行分割的,它是求出用这个阈值分割后的两个图像的类间方差,尽可能的让类间方差最大的那个像素值,即为分割阈值。
具体而言,将输入图像0-255分为L个灰度等级,n_i 表示灰度级为i的元素个数,像素总数N为N=n1+n2+n3+…+nL,。
- 对于每个灰度等级,都去统计整个像素值中有多少属于等级的元素个数,比如将灰度值分为0-m个等级,对于0-m的每一个灰度值t,将它作为阈值将图像分割为灰度值为0t以及t+1m这两部分
- 计算每一部分的所占比例w1,w2 ,每一部分的平均灰度值u1,u2 ,以及总的平均灰度值u
- 计算他们的类间方差δ2=w1(u1−u)^2+w2(u2−u)^2=w1w2(u1−u2)^2
- 取出类间方差最大时对应的阈值t,这就可以作为我们最终所取的阈值。
实现:
import cv2
import sys
from matplotlib import pyplot as plt
image = cv2.imread("img/2-1.png")
# 将输入图像转为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 绘制灰度图
plt.subplot(311), plt.imshow(gray, "gray")
plt.title("input image"), plt.xticks([]), plt.yticks([])
# 对灰度图使用 Ostu 算法
ret1, th1 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) # 有实现
cv2.imwrite('th1.jpg', th1)
# 绘制灰度直方图
plt.subplot(312), plt.hist(gray.ravel(), 256)
# 标注 Ostu 阈值所在直线
plt.axvline(x=ret1, color='red', label='otsu')
plt.legend(loc='upper right')
plt.title("Histogram"), plt.xticks([]), plt.yticks([])
# 绘制二值化图像
plt.subplot(313), plt.imshow(th1, "gray")
plt.title("output image"), plt.xticks([]), plt.yticks([])
plt.show()
参考
更多推荐
所有评论(0)