OpenCV---图像二值化

一:什么是二值图像

彩色图像:三个通道0-2550-2550-255,所以可以有2^24位空间

灰度图像:一个通道0-255,所以有256种颜色

二值图像:只有两种颜色,黑和白,1白色,0黑色

二:图像二值化

(一)先获取阈值

(二)根据阈值去二值化图像

(三)OpenCV中的二值化方法

(四)补充阈值类型

原灰度图像的像素值

1.THRESH_BINARY:过门限的值为最大值,其他值为0

2.THRESH_BINARY_INV:过门限的值为0,其他值为最大值

3.THRESH_TRUNC:过门限的值为门限值,其他值不变

 

4.THRESH_TOZERO:过门限的值不变,其他设置为0

5.THRESH_TOZERO_INV:过门限的值为0,其他不变

三:代码实现全局阈值

(一)全局阈值使用THRESH_OTSU大津法

def threshold_demo(image):
    gray = cv.cvtColor(image,cv.COLOR_RGB2GRAY)   #要二值化图像,要先进行灰度化处理
    ret, binary = cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)
    print("threshold value: %s"%ret)  #打印阈值,前面先进行了灰度处理0-255,我们使用该阈值进行处理,低于该阈值的图像部分全为黑,高于该阈值则为白色
    cv.imshow("binary",binary)  #显示二值化图像 

threshold value: 140.0  #获取的阈值是140

(二)全局阈值使用THRESH_TRIANGLE(三角形算法)

ret, binary = cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_TRIANGLE)

threshold value: 67.0

(三)上面使用大津法和三角形算法都是自动去获取阈值,下面我们自己直接指定阈值

(1)THRESH_BINARY_INV大于阈值的都为0

ret, binary = cv.threshold(gray,127,255,cv.THRESH_BINARY_INV)

threshold value: 127.0

 (2)THRESH_TRUNC截断大于127的值都为127

ret, binary = cv.threshold(gray,127,255,cv.THRESH_TRUNC)

(3)THRESH_TOZERO小于阈值的都为0和(1)相反

ret, binary = cv.threshold(gray,127,255,cv.THRESH_TOZERO)

相关知识补充

(1)threshold方法

①OpenC的threshold函数进行全局阈值。其函数原型为:threshold(src, thresh, maxval, type[, dst]) -> retval, dst
src参数表示输入图像(多通道,8位或32位浮点)。
thresh参数表示阈值。
maxval参数表示与THRESH_BINARY和THRESH_BINARY_INV阈值类型一起使用设置的最大值。
type参数表示阈值类型。
retval参数表示返回的阈值。若是全局固定阈值算法,则返回thresh参数值。若是全局自适应阈值算法,则返回自适应计算得出的合适阈值。
dst参数表示输出与src相同大小和类型以及相同通道数的图像。
②type参数阈值类型这部分参考博客:https://blog.csdn.net/iracer/article/details/49232703  ,写的很不错。

 (2)cv.THRESH_OTSU类型

推文:OTSU算法

cv2.threshold函数是有两个返回值的,

第一个返回值,得到图像的阈值,
第二个返回值,也就是阈值处理后的图像,
cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU)  #这是我们自己设置的
我们自己不一定能够找到一个最好的阈值,去二分化图像,所以我们需要算法自己去寻找一个阈值,而cv.THRESH_OTSU就可以满足这个需求,去找到一个最好的阈值。

注意:他非常适用于图像灰度直方图具有双峰的情况,他会在双峰之间找到一个值作为阈值,对于非双峰图像,可能并不是很好用。
因为cv.THRESH_OTSU方法会产生一个阈值,那么函数cv2.threshold的的第二个参数(设置阈值)就是0(None)了,并且在cv2.threshold的方法参数中还得加上语句cv2.THRESH_OTSU。
这里面第三个参数maxval参数表示与THRESH_BINARY和THRESH_BINARY_INV阈值类型一起使用设置的最大值。
而我们使用的灰度图像最大则为255,所以设置为255即可

(3)cv.THRESH_TRIANGLE类型(有丢失)适用于单个波峰

推文:图像处理之三角法图像二值化

THRESH_OTSU    flag, use Otsu algorithm to choose the optimal threshold value
THRESH_TRIANGLE    flag, use Triangle algorithm to choose the optimal threshold value
    ret, binary = cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_TRIANGLE)

(4)cv.THRESH_OTSU类型和cv.THRESH_TRIANGLE类型

THRESH_OTSU和THRESH_TRIANGLE和前面的说到的二值化方法组合使用,好处是不用自己指定thresh值,系统会进行计算并且作为返回值返回。
区别是:
THRESH_OTSU最适用于双波峰
THRESH_TRIANGLE最适用于单个波峰,最开始用于医学分割细胞等

四:代码实现局部阈值(更加清晰)

(一)ADAPTIVE_THRESH_MEAN_C

def local_threshold(image):
    gray = cv.cvtColor(image,cv.COLOR_RGB2GRAY)   #要二值化图像,要先进行灰度化处理
    dst = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,25,10)
    cv.imshow("local_threshold", dst)

 (二)ADAPTIVE_THRESH_GAUSSIAN_C轮廓更加清晰

dst = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,25,10)

相关知识补充

(1)adaptiveThreshold方法

def adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None): # real signature unknown; restored from __doc__
OpenCV的adaptiveThreshold函数进行局部阈值。函数原型为:adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) -> 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,57........ )。

C参数是常数,表示从平均值或加权平均值中减去的数。 通常情况下,这是正值,但也可能为零或负值。
在使用平均和高斯两种算法情况下,通过计算每个像素周围blockSize x blockSize大小像素块的加权均值并减去常量C即可得到自适应阈值。
如果使用平均的方法,则所有像素周围的权值相同;
如果使用高斯的方法,则每个像素周围像素的权值则根据其到中心点的距离通过高斯方程得到。

五:全局和局部的比较

 六:自己计算阈值

def custom_threshold(image):
    gray = cv.cvtColor(image,cv.COLOR_RGB2GRAY)   #要二值化图像,要先进行灰度化处理
    h,w=gray.shape[:2]  #求宽高
    m = np.reshape(gray,[1,w*h])  #将图像转一维数组,一行,w*h列,转换维度要保证其size不变
    mean = m.sum() / (w*h)  #求平均值来当做阈值,来分割图像
    print("mean :",mean)
    ret,binary = cv.threshold(gray,mean,255,cv.THRESH_BINARY)
    cv.imshow("binary",binary) 

 

相关知识补充:

(1)reshape方法

def reshape(a, newshape, order='C'):
numpy的reshape函数是给数组一个新的形状而不改变其数据,函数原型:reshape(a, newshape, order='C')

a参数表示需要重新形成的原始数组。

newshape参数表示int或int类型元组(tuple),若为(1, 3),表示生成的新数组是1行3列。

order参数表表示使用此索引顺序读取a的元素,并使用此索引顺序将元素放置到重新形成的数组中。

函数返回值:如果可能的话,这将是一个新的视图对象; 否则,它会成为副本。
注意:将图像转一维数组,转换维度要保证其size不变,newshape==》[行,列]一行n列,要保证其容量大小不变

 

posted @ 2018-07-06 11:44  山上有风景  阅读(56439)  评论(0编辑  收藏  举报