opencv库图像基础3直方图-python

发布时间 2024-01-05 16:38:41作者: AndreaDO

opencv库图像基础3直方图-python

直方图是什么

OpenCV 中的直方图是图像中像素值分布情况的统计表示。它是图像空间域内像素值分布的图形表示,以便更好地理解颜色分布。
灰度直方图是图像中每个像素灰度值出现的次数或频数的统计结果。它只反映该图像中灰度值出现的频率,而未反映某一灰度值像素所在的位置。也就是说,它只包含了该图像中某个灰度值的像素出现的概率,而丢失了其所在的位置的信息。 任一幅图像,都能唯一地算出一幅与它对应的直方图。但不同的图像,可能有相同的直方图。

直方图的用处

直方图可以用来分析图像的对比度、亮度和灰度分布。
例如,如果图像的直方图集中在低灰度值区域,则说明图像比较暗;如果图像的直方图集中在高灰度值区域,则说明图像比较亮。

直方图可以用来进行图像增强。例如,可以通过直方图均衡化来提高图像的对比度,使图像更加清晰。

直方图可以用来进行图像分割。例如,可以通过直方图反投影来查找图像中具有特定颜色或灰度值的区域。

直方图可以用来进行图像识别。例如,可以通过比较图像的直方图来识别图像中的对象。

OpenCV 提供了以下函数来计算和绘制直方图:

  • cv2.calcHist() 函数用于计算直方图。
  • cv2.imshow() 函数用于显示图像。
  • cv2.plot() 函数用于绘制直方图。

需要导入的库

# 1 导入库
import cv2
import matplotlib.pyplot as plt
import numpy as np

灰度直方图

创建两个工具函数 显示图片和显示直方图

# 2 方法:显示图片
def show_image(image, title, pos):
    #  顺序转换:BGR TO RGB
    image_RGB = image[:, :, ::-1] # shape : (height, width, channel)
    # 显示标题
    plt.title(title)
    plt.subplot(2, 3, pos) # 定位
# 2, 3 表示图像将显示在一个 2 行 3 列的网格中,pos 表示图像在网格中的位置。例如,pos=1 表示图像将显示在网格的第 1 行第 1 列。
    plt.imshow(image_RGB)

# 3 方法:显示图片的灰度直方图
def show_histogram(hist, title, pos, color):
    # 显示标题
    plt.title(title)
    plt.subplot(2, 3, pos) # 定位图片
    plt.xlabel("Bins") # 横轴信息
    plt.ylabel("Pixels") # 纵轴信息
    plt.xlim([0, 256]) # 范围
    plt.plot(hist, color=color) # 绘制直方图

编写主函数

# 4 主函数 main()
def main():
    # 5 创建画布
    plt.figure(figsize=(15, 6)) # 画布大小
    plt.suptitle("Gray Image Histogram", fontsize=14, fontweight="bold") # 设置标题形式

    # 6 加载图片
    img = cv2.imread("C:\\1.jpg") #这里修改成你自己图像位置
    # 7 灰度转换
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 8 计算灰度图的直方图
    hist_img = cv2.calcHist([img_gray], [0], None, [256], [0, 256]) #灰度图像这里写0

    # 9 展示灰度直方图
    # 灰度图转换成BGR格式图片
    img_BGR = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
    show_image(img_BGR, "BGR image", 1)
    show_histogram(hist_img, "gray image histogram", 4, "m")

    plt.show()

输出效果

在 OpenCV 中,cv2.calcHist() 函数用于计算直方图。它需要传入以下参数:
images:输入图像或图像的数组。
channels:要计算直方图的通道索引。对于灰度图像,该参数为 0。对于彩色图像,该参数可以为 [0, 1, 2],分别表示 R、G、B 三个通道。
mask:掩码图像。如果不使用掩码,则将其设置为 None。
histSize:直方图的大小。它表示直方图中包含的灰度级数。
ranges:直方图的范围。它表示直方图中包含的灰度值范围。

mask

mask在opencv中的作用

在 OpenCV 中,直方图是图像中像素值分布情况的统计表示。它是图像空间域内像素值分布的图形表示,以便更好地理解颜色分布。

