在讲阈值操作方法之前,肯定是先讲下阈值分割的作用
阈值分割其实就是图像分离,对于阈值内的你想如何操作,一个最简单的例子就是二值图像。
接下来我们看下方法吧:
threshold —— 简单的阈值操作
adaptiveThreshold —— 自适应阈值操作
threshold参数说明:
def threshold(src, thresh, maxval, type, dst=None)
thresh:Double类型的,具体的阈值。
maxval:Double类型的,阈值的最大值
type:
THRESH_BINARY 二进制阈值化 -> 大于阈值为1 小于阈值为0
THRESH_BINARY_INV 反二进制阈值化 -> 大于阈值为0 小于阈值为1
THRESH_TRUNC 截断阈值化 -> 大于阈值为阈值,小于阈值不变
THRESH_TOZERO 阈值化为0 -> 大于阈值的不变,小于阈值的全为0
THRESH_TOZERO_INV 反阈值化为0 -> 大于阈值为0,小于阈值不变
在本实验中,我还是采用了使用进度条来调节当前阈值的操作,最大阈值设定为255,得到的实验结果如下:
当阈值为0的时候 看下图像,可以对比上面的总结,窗口名称我用type较少Thresh来命名
当阈值为130的时候,看图像如下所示:
当阈值为255时候的图像:
一些极端的数值我在这里测试过了,大家可以根据图像和上面的定义做个对比来得出自己的结论,我在这里就不做总结了。 代码如下:
1 import cv2
2
3 img = cv2.imread("C:/Users/DELL/Desktop/img2.jpg")
4
5 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
6
7 gauss = cv2.GaussianBlur(gray, (3, 3), 1)
8
9 maxvalue = 255
10
11 def onthreshold(x):
12 value = cv2.getTrackbarPos("value", "Threshold")
13 a, binary = cv2.threshold(gauss, value, maxvalue, cv2.THRESH_BINARY)
14 b, binary_inv = cv2.threshold(gauss, value, maxvalue, cv2.THRESH_BINARY_INV)
15 c, trunc = cv2.threshold(gauss, value, maxvalue, cv2.THRESH_TRUNC)
16 d, to_zero = cv2.threshold(gauss, value, maxvalue, cv2.THRESH_TOZERO)
17 e, to_zero_inv = cv2.threshold(gauss, value, maxvalue, cv2.THRESH_TOZERO_INV)
18 if(a):
19 cv2.imshow("Binary", binary)
20 if(b):
21 cv2.imshow("Binary_INV", binary_inv)
22 if(c):
23 cv2.imshow("TRUNC", trunc)
24 if(d):
25 cv2.imshow("TO_ZERO", to_zero)
26 if(e):
27 cv2.imshow("TO_ZERO_INV", to_zero_inv)
28
29
30 cv2.namedWindow("Threshold")
31
32 cv2.createTrackbar("value", "Threshold", 0, 255, onthreshold)
33
34 cv2.imshow("Threshold", img)
35
36 cv2.waitKey(0)
在这个方法里我要讲下,你会发现方法前面有两个参数,原因是当你进入Pycharm的方法声明中,里面是这样给你实列的:
threshold(src, thresh, maxval, type[, dst]) -> retval, dst
第一个retval是你的方法是否执行成功,dst是目标图像,上面懒得起名字,所以用a,b,c,d,e来代表的对应方法的Bool值。
接下来讲下adaptiveThreshold的参数:
def adaptiveThreshold(src,maxValue,adaptiveMethod,thresholdType,blockSize,C,dst=None)
maxval:Double类型的,阈值的最大值
adaptiveMethod:Int类型的,这里有两种选择
1 —— ADAPTIVE_THRESH_MEAN_C(通过平均的方法取得平均值)
2 —— ADAPTIVE_THRESH_GAUSSIAN_C(通过高斯取得高斯值)
不过这两种方法最后得到的结果要减掉参数里面的C值
thresholdType:Int类型的,方法如下:
THRESH_BINARY 二进制阈值化 -> 大于阈值为1 小于阈值为0
THRESH_BINARY_INV 反二进制阈值化 -> 大于阈值为0 小于阈值为1
THRESH_TRUNC 截断阈值化 -> 大于阈值为阈值,小于阈值不变
THRESH_TOZERO 阈值化为0 -> 大于阈值的不变,小于阈值的全为0
THRESH_TOZERO_INV 反阈值化为0 -> 大于阈值为0,小于阈值不变
blockSize:Int类型的,这个值来决定像素的邻域块有多大。
注意:这里的blockSize的值要为奇数,否则会给出这样的提示:
Assertion failed (blockSize % 2 == 1 && blockSize > 1) in cv::adaptiveThreshold
C:偏移值调整量,计算adaptiveMethod用到的参数。
实验中,我阈值的type选择第一种,来演示这两种方式得出的结果
当blockSize的值比较小的时候,两种方法得到的结果的差异不是很大
当blockSize的值比较大的时候,就会发现,平均的这种会将整体的轮廓加深的程度大于高斯
直接看图:
我图片上虽然显示的blockSize为10,不过我在程序里面做了判断,当为偶数的情况,就让它+1变成奇数。
代码如下:
1 import cv2
2
3 img = cv2.imread("C:/Users/DELL/Desktop/img2.jpg")
4
5 gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
6
7 gauss = cv2.GaussianBlur(gray, (3, 3), 1)
8
9 maxvalue = 255
10
11 def onaptivethreshold(x):
12 value = cv2.getTrackbarPos("value", "Threshold")
13 if(value < 3):
14 value = 3
15 if(value % 2 == 0):
16 value = value + 1
17 args = cv2.adaptiveThreshold(gauss, maxvalue, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, value, 1)
18 gaus = cv2.adaptiveThreshold(gauss, maxvalue, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, value, 1)
19 cv2.imshow("Args", args)
20 cv2.imshow("Gaus", gaus)
21
22 cv2.namedWindow("Threshold")
23
24 cv2.createTrackbar("value", "Threshold", 0, 10, onaptivethreshold)
25
26 cv2.imshow("Threshold", img)
27
28 cv2.waitKey(0)