学习视频可参见python opencv3.3视频教学 基础入门[1]
outline
- 图像二值化
- 二值图像
- 图像二值化方法
- OpenCV相关API使用
图像二值化
1.二值图像
- 二值图像就是将灰度图转化成黑白图,没有灰,在一个值之前为黑,之后为白
2.二值化方法
- 全局阈值
- 对整幅图像都是用一个统一的阈值来进行二值化
- 局部阈值
- 像素的邻域块的像素值分布来确定该像素位置上的二值化阈值
3.OpenCV中图像二值化方法
二值化函数threshold
- 函数原型
- 关于常见的阈值使用方法如下表
OTSU(最大类间方差法)
- 基于Otsu的全局阈值处理又称最大类间方差法,即在对图像进行阈值分割时,选定的分割阈值应使前景区域的平均灰度,背景区域的平均灰度与整幅图像的平均灰度之间差别最大,这种差异用区域的方差来表示
- 参见基于Otsu的全局阈值处理的实现[2]
def threehold_demo(image):
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY) #转换为灰度图
ret,binary=cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU) #灰度图转二值图
print("threehold value %s"%ret)
cv.imshow("binary",binary)
threehold value 117.0 #阈值为117,大于117为白,小于117为黑
Triangle
- 该方法是使用直方图数据,基于纯几何方法来寻找最佳阈值,它的成立条件是假设直方图最大波峰在靠近最亮的一侧,然后通过三角形求得最大直线距离,根据最大直线距离对应的直方图灰度等级即为分割阈值
- 在直方图上从最高峰处bmx到最暗对应直方图bmin(p=0)%构造一条直线,从bmin处开始计算每个对应的直方图b到直线的垂直距离,知道bmax为止,其中最大距离dmax对应的直方图位置即为图像二值化对应的阈值T=dmax。
- 参见【图像处理】——图像的二值化操作及阈值化操作[3]
- 结果如下:
自动与手动
- 手动指定阈值
- 测试结果
ret,binary=cv.threshold(gray,127,255,cv.THRESH_BINARY_INV)
cv.THRESH_TRUNC
ret,binary=cv.threshold(gray,127,255,cv.THRESH_TRUNC)
cv.THRESH_TOZERO
ret,binary=cv.threshold(gray,127,255,cv.THRESH_TOZERO)
adaptiveThreshold (自适应阈值)
- 局部阈值法
- 局部阈值原理:以目标像素点为中心选择一个块,然后对块区域里面的像素点进行高斯或者均值计算,将得到的平均值或者高斯值作为目标像素点的阈值,以此来对目标像素格进行二值化。对图像每一个像素格进行如此操作就完成了对整个图像的二值化处理。
adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
#返回二值化后的图像矩阵-> dst
src参数:表示输入图像(8位单通道图像),灰度图。
maxValue参数:表示使用 THRESH_BINARY 和 THRESH_BINARY_INV 的最大值.
adaptiveMethod参数:表示自适应阈值算法,平均 (ADAPTIVE_THRESH_MEAN_C)或高斯(ADAPTIVE_THRESH_GAUSSIAN_C)。
thresholdType参数:表示阈值类型,必须为THRESH_BINARY或THRESH_BINARY_INV的阈值类型。
blockSize参数:表示块大小(奇数且大于1,比如3,5,7........ )。
C参数:常数,表示从平均值或加权平均值中减去的数。 通常情况下,这是正值,但也可能为零或负值
均值-c>0为白
一般情况下blocksize过大会导致图像细节的丢失,过小虽然保存了图像细节,但是也使得运行的时间大幅增加,因此需要进行权衡。
一般情况参数C是大于0的,C越大说明最后的阈值就会越小,这样导致的结果就是图像的大部分像素会被转换为亮域,即更多的像素点的灰度值大于阈值,被转化为255亮域。C越小时则恰恰相反
def threehold_local(image):
gray=cv.cvtColor(image,cv.COLOR_BGR2GRAY)
binary=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,25,10)
#binary=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,25,10)
cv.imshow("binary",binary)
遇到比较大的图像处理
- 将大图片拆分成小图片后再用自适应局部阈值比较好
- 结果如下:
参考资料
[1]
python opencv3.3视频教学 基础入门: https://www.bilibili.com/video/BV1QW411F7e7?p=1
[2]
基于Otsu的全局阈值处理的实现: https://blog.csdn.net/m0_38061927/article/details/77362877
[3]
【图像处理】——图像的二值化操作及阈值化操作: https://blog.csdn.net/qq_45769063/article/details/107102117#(2)三角法TRIANGLE阈值类型——适用于单峰直方图