博客
关于我
OpenCV threshold函数详解
阅读量:291 次
发布时间:2019-03-01

本文共 11735 字,大约阅读时间需要 39 分钟。

threshold函数作用:

去掉噪,例如过滤很小或很大像素值的图像点。

threshold函数python版原型:

retval, dst = cv.threshold( src, thresh, maxval, type[, dst] )

参数说明:

src:原图像。

dst:结果图像。
thresh:当前阈值。
maxVal:最大阈值,一般为255.

thresholdType:阈值类型,主要有下面几种:

enum ThresholdTypes {    THRESH_BINARY     = 0,    THRESH_BINARY_INV = 1,    THRESH_TRUNC      = 2,    THRESH_TOZERO     = 3,    THRESH_TOZERO_INV = 4,    THRESH_MASK       = 7,    THRESH_OTSU       = 8,    THRESH_TRIANGLE   = 16};

返回值:
 retval: 与参数thresh一致
dst: 结果图像

编号 阈值类型枚举
注意
1 THRESH_BINARY
2 THRESH_BINARY_INV
3 THRESH_TRUNC
4 THRESH_TOZERO
5 THRESH_TOZERO_INV
6 THRESH_MASK
不支持
7 THRESH_OTSU
不支持32位
8 THRESH_TRIANGLE
不支持32位

具体说明如下:

注意:

THRESH_OTSU和THRESH_TRIANGLE是作为优化算法配合THRESH_BINARY、THRESH_BINARY_INV、THRESH_TRUNC、THRESH_TOZERO以及THRESH_TOZERO_INV来使用的。

当使用了THRESH_OTSU和THRESH_TRIANGLE两个标志时,输入图像必须为单通道

生成关系:

下面通过代码来验证一下threshold的用法:

import numpy as npimport cv2#创建一个6x6的BGR三通道图片img6x6 = np.zeros((6,6,3), dtype=np.uint8) #Blue通道取值0~99随机值img6x6[:,:,0] = np.random.randint(0, 100, size=36).reshape(6,6)#Green通道取值100~199随机值img6x6[:,:,1] = np.random.randint(100, 200, size=36).reshape(6,6)#Red通道取值200~255随机值img6x6[:,:,2] = np.random.randint(200, 256, size=36).reshape(6,6)print(img6x6)

得到img6x6的BGR三通道数据:

[[[ 62 171 226]  [ 29 118 212]  [ 61 151 200]  [ 43 123 206]  [ 58 146 232]  [  2 124 246]] [[ 48 101 207]  [ 32 194 228]  [ 90 171 241]  [ 36 152 244]  [ 64 169 245]  [ 71 106 202]] [[ 27 198 206]  [ 39 193 213]  [ 60 128 207]  [ 53 134 248]  [ 25 187 229]  [ 72 116 229]] [[ 52 163 201]  [ 39 189 251]  [ 63 190 217]  [ 73 139 212]  [ 54 166 236]  [ 43 191 200]] [[ 34 119 207]  [ 36 110 209]  [ 40 191 229]  [ 60 100 228]  [ 62 174 250]  [ 41 115 209]] [[ 35 165 246]  [ 50 182 218]  [ 77 110 239]  [ 44 106 245]  [ 21 189 252]  [ 64 144 241]]]

观察结果我们发现img6x6[2][2][1]=128,我们取该值作为thresh值来演示THRESH_BINARY、THRESH_BINARY_INV等的作用。

1) THRESH_BINARY

我们取参数值thresh=128,maxval=255,flag = THRESH_BINARY

cv2.threshold(img6x6, 128, 255, cv2.THRESH_BINARY)

根据前面对THRESH_BINARY flag值的解释:

预期得到的结果中,img6x6中>128的值均应变为255,<=128的值均应变为0。

我们实际得到的结果为:

[[[  0 255 255]  [  0   0 255]  [  0 255 255]  [  0   0 255]  [  0 255 255]  [  0   0 255]] [[  0   0 255]  [  0 255 255]  [  0 255 255]  [  0 255 255]  [  0 255 255]  [  0   0 255]] [[  0 255 255]  [  0 255 255]  [  0   0 255]  [  0 255 255]  [  0 255 255]  [  0   0 255]] [[  0 255 255]  [  0 255 255]  [  0 255 255]  [  0 255 255]  [  0 255 255]  [  0 255 255]] [[  0   0 255]  [  0   0 255]  [  0 255 255]  [  0   0 255]  [  0 255 255]  [  0   0 255]] [[  0 255 255]  [  0 255 255]  [  0   0 255]  [  0   0 255]  [  0 255 255]  [  0 255 255]]]

