刚接触opencv,需要用到图像二值化,发现opencv提供的二值化算法有很多,网上借鉴了很多大神的帖子,自己做了一些总结归纳,作为笔记先记录一下。
opencv二值化相关函数有两个,先记录一下threshold的使用,另一个为adaptiveThreshold,会在下个帖子做记录
研究了一下参数,
src:需要进行二值化的一张灰度图像
thresh:手动指定的灰度值(0~255)(用来比较的阈值)
maxval:另一个需要手动指定的灰度值(0~255)(将要设置的灰度值)
type:opencv提供的二值化方法
dst:输出图像,可以忽略
返回值有两个,第一个是opencv实际在做二值化处理时的用的灰度值,第二个是二值化后的图像
在使用这个函数的时候,
需要一张灰度图,这个很简单,直接下面这段代码就能得到灰度图
image_path = './img/1.jpg'
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
指定一个阈值,将灰度图的像素点分成两类,灰度大于阈值的像素点集合和小于阈值的像素点集合
一般简单粗暴直接传个中间值127进去,但毕竟是写死的数值,通用性较差,因此也可以使用图像的平均灰度值,好处是能根据不同图像动态变换。具体图像的平均灰度值计算方法如下
import numpy as np
h, w = gray.shape[:2] # gray 为灰度图
m = np.reshape(gray, [1, w*h])
mean = m.sum()/(w*h) # 图像平均灰度值
thresh = mean
一般情况下可以认为把大于阈值的像素点的灰度值设置成maxval,一般用255,即大于阈值的像素点值一律变成255(白色)
opencv提供以下参数
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
看了其他帖子的介绍,THRESH_MASK好像不支持使用,因此可以忽略。剩下的参数可以分为两类
THRESH_BINARY = 0,
THRESH_BINARY_INV = 1,
THRESH_TRUNC = 2,
THRESH_TOZERO = 3,
THRESH_TOZERO_INV = 4,
THRESH_OTSU = 8,
THRESH_TRIANGLE = 16
前五个为一类参数,用来指定二值化的方式,总结出来如下
THRESH_BINARY:大于阈值thresh的像素点灰度值设为maxval, 小于阈值的像素点灰度值设为0
THRESH_BINARY_INV:THRESH_BINARY的反转,即大于阈值的像素点灰度值设为0, 小于阈值的像素点灰度值设为maxval
THRESH_TRUNC 大于阈值的像素点灰度值设为阈值thresh,其他像素点不变, maxval参数不生效
THRESH_TOZERO 大于阈值的像素点不变,小于阈值的像素点灰度值设为0, maxval参数不生效
THRESH_TOZERO_INV 大于阈值的像素点灰度值设为0,其他像素点不变, maxval参数不生效
大部分场合,会用到前面两种类型,而后三种类型函数的第三个参数maxval将不会生效。
看一下效果,作为演示,阈值都指定为127
thresh, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_XXXX)
cv2.imshow(f'thresh={int(thresh)}, type=THRESH_XXXX', binary)
再来说最后两个参数THRESH_OTSU和THRESH_TRIANGLE ,前面的代码的阈值,不管是127还是动态计算平均灰度值,都需要人为指定,而使用THRESH_OTSU或THRESH_TRIANGLE后,就不需要人为指定阈值了。
THRESH_OTSU或THRESH_TRIANGLE不是二值化方式,更像是计算图像阈值的算法,因此需要结合前五个参数一起使用,具体使用方式比如 type= cv2.THRESH_BINARY | cv2.THRESH_OTSU
#第二个参数不生效,因此传个0
thresh, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
cv2.imshow(f'thresh={int(thresh)}, type=THRESH_BINARY | cv2.THRESH_OTSU', binary)
thresh, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE)
cv2.imshow(f'thresh={int(thresh)}, type=THRESH_BINARY | cv2.THRESH_TRIANGLE', binary)
可以看到,即便阈值设置为0,两个算法分别算出了用于计算的阈值,分别是153和250
以上为cv2.threshold使用时的个人总结,之后继续分享另一种二值化方式cv2.adaptiveThreshold
import cv2
import numpy as np
def cal_average_gray_value(gray):
h, w = gray.shape[:2]
m = np.reshape(gray, [1, w*h])
mean = m.sum()/(w*h)
return mean
if __name__ == "__main__":
image_path = './img/1.jpg'
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresholdTypes = [cv2.THRESH_BINARY, cv2.THRESH_BINARY_INV, cv2.THRESH_TRUNC,
cv2.THRESH_TOZERO, cv2.THRESH_TOZERO_INV, cv2.THRESH_OTSU, cv2.THRESH_TRIANGLE]
for thresholdType in thresholdTypes:
thresh, binary = cv2.threshold(gray, 127, 255, thresholdType)
cv2.imshow(
f'thresh={int(thresh)}, thresholdType={thresholdType}', binary)
cv2.waitKey(0)