原文链接:http://www.juzicode.com/opencv-python-threshold-adaptivethreshold

返回Opencv-Python教程

图像的阈值化(有些场合也称二值化)是图像分割的一种,一般用于将感兴趣区域从背景中区分出来,处理过程就是将每个像素和阈值进行对比,分离出来需要的像素设置为特定白色的255或者黑色的0,具体看实际的使用需求而定。

1、threshold()

threshold的接口形式如下:

cv2.threshold(src, thresh, maxval, type[, dst]) ->retval, dst

该方法返回2个值,第1个值retval为阈值,第2个值dst为阈值化后的图像。

  • 参数含义:

  • src:源图像,8bit或者32bit浮点类型,当type没有使用cv2.THRESH_OTSU或cv2.THRESH_TRIANGLE标志时可以是多通道图像;

  • thresh:比较的阈值;

  • maxval:阈值化方法为THRESH_BINARY和THRESH_BINARY_INV时单个像素转换后的最大值;

  • type:阈值化类型;

type入参的取值如下表:

标志 dst(x,y)取值 条件
cv2.THRESH_BINARY 0 maxval  if src(x,y)>thresh;
0 otherwise
cv2.THRESH_BINARY_INV 1 0 if src(x,y)>thresh;
maxval otherwise
cv2.THRESH_TRUNC 2 threshold if src(x,y)>thresh;
src(x,y) otherwise
cv2.THRESH_TOZERO 3 src(x,y) if src(x,y)>thresh;
0 otherwise
cv2.THRESH_TOZERO_INV 4 0 if src(x,y)>thresh;
src(x,y) otherwise
cv2.THRESH_MASK 7 / /
cv2.THRESH_OTSU 8 / 标志位,使用大津法选择最佳阈值
cv2.THRESH_TRIANGLE 16 / 标志位,使用三角算法选择最佳阈值

其中cv2.THRESH_OTSU或cv2.THRESH_TRIANGLE的使用比较特殊,并不能单独使用,需要和其他类型的数值按位或一起传入,比如这样使用 type=cv2.THRESH_BINARY | cv2.THRESH_OTSU。当然在实际使用中也常见将cv2.THRESH_OTSU或cv2.THRESH_TRIANGLE这2种取值之一和前5种type相加,比如type=cv2.THRESH_BINARY + cv2.THRESH_OTSU,这是因cv2.THRESH_OTSU或cv2.THRESH_TRIANGLE和其他5种type按位或和相加得到的值是一致的。从上面的对照表也可以看到,如果使用cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV得到的图像像素值只有2种,要么是maxval,要么是0,可以称得上真正意义上的“二值化”。

不同type类型做阈值化操作也可以用下图形象的表示,第1张图中折线为图像的像素值,中间的横线为阈值,第2~6张图为5种类型阈值化方法得到的像素值。以Threshold Binary为例,折线部分在阈值线以下的位置阈值化之后的值为0,在阈值线以上的位置阈值化之后的值为maxVal:

图源:opencv.org

下面这个例子使用不同的type和thresh取值阈值化后的效果对比:

import matplotlib.pyplot as plt
import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)#转换
img = cv2.imread('..\\lena.jpg')
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
thr_val, img_ret11 = cv2.threshold(img_gray, 50, 255, cv2.THRESH_BINARY )
thr_val, img_ret12 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY )
thr_val, img_ret13 = cv2.threshold(img_gray, 200, 255, cv2.THRESH_BINARY_INV )
thr_val, img_ret21 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC )
thr_val, img_ret22 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO )
thr_val, img_ret23 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV )
thr_val, img_ret31 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
thr_val, img_ret32 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY|cv2.THRESH_TRIANGLE)#显示图像
fig,ax = plt.subplots(3,3)
ax[0,0].set_title('THRESH_BINARY,50',fontsize=10)
ax[0,0].imshow(cv2.cvtColor(img_ret11,cv2.COLOR_BGR2RGB)) #matplotlib显示图像为rgb格式
ax[0,1].set_title('THRESH_BINARY,127',fontsize=10)
ax[0,1].imshow(cv2.cvtColor(img_ret12,cv2.COLOR_BGR2RGB))
ax[0,2].set_title('THRESH_BINARY_INV,200',fontsize=10)
ax[0,2].imshow(cv2.cvtColor(img_ret13,cv2.COLOR_BGR2RGB))
ax[1,0].set_title('THRESH_TRUNC,127',fontsize=10)
ax[1,0].imshow(cv2.cvtColor(img_ret21,cv2.COLOR_BGR2RGB))
ax[1,1].set_title('THRESH_TOZERO,127',fontsize=10)
ax[1,1].imshow(cv2.cvtColor(img_ret22,cv2.COLOR_BGR2RGB))
ax[1,2].set_title('THRESH_TOZERO_INV,127',fontsize=10)
ax[1,2].imshow(cv2.cvtColor(img_ret23,cv2.COLOR_BGR2RGB))
ax[2,0].set_title('THRESH_OTSU',fontsize=10)
ax[2,0].imshow(cv2.cvtColor(img_ret31,cv2.COLOR_BGR2RGB))
ax[2,1].set_title('THRESH_TRIANGLE',fontsize=10)
ax[2,1].imshow(cv2.cvtColor(img_ret32,cv2.COLOR_BGR2RGB))
ax[2,2].set_title('RAW',fontsize=10)
ax[2,2].imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)) ax[0,0].axis('off');ax[0,1].axis('off');ax[0,2].axis('off')
ax[1,0].axis('off');ax[1,1].axis('off');ax[1,2].axis('off')
ax[2,0].axis('off');ax[2,1].axis('off');ax[2,2].axis('off')
plt.show() 

运行结果:

接下来这个例子使用trackbar的方法设置thresh和type,可以方便地观察到不同参数阈值化之后的差异:

import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)track_type = 'type'
track_type2 = 'type2' #treshold的二值化类型由2部分位或得到
track_thresh = 'thresh'
track_type_max = 4  # type类型从0~4
track_type2_max = 16  # 可选8,16,其他参数无意义
track_thresh_max = 255
win_name = 'threshold-juzicode.com'
max_bin_val = 255def threshold_func(v):threshold_type = cv2.getTrackbarPos(track_type,win_name)threshold_type2 = cv2.getTrackbarPos(track_type2,win_name)threshold_val = cv2.getTrackbarPos(track_thresh,win_name)print('threshold_type,threshold_type2,threshold_val',threshold_type,threshold_type2,threshold_val)_ , img_bin = cv2.threshold(img_gray,threshold_val,max_bin_val,threshold_type|threshold_type2)cv2.imshow(win_name,img_bin)img_in = cv2.imread('..\\lena.jpg')
img_gray = cv2.cvtColor(img_in,cv2.COLOR_BGR2GRAY)
cv2.namedWindow(win_name)
cv2.createTrackbar(track_type,win_name,0,track_type_max,threshold_func)
cv2.createTrackbar(track_type2,win_name,0,track_type2_max,threshold_func)
cv2.createTrackbar(track_thresh,win_name,0,track_thresh_max,threshold_func)
cv2.imshow(win_name,img_gray)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:

opencv-python-threshold

type和函数返回值的关系:

从运行结果看,当type设置了cv2.THRESH_OTSU或cv2.THRESH_TRIANGLE标志时,入参thresh没有实际意义,图像并不会跟随thresh发生变化,这是因为该方法会根据图像自动计算阈值,这时threshold()函数返回的第1个值就是自动计算出来的阈值。