与预期的结果一致。

2)THRESH_BINARY_INV

THRESH_BINARY_INV的作用与THRESH_BINARY相反,大于thresh的值置0,小于等于thresh的值置maxval:

预期的结果与1)的结果完全相反。

code:

ret,dst=cv2.threshold(img6x6, 128, 255, cv2.THRESH_BINARY_INV)print(dst)
dst输出:
[[[255   0   0]  [255 255   0]  [255   0   0]  [255 255   0]  [255   0   0]  [255 255   0]] [[255 255   0]  [255   0   0]  [255   0   0]  [255   0   0]  [255   0   0]  [255 255   0]] [[255   0   0]  [255   0   0]  [255 255   0]  [255   0   0]  [255   0   0]  [255 255   0]] [[255   0   0]  [255   0   0]  [255   0   0]  [255   0   0]  [255   0   0]  [255   0   0]] [[255 255   0]  [255 255   0]  [255   0   0]  [255 255   0]  [255   0   0]  [255 255   0]] [[255   0   0]  [255   0   0]  [255 255   0]  [255 255   0]  [255   0   0]  [255   0   0]]]

与预期结果完全一致。

3)THRESH_TRUNC

THRESH_TRUNC的作用是对大于thresh的值进行截断,其余值保留原值。

code:

ret,dst=cv2.threshold(img6x6, 128, 255, cv2.THRESH_TRUNC)print(dst)

dst输出:

[[[ 62 128 128]  [ 29 118 128]  [ 61 128 128]  [ 43 123 128]  [ 58 128 128]  [  2 124 128]] [[ 48 101 128]  [ 32 128 128]  [ 90 128 128]  [ 36 128 128]  [ 64 128 128]  [ 71 106 128]] [[ 27 128 128]  [ 39 128 128]  [ 60 128 128]  [ 53 128 128]  [ 25 128 128]  [ 72 116 128]] [[ 52 128 128]  [ 39 128 128]  [ 63 128 128]  [ 73 128 128]  [ 54 128 128]  [ 43 128 128]] [[ 34 119 128]  [ 36 110 128]  [ 40 128 128]  [ 60 100 128]  [ 62 128 128]  [ 41 115 128]] [[ 35 128 128]  [ 50 128 128]  [ 77 110 128]  [ 44 106 128]  [ 21 128 128]  [ 64 128 128]]]

4) THRESH_TOZERO

THRESH_TOZERO的作用是对大于thresh的值进行保留原值,小于或等于thresh的值置0:

code:

ret, dst=cv2.threshold(img6x6, 128, 255, cv2.THRESH_TOZERO)print(dst)

dst输出:

[[[  0 171 226]  [  0   0 212]  [  0 151 200]  [  0   0 206]  [  0 146 232]  [  0   0 246]] [[  0   0 207]  [  0 194 228]  [  0 171 241]  [  0 152 244]  [  0 169 245]  [  0   0 202]] [[  0 198 206]  [  0 193 213]  [  0   0 207]  [  0 134 248]  [  0 187 229]  [  0   0 229]] [[  0 163 201]  [  0 189 251]  [  0 190 217]  [  0 139 212]  [  0 166 236]  [  0 191 200]] [[  0   0 207]  [  0   0 209]  [  0 191 229]  [  0   0 228]  [  0 174 250]  [  0   0 209]] [[  0 165 246]  [  0 182 218]  [  0   0 239]  [  0   0 245]  [  0 189 252]  [  0 144 241]]]

5) THRESH_TOZERO_INV

THRESH_TOZERO_INV的作用与THRESH_TOZERO的作用完全相反,对大于thresh的值置0,其余值则保留:

code:

ret, dst=cv2.threshold(img6x6, 131, 255, cv2.THRESH_TOZERO_INV)print(dst)

dst输出:

