• Python机器视觉--OpenCV进阶(核心)--图像直方图与掩膜直方图与直方图均衡化


    1.图像直方图

    1.1 图像直方图的基本概念

    统计学中,直方图是一种对数据分布情况的图形表示,是一种二维统计图表.

    图像直方图是用一表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。可以借助观察该直方图了解需要如何调整亮度分布的直方图。这种直方图中,横坐标的左侧为纯黑、较暗的区域,而右侧为较亮、纯白的区域。因此,一张较暗图片的图像直方图中的数据多集中于左侧和中间部分,而整体明亮、只有少量阴影的图像则相反。

    1.2绘制直方图

    • 横坐标: 图像中各个像素点的灰度级.
    • 纵坐标: 具有该灰度级的像素个数.

    图片来源: https://www.cambridgeincolour.com/tutorials/histograms1.htm


    画出上图的直方图:

    image-20211122153237404

    或者以柱状图的形式:

    1.3归一化直方图

    • 横坐标: 图像中各个像素点的灰度级

    • 纵坐标: 出现这个灰度级的概率

    直方图术语
    dims:需要统计的特征的数目。例如:dims=1,表示我们仅统计灰度值。
    bins:每个特征空间子区段的数目。

    range:统计灰度值的范围, 一般为[0, 255]

    2.基于OpenCV的统计直方图

    2.1 Opencv绘制直方图

    • calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])

      • images: 原始图像
      • channels: 指定通道.
        • 需要用中括号括起来, 输入图像是灰度图像是, 值是[0], 彩色图像可以是[0], [1], [2], 分别对应B,G,R.
      • mask: 掩码图像
        • 统计整幅图像的直方图, 设为None
        • 统计图像某一部分的直方图时, 需要掩码图像.
      • histSize: BINS的数量
        • 需要用中括号括起来, 例如[256]
      • ranges: 像素值范围, 例如[0, 255]
      • accumulate: 累积标识
        • 默认值为False
        • 如果被设置为True, 则直方图在开始分配时不会被清零.
        • 该参数允许从多个对象中计算单个直方图, 或者用于实时更新直方图.
        • 多个直方图的累积结果, 用于对一组图像计算直方图.
    代码实现 (统计直方图)
    import cv2
    import matplotlib.pyplot as plt
    lena = cv2.imread('./lena.png')
    
    hist = cv2.calcHist([lena], [0], None, [256], [0, 255])
    print(type(hist))
    print(hist.size)
    print(hist.shape)
    print(hist)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    代码实现(plt统计绘制直方图)
    import matplotlib.pyplot as plt
    ### h绘制直方图
    # 不使用cv2方法
    img=cv2.imread('./lena.png')
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    plt.hist(gray.ravel(),bins=256,range=[0,255])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    结果如图

    在这里插入图片描述

    代码实现(使用OpenCV统计绘制 直方图)
    import cv2
    import matplotlib.pyplot as plt
    lena = cv2.imread('./lena.png')
    
    histb = cv2.calcHist([lena], [0], None, [256], [0, 255])
    histg = cv2.calcHist([lena], [1], None, [256], [0, 255])
    histr = cv2.calcHist([lena], [2], None, [256], [0, 255])
    
    plt.plot(histb, color='b')
    plt.plot(histg, color='g')
    plt.plot(histr, color='r')
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    结果如图

    在这里插入图片描述

    2.2 使用掩膜的直方图

    • 掩膜

    • 如何生成掩膜

      • 先生成一个全黑的和原始图片大小一样大的图片. mask = np.zeros(image.shape, np.uint8)
      • 将想要的区域通过索引方式设置为255. mask[100:200, 200: 300] = 355
    代码实现
    import cv2
    import matplotlib.pyplot as plt
    lena = cv2.imread('./lena.png')
    gray = cv2.cvtColor(lena, cv2.COLOR_BGR2GRAY)
    
    mask = np.zeros(gray.shape, np.uint8)
    mask[200:400, 200: 400] = 255
    hist_mask = cv2.calcHist([gray], [0], mask, [256], [0, 255])
    hist_img = cv2.calcHist([gray], [0], None, [256], [0, 255])
    plt.plot(hist_mask)
    plt.plot(hist_img)
    
    cv2.imshow('mask', cv2.bitwise_and(gray, gray, mask=mask))
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    结果如图

    在这里插入图片描述

    3.直方图均衡化原理

    直方图均衡化是通过拉伸像素强度的分布范围,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。

    原理:

    1. 计算累计直方图
    2. 讲累计直方图进行区间转换
    3. 在累计直方图中, 概率相近的原始值, 会被处理为相同的值

    • equalizeHist(src[, dst])
      • src 原图像
      • dst 目标图像, 即处理结果
    代码实现
    import cv2
    import matplotlib.pyplot as plt
    lena = cv2.imread('./lena.png')
    gray = cv2.cvtColor(lena, cv2.COLOR_BGR2GRAY)
    
    # lena变黑
    gray_dark = gray - 40
    # lena变亮
    gray_bright = gray + 40
    
    # 查看各自的直方图
    hist_gray = cv2.calcHist([gray], [0], None, [256], [0, 255])
    hist_dark = cv2.calcHist([gray_dark], [0], None, [256], [0, 255])
    hist_bright = cv2.calcHist([gray_bright], [0], None, [256], [0, 255])
    
    plt.plot(hist_gray)
    plt.plot(hist_dark)
    plt.plot(hist_bright)
    
    # 进行均衡化处理
    dark_equ = cv2.equalizeHist(gray_dark)
    bright_equ = cv2.equalizeHist(gray_bright)
    cv2.imshow('gray_dark', np.hstack((gray_dark, dark_equ)))
    cv2.imshow('gray_bright', np.hstack((gray_bright, bright_equ)))
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    结果如图

  • 相关阅读:
    (vue)el-select选择框加全选/清空/反选
    27、Java高级特性——集合、ArrayList集合、LinkedList集合、List接口、ArrayList和LinkedList的区别
    2023南华大学计算机考研信息汇总
    解释器-架构案例2021(三十一)
    C# 之 扑克游戏 -- 21点规则介绍和代码实现
    人大金仓KingbaseES_V008R006C008B0014安装
    BUUCTF [BJDCTF2020]藏藏藏 1
    3.8、集线器与交换机的区别
    详解C++代码从源代码到可执行文件的整个编译过程(预处理、编译、汇编和链接)
    深入URP之Shader篇1: URP Shader概述
  • 原文地址:https://blog.csdn.net/qq_43944517/article/details/126914714