import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img_gray = cv2.imread('..\\lena.jpg',cv2.IMREAD_GRAYSCALE)
thresh,img_bin = cv2.threshold(img_gray,127,255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
print('thresh:',thresh)
thresh,img_bin = cv2.threshold(img_gray,10, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
print('thresh:',thresh)
thresh,img_bin = cv2.threshold(img_gray,250,255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
print('thresh:',thresh)==========运行结果:
cv2.__version__: 4.5.2
thresh: 117.0
thresh: 117.0
thresh: 117.0

当type没有设置cv2.THRESH_OTSU或cv2.THRESH_TRIANGLE标志时,threshold()函数的第1个返回值就等于thresh入参:

import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img_gray = cv2.imread('..\\lena.jpg',cv2.IMREAD_GRAYSCALE)
thresh,img_bin = cv2.threshold(img_gray,127,255, cv2.THRESH_BINARY)
print('thresh:',thresh)
thresh,img_bin = cv2.threshold(img_gray,10, 255, cv2.THRESH_BINARY)
print('thresh:',thresh)
thresh,img_bin = cv2.threshold(img_gray,250,255, cv2.THRESH_BINARY)
print('thresh:',thresh)==========运行结果:
cv2.__version__: 4.5.2
thresh: 127.0
thresh: 10.0
thresh: 250.0

2、自适应阈值 adaptiveThreshold()

前面介绍的threshold()在一张图片中使用了一个特定的阈值进行二值化,要么是在入参thresh中指定阈值,要么是在设置了cv2.THRESH_OTSU或cv2.THRESH_TRIANGLE标志时根据图像像素值自动计算阈值,不管哪种方法都是同一张图片使用同一个阈值。

但是在某些情况下一张图片因为光线的差异,可能某一个区域的亮度和其他区域相比差异较大,这时整幅图像使用单一数值阈值化后得到的图片效果可能就会很差。

adaptiveThreshold()的接口形式:

cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) ->dst
  • 参数含义:

  • src:源图像;

  • maxValue:单个像素转换后的最大值;

  • adaptiveMethod:自适应方法:cv2.ADAPTIVE_THRESH_MEAN_C(平均法)或cv2.ADAPTIVE_THRESH_GAUSSIAN_C(高斯法)

  • thresholdType:阈值化类型,THRESH_BINARY或THRESH_BINARY_INV二选一;

  • blockSize:计算某个像素使用的阈值时采用的窗口大小,奇数值;

  • C:平均值或加权平均值减去的常量值;可以为正值,0或负值;

adaptiveMethod参数详解:

  • cv2.ADAPTIVE_THRESH_MEAN_C(平均法):这时阈值等于窗口大小为blockSize的临近像素点的平均值减去C;

  • cv2.ADAPTIVE_THRESH_GAUSSIAN_C(高斯法):阈值等于窗口大小为blockSize的临近像素点高斯窗口互相关加权和减去C。

下面这段代码就是对一张光线不均匀图片进行普通二值化和自适应二值化的例子:

import cv2
print('VX公众号: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)img = cv2.imread('..\\samples\\picture\\leaf.jpeg')
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('img',img)
thresh,img_bin = cv2.threshold(img_gray,10, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
cv2.imshow('threshold',img_bin)
img_ret11 = cv2.adaptiveThreshold(img_gray,  255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,55,0 )
cv2.imshow('adaptiveThreshold',img_ret11)
img_ret12 = cv2.adaptiveThreshold(img_gray,  255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,55,0 )
cv2.imshow('adaptive2',img_ret12)
cv2.waitKey()

运行结果:

原图来源:pexels.com

从运行结果可以看出,最左边原图它的中上部分光线非常暗,中间图片是使用threshold()的大津法做阈值化后的结果,它的中上部分是一大片黑色区域,完全没有体现出树叶的纹路,最后边的图片是使用自适应阈值化后的图片,树叶纹路则能很好的体现出来。

小结:threshold()方法使用大津法和三角法时不需要指定阈值,会自动根据像素值求出阈值,其他方法则需要指定阈值的大小。threshold()方法使用全局单一阈值,而adaptiveThreshold()方法使用局部阈值,所以在处理光线不均匀图片时能取得更好的效果。

推荐阅读:

论如何把自己变成卡通人物

一行代码深度定制你的专属二维码(amzqr)

有了这款神器,什么吃灰文件都统统现形

OpenCV-Python教程:读取图像、显示、写入图像

桔子菌和超市老板田大爷的一次角色互换经历

pyautogui: 有了Python键盘鼠标都可以省着用了

改造getpass,强迫症患者再也不用担心少输字符了

Python logging正在忠实记录你的一举一动

来看看怎么用OpenCV解构Twitter大牛的视觉错觉图

老板,帮忙把这份Python代码打个包

OpenCV-Python教程:阈值化(threshold,adaptiveThreshold)相关推荐

  1. OpenCV自适应阈值化函数adaptiveThreshold详解,并附实例源码

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 2016-6-14日:又发现一种阈值分割法,最大 ...

  2. OpenCV Python教程(3)(4)(5): 直方图的计算与显示 形态学处理 初级滤波内

    OpenCV Python教程(3.直方图的计算与显示) 本篇文章介绍如何用OpenCV Python来计算直方图,并简略介绍用NumPy和Matplotlib计算和绘制直方图 直方图的背景知识.用途 ...

  3. OpenCV Python教程(2、图像元素的访问、通道分离与合并)

    OpenCV Python教程之图像元素的访问.通道分离与合并 转载请详细注明原作者及出处,谢谢! 访问像素 像素的访问和访问numpy中ndarray的方法完全一样,灰度图为: [python] v ...

  4. opencv(python)------二值化阙值(threshold)、自适应阙值(adaptiveThreshold)

    1. 简单阈值 对于每个像素,应用相同的阈值.如果像素值小于阈值,则将其设置为0,否则将其设置为最大值.函数cv.threshold用于应用阈值.第一个参数是源图像,它应该是灰度图像.第二个参数是阈值 ...

  5. opencv python教程简书_OpenCV-Python系列二:常用的图像属性

    对于图像,我们经常需要知道关于图像的特殊属性,比如宽度,高度,面积,像素点数目等等,那么在opencv-python中,这些信息如何获取呢? 本文结构: 1.基本图像属性 2. 对于opencv中的特 ...

  6. opencv python教程-OpenCV4 Python 最新中文版官方教程来了(附下载)

    教程简介 OpenCV 是计算机视觉中经典的专用库,然而其中文版官方教程久久不来.近日,一款最新 OpenCV4.1 版本的完整中文版官方教程出炉,读者朋友可以更好的学习了解 OpenCV 相关细节. ...

  7. opencv python教程简书_OpenCV-Python教程:28.模板匹配

    理论 模板匹配是在一个大图里搜索和找模板图像位置的方法.OpenCV有个函数cv2.matchTemplate()来做这个.它吧模板图像在输入图像上滑动,对比模板和在模板图像下的输入图像块.它返回了一 ...

  8. OpenCV Python教程(1、图像的载入、显示和保存)

    本文是OpenCV  2 Computer Vision Application Programming Cookbook读书笔记的第一篇.在笔记中将以Python语言改写每章的代码. PythonO ...

  9. opencv python教程简书_Python-OpenCV —— 基本操作一网打尽

    OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows.MacOS操作系统上.它轻量级而且高效--由一系列 C 函数和少量C++类构成,同时提供了Pyt ...

  10. OpenCV Python教程系列

    参考: OpenCV - sunny2038的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/sunny2038/article/category/904451

最新文章

  1. 想要学习Python爬虫的你,真的了解爬虫最基础的知识储备吗?
  2. postgresql GUC 参数
  3. 命名分组(?name....)
  4. hdu4685 最大匹配可能性
  5. 如何解析字符串类型的xml
  6. el table怎么获取最后一行_elementUi表格插入额外一行怎么操作
  7. Ideal Farm 构造(2400)
  8. 协同过滤算法_机器学习 | 简介推荐场景中的协同过滤算法,以及SVD的使用
  9. Java Vector insertElementAt()方法与示例
  10. 加加减减的奥秘——从数学到魔术的思考(三)
  11. C#中缓存的简单方法及使用Sql设置缓存依赖项
  12. mysql 子查询空_mysql的子查询
  13. 【洛谷 SP8093】 JZPGYZ - Sevenk Love Oimaster(后缀自动机)
  14. Hp-socket高性能网络库三--tcp组件pack接收模型
  15. Aho_Corasick_Automaton
  16. 合天网安 Weekly CTF 刷题合集
  17. K-divisible Sum
  18. 大学这么多比赛,我该参加哪个?
  19. 中国与印度软件工程师的比较
  20. html5 3d场景设计,基于 HTML5 WebGL 的加油站 3D 可视化监控

热门文章

  1. 计算方法(三)分段线性插值和Hermite插值
  2. Node.js 整合 Express 框架实现微信支付和支付宝支付
  3. vue 上传图片进行压缩图片
  4. allegro怎么导出PCB文件里封装
  5. mysql中如何复制数据表_MySQL中快速复制数据表方法汇总
  6. notepad 自动排版html,notepad++怎么自动排版
  7. css之box-sizing用法
  8. 输入大写字母,将大写字母转换为小写字母
  9. html转换成ppt转换器,ppt转换成word|幻灯片转换成word ppt转视频轻松解决
  10. 【R语言】结巴分词与词性提取(以“提取知乎问题标题的频繁词前100个形容词”实战为例)(3月25日学习笔记)