[[[ 62   0   0]  [ 29 118   0]  [ 61   0   0]  [ 43 123   0]  [ 58   0   0]  [  2 124   0]] [[ 48 101   0]  [ 32   0   0]  [ 90   0   0]  [ 36   0   0]  [ 64   0   0]  [ 71 106   0]] [[ 27   0   0]  [ 39   0   0]  [ 60 128   0]  [ 53   0   0]  [ 25   0   0]  [ 72 116   0]] [[ 52   0   0]  [ 39   0   0]  [ 63   0   0]  [ 73   0   0]  [ 54   0   0]  [ 43   0   0]] [[ 34 119   0]  [ 36 110   0]  [ 40   0   0]  [ 60 100   0]  [ 62   0   0]  [ 41 115   0]] [[ 35   0   0]  [ 50   0   0]  [ 77 110   0]  [ 44 106   0]  [ 21   0   0]  [ 64   0   0]]]

6)THRESH_OTSU

THRESH_OTSU是需要搭配THRESH_BINARY、THRESH_BINARY_INV、THRESH_TRUNC、THRESH_TOZERO以及THRESH_TOZERO_INV来使用的。并且输入图像必须是灰度图像。

所以,我们首先需要创建一个灰度图像:

code:

img_gray = cv2.cvtColor(img6x6,cv2.COLOR_BGR2GRAY)print(img_gray)

得到的img_gray为:

[[175   0   0   0 162   0] [  0 186 183 166 180   0] [181 181   0 159 181   0] [162 190 184   0 174 177] [  0   0 185   0 184   0] [174 178   0   0 189 164]]

然后在通过THRESH_OTSU标准搭配其他标志位来对输入图像做处理,这里只演示搭配THRESH_BINARY标志的用法,

code:

ret,dst=cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO|cv2.THRESH_OTSU)print(dst)

dst输出:

[[175   0   0   0 162   0] [  0 186 183 166 180   0] [181 181   0 159 181   0] [162 190 184   0 174 177] [  0   0 185   0 184   0] [174 178   0   0 189 164]]

对比一下不使用THRESH_OTSU时的输出,

code:

ret,dst=cv2.threshold(img_gray, 166, 255, cv2.THRESH_TOZERO)print(dst)

dst输出:

[[175   0   0   0   0   0] [  0 186 183   0 180   0] [181 181   0   0 181   0] [  0 190 184   0 174 177] [  0   0 185   0 184   0] [174 178   0   0 189   0]]

7) THRESH_TRIANGLE

THRESH_TRIANGLE用法与THRESH_OTSU用法一致,这里不做演示。

综合示例

Demo Code