mask 是掩码图像。它可以用来指定计算直方图的区域。例如,如果要计算图像中特定区域的直方图,则可以使用掩码图像来指定该区域。

在 OpenCV 中,cv2.calcHist() 函数用于计算直方图。它需要传入 mask 参数。如果 mask 为 None,则表示计算整个图像的直方图。如果 mask 不为 None,则表示计算 mask 指定区域的直方图。

代码

用的两个函数如第一个例子上

def main():
    # 5 创建画布
    plt.figure(figsize=(12, 7))
    plt.suptitle("Gray Image and Histogram with mask", fontsize=4, fontweight="bold")

    # 6 读取图片并灰度转换,计算直方图,显示
    img_gray = cv2.imread("C://1.png", cv2.COLOR_BGR2GRAY) # 读取并进行灰度转换
    img_gray_hist = cv2.calcHist([img_gray], [0], None, [256], [0, 256]) # 计算直方图
    show_image(img_gray, "image gray", 1)
    show_histogram(img_gray_hist, "image gray histogram", 2, "m")

    # 7 创建mask,计算位图,直方图
    mask = np.zeros(img_gray.shape[:2], np.uint8)
    mask[130:500, 600:1400] = 255 # 获取mask,并赋予颜色
    img_mask_hist = cv2.calcHist([img_gray], [0], mask, [256], [0, 256]) # 计算mask的直方图

    # 8 通过位运算(与预算)计算带有mask的灰度图片
    mask_img = cv2.bitwise_and(img_gray, img_gray, mask = mask)

    # 9 显示带有mask的图片和直方图
    show_image(mask_img, "gray image with mask", 3)
    show_histogram(img_mask_hist, "histogram with masked gray image", 4, "m")

    plt.show()

输出效果

彩色直方图

创建三个辅助函数


# 2 方法:显示图片
def show_image(image, title, pos):
    plt.subplot(3, 2, pos)
    plt.title(title)
    image_RGB = image[:, :, ::-1] # BGR to RGB
    plt.imshow(image_RGB)
    plt.axis("off")

# 3 方法:显示彩色直方图 b, g, r
def show_histogram(hist, title, pos, color):
    plt.subplot(3, 2, pos)
    plt.title(title)
    plt.xlim([0, 256])
    for h, c in zip(hist, color): # color: ('b', 'g', 'r')
        plt.plot(h, color=c)


# 4 方法:计算直方图
def calc_color_hist(image):
    # b, g, r
    hist = []
    hist.append( cv2.calcHist([image], [0], None, [256], [0, 256]))
    hist.append( cv2.calcHist([image], [1], None, [256], [0, 256]))
    hist.append( cv2.calcHist([image], [2], None, [256], [0, 256]))
    return hist

主函数

# 5 主函数
def main():
    # 5.1 创建画布
    plt.figure(figsize=(12, 8))
    plt.suptitle("Color Histogram", fontsize=4, fontweight="bold")

    # 5.2 读取原图片
    img = cv2.imread("C://1.png")

    # 5.3 计算直方图
    img_hist = calc_color_hist(img)

    # 5.4 显示图片和直方图
    show_image(img, "RGB Image", 1)
    show_histogram(img_hist, "RGB Image Hist", 2, ('b', 'g', 'r'))

    # 5.5 原始图片中的每个像素增加50个像素值
    M = np.ones(img.shape, dtype="uint8") * 50

    added_image = cv2.add(img, M) # 像素一一对应相加
    added_image_hist = calc_color_hist(added_image)
    show_image(added_image, 'added image', 3)
    show_histogram(added_image_hist, 'added image hist', 4, ('b', 'g', 'r'))


    # 5.6 原始图片中的每个像素减去50个像素值
    subtracted_image = cv2.subtract(img, M)
    subtracted_image_hist = calc_color_hist(subtracted_image)
    show_image(subtracted_image, 'subtracted image', 5)
    show_histogram(subtracted_image_hist, 'subtracted image hist', 6, ('b', 'g', 'r'))

    plt.show()

输出