Python OpenCV自适应阈值二值化详解:cv2.adaptiveThreshold函数使用指南
本文深入解析OpenCV中cv2.adaptiveThreshold函数的应用,针对全局阈值法在明暗不均图像中失效的问题,介绍如何通过局部区域计算动态阈值。详细讲解ADAPTIVE_THRESH_MEAN_C与GAUSSIAN_C两种算法、blockSize及C参数的影响,并结合Python代码演示如何优化轮廓提取效果。
自适应阈值二值化的背景与问题
在前一篇关于OpenCV二值化方法threshold的使用探讨中,我们注意到该方法存在一定的局限性。当图像中存在明显的明暗差异区域时,单一全局阈值往往难以处理,例如以下示例图片所示的情况。

从图中可以观察到,左侧区域由于整体亮度较低,在使用固定阈值进行二值化处理后,该区域完全变为黑色,导致所有细节信息丢失。这显然不符合我们期望的处理结果。
造成这一现象的原因是,threshold函数采用单一固定阈值对整张图像进行二值化操作,所有低于该阈值的像素点均被设置为0。因此,这种基于全局阈值的二值化方法并不适用于上述具有显著亮度差异的图像。那么,如何解决这一问题呢?
观察上述图像可以发现,左右两个区域的亮度差异显著。最简单的解决方案是将图像分割为两个区域,分别对每个区域进行二值化处理,即针对该图像使用两个不同的阈值。如果图像中存在三个、四个或更多亮度不同的区域,则应对每个区域分别应用相应的阈值进行二值化。基于这一思路,OpenCV提供了cv2.adaptiveThreshold函数。
首先,我们来看一下adaptiveThreshold函数在二值化处理中的实际效果。

结果显示,该方法确实有效,至少左侧区域不再呈现全黑状态,保留了一定的细节信息。
cv2.adaptiveThreshold函数参数详解
接下来,我们将简要介绍adaptiveThreshold方法的具体实现原理。
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
该函数的基本逻辑是:以图像中的每个像素点为中心,选取一个N*N大小的邻域区域,计算该区域的阈值,从而决定该像素点是被设置为0还是255。
src:需要进行二值化处理的灰度图像。
maxValue:当像素点满足条件时,需要设置的灰度值(即目标灰度值)。
adaptiveMethod:自适应阈值计算算法,可选值为ADAPTIVE_THRESH_MEAN_C或ADAPTIVE_THRESH_GAUSSIAN_C。
thresholdType:OpenCV提供的二值化方法,仅支持THRESH_BINARY或THRESH_BINARY_INV。
blockSize:划分的区域大小,即上述N值,通常建议取奇数。
C:常数,每个区域计算出的阈值基础上减去该常数,作为该区域的最终阈值,C可以为负数。
dst:输出图像,此参数通常可以忽略。
前两个参数src和maxval与threshold函数中的对应参数含义相同。
自适应算法与阈值类型
第三个参数adaptiveMethod决定了阈值计算的具体方式。
该参数提供了两种不同的阈值计算方法,参考其他技术文章的解释如下:
ADAPTIVE_THRESH_MEAN_C:基于局部邻域块的平均值。该算法首先计算邻域块内的像素均值。
ADAPTIVE_THRESH_GAUSSIAN_C:基于局部邻域块的高斯加权和。该算法根据像素点(x, y)周围像素距离中心点的距离,利用高斯函数进行加权计算。
第四个参数thresholdType指定二值化的类型。
该参数仅支持THRESH_BINARY或THRESH_BINARY_INV两种选项。
邻域大小与常数C的影响
第五个参数blockSize定义了邻域的大小。
这是上述算法计算邻域时所使用的邻域尺寸,通常选择3、5、7等奇数。
第六个参数C用于调整最终阈值。
每个邻域计算出的阈值需减去C,作为该区域的最终阈值。
参数影响演示与总结
下面通过示例演示blockSize和C参数对二值化结果的影响,以THRESH_BINARY和ADAPTIVE_THRESH_GAUSSIAN_C为例进行说明。







从结果可以看出,当blockSize增大时,参与阈值计算的区域范围变大,导致细节轮廓减少,整体轮廓变得更加粗犷且明显。
当C值增大时,每个像素点N*N邻域计算出的阈值变小,中心点像素值大于该阈值的概率增加,从而被设置为255的概率增大,导致图像中白色像素增多;反之,C值减小则白色像素减少。
这种二值化方法与Canny边缘检测有相似之处,在寻找轮廓或特征点方面具有不错的效果。
import cv2
import numpy as np
blocksize = 3
C=0
def adaptive_demo(gray, blocksize, C):
binary = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, blocksize, C)
# binary = cv2.GaussianBlur(binary, (15,15), 0)
cv2.imshow('binary', binary)
def C_changed(value):
global gray
global blocksize
global C
C = value - 30
print('C:', C)
adaptive_demo(gray, blocksize, C)
def blocksize_changed(value):
blocksize = 2 * value + 1
print('blocksize:', blocksize)
if __name__ == "__main__":
image_path = './img/1.jpg'
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
adaptive_demo(gray, 3, 0)
cv2.createTrackbar('C', 'binary',0, 60, C_changed)
cv2.createTrackbar('blocksize', 'binary',1, 20, blocksize_changed)
cv2.waitKey(0)至此,关于Python3 OpenCV图像二值化(cv2.adaptiveThreshold)的笔记介绍完毕。如需了解更多相关Python3 OpenCV图像二值化内容,请搜索本站历史文章或继续浏览后续相关文章。希望大家今后能多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