#encoding=utf-8import sys, cv2, numpy as npfrom ui_thresholdDemo import Ui_ThresoldDemofrom PyQt5.QtWidgets import QApplication, QWidget, QFileDialogfrom PyQt5.QtGui import QImage, QPixmapclass ThresholdDemo(QWidget, Ui_ThresoldDemo):        def __init__(self):        super().__init__()        self.setupUi(self)        self.setupSigSlots()        self.param_threshold = 1        self.param_maxVal    = 255        self.param_thresholdType = cv2.THRESH_BINARY        self.param_ExtendType = 0        self.checkGray = False            def setupSigSlots(self):        self.btnBrowse.clicked.connect(self.slotBtnBrowse)        self.parmThreshold.valueChanged.connect(self.slotThresholdChanged)        self.paramMaxVal.valueChanged.connect(self.slotMaxValChanged)        self.parmThresholdType.currentTextChanged[str].connect(self.slotThresholdTypeChanged)        self.btnCheckGray.toggled.connect(self.slotCheckGray)        self.parmThresholdType2.currentTextChanged[str].connect(self.slotThresholdType2Changed)        def slotBtnBrowse(self):        try:            file, _ = QFileDialog.getOpenFileName(self, 'Open Image', 'D:\\tmp\\pics', '*.*', '*.*',)            if file:                self.imagePath.setText(file)                img_init = cv2.imdecode(np.fromfile(file, dtype=np.uint8), -1)                self.img_threshold = img_init.copy()                cv2.cvtColor(img_init, cv2.COLOR_BGR2RGB, img_init)                h,w,c = img_init.shape                qImg = QImage(img_init, w, h, w*c, QImage.Format_RGB888)                self.initPicFrame.setPixmap(QPixmap.fromImage(qImg))                self.updateThresholdImage()        except Exception as e:            print(e)                def updateThresholdImage(self):        try:            img = self.img_threshold.copy()            if self.checkGray:                img_gray = np.zeros((img.shape[0], img.shape[1]), dtype=np.uint8)                cv2.cvtColor(img, cv2.COLOR_BGR2GRAY, img_gray)                ret, img_threshold = cv2.threshold(img_gray, self.param_threshold, self.param_maxVal, self.param_thresholdType|self.param_ExtendType)                print('thresh:{}, maxval:{}, flags:{}|{}'.format(self.param_threshold, self.param_maxVal, self.param_thresholdType, self.param_ExtendType))                h,w = img_threshold.shape                qImg = QImage(img_threshold, w, h, w, QImage.Format_Indexed8)                self.thresholdPicFrame.setPixmap(QPixmap.fromImage(qImg))            else:                ret, img_threshold = cv2.threshold(img, self.param_threshold, self.param_maxVal, self.param_thresholdType)                #ret: ret equals to self.param_threshold, it canbe ignored                h,w,c = img_threshold.shape                cv2.cvtColor(img_threshold, cv2.COLOR_BGR2RGB, img_threshold)                qImg = QImage(img_threshold, w, h, w*c, QImage.Format_RGB888)                self.thresholdPicFrame.setPixmap(QPixmap.fromImage(qImg))        except Exception as e:            print(e)        def slotThresholdChanged(self, val):        self.param_threshold = val        self.labelThreshold.setText('threshold:{:>3}'.format(val))        self.updateThresholdImage()        def slotMaxValChanged(self, val):        self.param_maxVal    = val        self.labelMaxVal.setText(' maxValue:{:>3}'.format(val))        self.updateThresholdImage()        def slotThresholdTypeChanged(self, type):        type_dic = {            'THRESH_BINARY': cv2.THRESH_BINARY,            'THRESH_BINARY_INV': cv2.THRESH_BINARY_INV,            'THRESH_TRUNC': cv2.THRESH_TRUNC,            'THRESH_TOZERO': cv2.THRESH_TOZERO,            'THRESH_TOZERO_INV': cv2.THRESH_TOZERO_INV,            #'THRESH_MASK': cv2.THRESH_MASK,            #'THRESH_OTSU': cv2.THRESH_OTSU,            #'THRESH_TRIANGLE': cv2.THRESH_TRIANGLE,            }        self.param_thresholdType = type_dic[type]        #print(type,self.param_thresholdType )        self.updateThresholdImage()            def slotThresholdType2Changed(self, type):        try:            extend_type = {                "THRESH_OTSU":cv2.THRESH_OTSU,                "THRESH_TRIANGLE":cv2.THRESH_TRIANGLE                }            if type == 'NONE':                self.param_ExtendType = 0                self.checkGray = False                self.btnCheckGray.setEnabled(True)            else:                self.param_ExtendType = extend_type[type]                self.checkGray = True                self.btnCheckGray.setEnabled(False)                            print('self.param_ExtendType: ', self.param_ExtendType)            self.updateThresholdImage()        except Exception as e:            print(e)                def slotCheckGray(self, bGray):        self.checkGray = bGray        self.updateThresholdImage()def thresholdDemo():    img6x6 = np.zeros((6,6,3), dtype=np.uint8)    img6x6[:,:,0] = np.random.randint(0, 100, size=36).reshape(6,6)    img6x6[:,:,1] = np.random.randint(100, 200, size=36).reshape(6,6)    img6x6[:,:,2] = np.random.randint(200, 256, size=36).reshape(6,6)    cv2.threshold(img6x6, 127, 255, cv2.THRESH_BINARY)if __name__ == '__main__':    qApp = QApplication(sys.argv)    demo = ThresholdDemo()    demo.show()    qApp.exec_()

程序运行结果:

完整Code下载,请点

你可能感兴趣的文章
mysql-connector-java各种版本下载地址
查看>>
mysql-EXPLAIN
查看>>
MySQL-Explain的详解
查看>>
mysql-group_concat
查看>>
MySQL-redo日志
查看>>
MySQL-【1】配置
查看>>
MySQL-【4】基本操作
查看>>
Mysql-丢失更新
查看>>
Mysql-事务阻塞
查看>>
Mysql-存储引擎
查看>>
mysql-开启慢查询&所有操作记录日志
查看>>
MySQL-数据目录
查看>>
MySQL-数据页的结构
查看>>
MySQL-架构篇
查看>>
MySQL-索引的分类(聚簇索引、二级索引、联合索引)
查看>>
Mysql-触发器及创建触发器失败原因
查看>>
MySQL-连接
查看>>
mysql-递归查询(二)
查看>>
MySQL5.1安装
查看>>
mysql5.5和5.6版本间的坑
查看>>