• Python 图像处理 OpenCV (6):图像的阈值处理


    前文传送门:

    「Python 图像处理 OpenCV (1):入门」

    「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」

    「Python 图像处理 OpenCV (3):图像属性、图像感兴趣 ROI 区域及通道处理」

    「Python 图像处理 OpenCV (4):图像算数运算以及修改颜色空间」

    「Python 图像处理 OpenCV (5):图像的几何变换」

    图像的阈值

    看到这个词可能大家都很懵,为啥在图像处理里面还会有阈值。

    图像的阈值处理用大白话讲就是将图像转化为二值图像(黑白图),目的是用来提取图像中的目标物体,将背景和噪声区分开(可以近似的认为除了目标全是噪声)。

    通常会设定一个阈值 T ,通过 T 将图像的像素划分为两类:大于 T 的像素群和小于 T 的像素群。

    首先可以先将图像转化为灰度图像,因为在灰度图像中,每个像素都只有一个灰度值用来表示当前像素的亮度。

    接下来二值化处理可以将图像中的像素划分为两类颜色,一种是大于阈值 T 的,另一种是小于阈值 T 的。

    比如最常见的二值图像:

    当灰度值小于阈值 T 的时候,可以将其像素设置为 0 ,表示为黑色。

    当灰度值大于阈值 T 的时候,可以将其像素设置为 255 ,表示为白色。

    在 OpenCV 中,为我们提供了阈值函数 threshold() 来帮助我们实现二值图像的处理。

    函数如下:

    retval, dst = threshold(src, thresh, maxval, type, dst=None)
    
    • retval: 阈值
    • dst: 处理后的图像
    • src: 原图像
    • thresh: 阈值
    • maxval: 最大值
    • type: 处理类型

    常用的 5 中处理类型如下:

    • cv.THRESH_BINARY: 二值处理
    • cv.THRESH_BINARY_INV: 反二值处理
    • cv.THRESH_TRUNC: 截断阈值化
    • cv.THRESH_TOZERO: 阈值化为 0
    • cv.THRESH_TOZERO_INV: 反阈值化为 0

    接下来这几种处理类型有啥不同,我们一个一个来看。

    二值处理

    这种二值处理方式最开始需要选定一个阈值 T ,从 0 ~ 255 之间,我这里选择出于中间的那个数 127 。

    接下来的处理规则就是这样的:

    • 大于等于 127 的像素点的灰度值设定为最大值,也就是 255 白色
    • 小于 127 的像素点的灰度值设定为 0 ,也就是黑色

    接下来开始写代码,看我们的马里奥同学(不知道你们还记不记得我们的马里奥同学):

    import cv2 as cv
    
    src = cv.imread("maliao.jpg")
    
    # BGR 图像转灰度
    gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    
    # 二值图像处理
    r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY)
    
    # 显示图像
    cv.imshow("src", src)
    cv.imshow("result", b)
    
    # 等待显示
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    反二值处理

    这种方式和上面的二值处理非常相似,只是把处理规则给反了一下:

    • 大于等于 127 的像素点的灰度值设定为 0 ,也就是白色
    • 小于 127 的像素点的灰度值设定为最大值,也就是 255 白色

    完整代码如下:

    import cv2 as cv
    
    src = cv.imread("maliao.jpg")
    
    # BGR 图像转灰度
    gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    
    # 二值图像处理
    r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY_INV)
    
    # 显示图像
    cv.imshow("src", src)
    cv.imshow("result", b)
    
    # 等待显示
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    从图像上可以看到,颜色和上面的二值图像正好相反,大部分的位置都变成了白色。

    截断阈值化

    这种方法还是需要先选定一个阈值 T ,图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变。

    完整代码如下:

    import cv2 as cv
    
    src = cv.imread("maliao.jpg")
    
    # BGR 图像转灰度
    gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    
    # 二值图像处理
    r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_TRUNC)
    
    # 显示图像
    cv.imshow("src", src)
    cv.imshow("result", b)
    
    # 等待显示
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    这种方式实际上是把图片比较亮的像素处理成为阈值,其他部分保持不变。

    阈值化为 0

    这种方式还是需要先选定一个阈值 T ,将小于 T 的像素点设置为 0 黑色,其他的保持不变。

    完整代码如下:

    import cv2 as cv
    
    src = cv.imread("maliao.jpg")
    
    # BGR 图像转灰度
    gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    
    # 二值图像处理
    r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO)
    
    # 显示图像
    cv.imshow("src", src)
    cv.imshow("result", b)
    
    # 等待显示
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    这个方法是亮的部分不改,把比较暗的部分修改为 0 。

    反阈值化为 0

    这个和前面的反二值图像很像,同样是反阈值化为 0 ,将大于等于 T 的像素点变为 0 ,其余保持不变。

    完整代码如下:

    import cv2 as cv
    
    src = cv.imread("maliao.jpg")
    
    # BGR 图像转灰度
    gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    
    # 二值图像处理
    r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO_INV)
    
    # 显示图像
    cv.imshow("src", src)
    cv.imshow("result", b)
    
    # 等待显示
    cv.waitKey(0)
    cv.destroyAllWindows()
    

    这个方法是暗的部分不改,把比较亮的部分修改为 0 。

    全家福

    接下来还是给这几种阈值处理后的图像来个全家福,让大家能有一个直观的感受,代码我也给出来,如下:

    import cv2 as cv
    import matplotlib.pyplot as plt
    
    # 读取图像
    img=cv.imread('maliao.jpg')
    lenna_img = cv.cvtColor(img,cv.COLOR_BGR2RGB)
    gray_img=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    
    # 阈值化处理
    ret1, thresh1=cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY)
    ret2, thresh2=cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY_INV)
    ret3, thresh3=cv.threshold(gray_img, 127, 255, cv.THRESH_TRUNC)
    ret4, thresh4=cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO)
    ret5, thresh5=cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO_INV)
    
    # 显示结果
    titles = ['Gray Img','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
    images = [gray_img, thresh1, thresh2, thresh3, thresh4, thresh5]
    
    # matplotlib 绘图
    for i in range(6):
       plt.subplot(2, 3, i+1), plt.imshow(images[i],'gray')
       plt.title(titles[i])
       plt.xticks([]),plt.yticks([])
    
    plt.show()
    

    示例代码

    如果有需要获取源码的同学可以在公众号回复「OpenCV」进行获取。

    参考

    https://blog.csdn.net/Eastmount/article/details/83548652

    http://www.woshicver.com/

  • 相关阅读:
    记录一些常用的JS属性和语句
    明确前端工作定位
    PHP实现定时执行任务的方法
    经典的阿里前端笔试题
    CSS3 一、文本阴影textshadow属性
    Javascript作用域
    DOM事件探秘
    JavaScript中‘this’关键词的优雅解释
    Sublime Text3 支持Less
    修改table 设置默认值
  • 原文地址:https://www.cnblogs.com/babycomeon/p/13047763.html
Copyright © 2020-2023  润新知