今天是持续写作的第 38 / 100 天。
如果你有想要交流的想法、技术,欢迎在评论区留言。

取经之旅第 6 天

    • 彩色图像的二值化
      • 方法 1
      • 方法 2
      • 方法 3
    • OpenCV 尾声

今天学习一下彩色图像的二值化操作。

彩色图像的二值化

图像的二值化,就是让图像的像素点矩阵中,每个像素点的灰度值设置为 0(黑色) 或者 255(白色),说白了就是让图像呈现只有黑和白的效果。

在灰度图中图像的灰度值的范围是 0~255,在二值化的图像中灰度值的范围是 0 或者 255。

一个像素点在灰度化之后的灰度值如何转换为 0(黑色)或者 255(白色),例如灰度值是 200,那二值化之后到底是 0 还是 255,这里面衍生出来的概念叫做阈值

有前面咱学到的像素概念,这时橡皮擦首先想到的是二值化肯定能大幅度降低图像处理的数据量,毕竟数值变少了。

那接下来就学习一下如何将图像二值化吧。

方法 1

取阈值为 127,相当于 0~255 的中数(0+255)/2 = 127,灰度值大于等于 127 的设置为 0,灰度值大于 127 的设置为 255,这种方法简单便捷,缺点就是阈值设置的太死板了,对于不同的照片,效果肯定不同。检索资料的时候发现,还有人把这种方法称为 史上最弱智的二值处理方法,没办法,弱智方法也得学啊。

该方法会使用到一个 threshold 方法。

threshold 方法的语法格式如下:

cv2.threshold(src, thresh, maxval, type[, dst]) -> retval, dst

参数说明如下:

  • src 输入图,中只能输入单通道图,一般就是灰度图;
  • thresh 阈值;
  • maxval 最大值,当像素超过了阈值(或者小于阈值)时所赋予的值;
  • type – 二值化操作的类型,有 5 种,在下文描述;
  • dst 输出数组/图像(与 src 相同大小和类型以及相同通道数的数组/图像)。

返回值 retval 阈值 thresh, dst 经过处理的图像。

二值化操作类型(阈值类型):

  1. 二进制阈值化 THRESH_BINARY,过门限的值为最大值,其他值为 0;
  2. 反二进制阈值化 THRESH_BINARY_INV,过门限的值为 0,其他值为最大值;
  3. 截断阈值化 THRESH_TRUNC,过门限的值为门限值,其他值不变;
  4. 阈值化为 0 THRESH_TOZERO,过门限的值不变,其他设置为 0;
  5. 反阈值化为 0 THRESH_TOZERO_INV,过门限的值为 0,其他不变。

以上内容也叫做全局阈值

全局阈值代码测试代码如下

import cv2

def main():
    img = cv2.imread("6.jpg", 0)
    thresh, dst = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    cv2.imshow("dst", dst)
    cv2.waitKey()

if __name__ == "__main__":
    main()

得到的效果真的不怎么好看。

不断的去调整下图红框中的值,查看效果。

更换最后一个个参数之后,可以对比不同效果。

方法 2

计算像素点矩阵中的所有像素点的灰度值的平均值 avg,让每一个像素点与 avg 比较,小于等于 avg 的像素点就为 0(黑色),大于 avg 的像 素点为 255(白色),这种方法看起来靠谱了一些。

使用该方法之前需要先遍历图像的所有灰度值,才能计算出平均值。

    img = cv2.imread("6.jpg", 0)
    height, width = img.shape
    # 灰度值总和
    px_t = 0
    for i in range(height):
        for j in range(width):
            px_t += img[i][j]
    print(px_t)
    # 求像素平均值
    avg_thresh = int(px_t/(height*width))

    thresh, dst = cv2.threshold(img, avg_thresh, 255, cv2.THRESH_BINARY)
    print("阈值:", thresh)
    cv2.imshow("dst", dst)

    cv2.waitKey()

方法 3

在使用方法 3 学习之前,先跑偏一点,距离今日的 1 小时学习时间又要过去了。

安装 matplotlib 库,然后用于图片的展示,就不用每次都使用 imshow 方法了。

安装比较简单,pip install matplotlib 即可。

头部导入模块之后,编写如下代码:

import cv2
import matplotlib.pylab as plt
def main2():
    img = cv2.imread('6.jpg', 0)
    ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
    ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
    ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
    ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)

    titles = ['Original Image', 'BINARY',
              'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
    images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

    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 尾声

1 个小时又过去了,对 Python OpenCV 图像写入相关的知识点,你掌握了吗?

空闲之余,可以订阅橡皮擦的爬虫百例课程学习爬虫知识。

想学 Python 爬虫,可以订阅橡皮擦专栏哦~ 点击发现惊喜

如果你想跟博主建立亲密关系,可以关注博主,或者关注博主公众号 “非本科程序员”,了解一个非本科程序员是如何成长的。
博主 ID:梦想橡皮擦,希望大家点赞、评论、收藏

本文地址:https://blog.csdn.net/hihell/article/details/111936034