7.1 Python图像处理之图像分割-自适应阈值
1 算法原理
在不均匀照明或者灰度值分布不均的情况下,如果使用全局阈值分割,那么得到的分割效果往往会很不理想。显然得到的结果只是将光照较强的区域分割出来了,而阴影部分或者光照较弱的区域却没有分割出来。既然全局阈值不合适,那么想到的策略是针对每一个位置的灰度值设置一个对应的阈值,而该位置阈值的设置也和其邻域有必然的关系。
在对图像进行平滑处理时,均值平滑、高斯平滑、中值平滑用不同规则计算出以当前像素为中心的邻域内的灰度“平均值”,所以可以使用平滑处理后的输出结果作为每个像素设置阈值的参考值,如参考文献[]中提到用均值滤波后的结果乘以某个比例系数作为最后的阈值矩阵。
在自适应阈值处理中,平滑算子的尺寸决定了分割出来的物体的尺寸,如果滤波器尺寸太小,那么估计出的局部阈值将不理想。凭经验,平滑算子的宽度必须大于被识别物体的宽度,平滑算子的尺寸越大,平滑后的结果越能更好地作为每个像素的阈值的参考,当然也不能无限大。
假设输入图像为I,高为H、宽为W,平滑算子的尺寸记为H×W,其中W和H均为奇数。自适应阈值分割算法的步骤如下。
第一步:对图像进行平滑处理,平滑结果记为 smooth(I),其中 smooth可以代表均值平滑、高斯平滑、中值平滑。
第二步:自适应阈值矩阵 Thresh=(1-raio)* smooth(I),一般令 ratio:=0.15。
第三步:利用局部阈值分割的规则
2 代码
运行代码说明
1.要改变代码中的图片地址(地址不能有中文)
最后一行代码:更改
put(path)
函数中的路径put(r'../image/image1.jpg')
2.注意最后的
plt.savefig('1.new.jpg')
是保存plt图像,如果不使用可以注释掉代码依赖包:
matplotlib 3.4.2 numpy 1.20.3 opencv-python 4.1.2.30
# pip安装 pip install matplotlib numpy opencv-python
import cv2
import numpy as np
from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 自适应动态阈值分割
def adaptiveThresh(I, winSize, ratio=0.15):
# 第一步:对图像矩阵进行均值平滑
I_mean = cv2.boxFilter(I, cv2.CV_32FC1, winSize)
# 第二步:原图像矩阵与平滑结果做差
out = I - (1.0 - ratio) * I_mean
# 第三步:当差值大于或等于0时,输出值为255;反之,输出值为0
out[out >= 0] = 255
out[out < 0] = 0
out = out.astype(np.uint8)
return out
def put(path):
# 0是表示直接读取灰度图
image = cv2.imread(path, 0)
ad_img = adaptiveThresh(image, (5, 5))
plt.subplot(121), plt.imshow(image, "gray")
plt.title("灰度图"), plt.axis('off')
plt.subplot(122), plt.imshow(ad_img, "gray")
plt.title("自适应动态阈值 "), plt.axis('off')
# plt.savefig('1.new-img.jpg')
plt.show()
# 图像处理函数,要传入路径
put(r'../image/img5.jpg')