刚接触opencv,需要用到图像二值化,发现opencv提供的二值化算法有很多,网上借鉴了很多大神的帖子,自己做了一些总结归纳,作为笔记先记录一下。

opencv二值化相关函数有两个,先记录一下threshold的使用,另一个为adaptiveThreshold,会在下个帖子做记录

cv2.threshold(src, thresh, maxval, type, dst=None)

研究了一下参数,

src:需要进行二值化的一张灰度图像

thresh:手动指定的灰度值(0~255)(用来比较的阈值)

maxval:另一个需要手动指定的灰度值(0~255)(将要设置的灰度值)

type:opencv提供的二值化方法

dst:输出图像,可以忽略

返回值有两个,第一个是opencv实际在做二值化处理时的用的灰度值,第二个是二值化后的图像

在使用这个函数的时候,

第一个参数src

需要一张灰度图,这个很简单,直接下面这段代码就能得到灰度图

image_path = './img/1.jpg'
img = cv2.imread(image_path)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

第二个参数thresh

指定一个阈值,将灰度图的像素点分成两类,灰度大于阈值的像素点集合和小于阈值的像素点集合

一般简单粗暴直接传个中间值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

一般情况下可以认为把大于阈值的像素点的灰度值设置成maxval,一般用255,即大于阈值的像素点值一律变成255(白色)

第四个参数type

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)

GitHub 加速计划 / opencv31 / opencv
77.38 K
55.71 K
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:2 个月前 )
48668119 dnn: use dispatching for Winograd optimizations 11 小时前
3dace76c flann: remove unused hdf5 header 11 小时前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