OpenCV 图像直方图

在图像处理中,直方图是一种非常重要的工具,它可以帮助我们了解图像的像素分布情况。

通过分析图像的直方图,我们可以进行图像增强、对比度调整、图像分割等操作。

什么是图像直方图?

图像直方图是图像像素强度分布的图形表示,对于灰度图像,直方图显示了每个灰度级(0到255)在图像中出现的频率,对于彩色图像,我们可以分别计算每个通道(如R、G、B)的直方图。

直方图可以帮助我们了解图像的亮度、对比度等信息。例如,如果直方图集中在低灰度区域,说明图像偏暗;如果直方图分布均匀,说明图像对比度较好。

  • 直方图: 表示图像中像素强度的分布情况,横轴表示像素强度值,纵轴表示该强度值的像素数量。

  • 灰度直方图: 针对灰度图像的直方图,表示每个灰度级的像素数量。

  • 颜色直方图: 针对彩色图像的直方图,分别表示每个颜色通道(如 BGR)的像素强度分布。

OpenCV 提供了丰富的直方图计算和操作函数:

功能函数说明
计算直方图cv2.calcHist()计算图像的直方图。
直方图均衡化cv2.equalizeHist()增强图像的对比度。
直方图比较cv2.compareHist()比较两个直方图的相似度。
绘制直方图matplotlib.pyplot.plot()使用 Matplotlib 绘制直方图。

OpenCV 中的直方图计算函数

在 OpenCV 中,我们可以使用 cv2.calcHist() 函数来计算图像的直方图。

cv2.calcHist() 函数语法

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

参数说明

  • images: 输入的图像列表,通常是一个包含单通道或多通道图像的列表。例如 [img]
  • channels: 需要计算直方图的通道索引。对于灰度图像,使用 [0];对于彩色图像,可以使用 [0][1][2] 分别计算蓝色、绿色和红色通道的直方图。
  • mask: 掩码图像。如果指定了掩码,则只计算掩码区域内的像素。如果不需要掩码,可以传入 None
  • histSize: 直方图的 bin 数量。对于灰度图像,通常设置为 [256],表示将灰度级分为 256 个 bin。
  • ranges: 像素值的范围。对于灰度图像,通常设置为 [0, 256],表示像素值的范围是 0 到 255。
  • hist: 输出的直方图数组。
  • accumulate: 是否累积直方图。如果设置为 True,则直方图不会被清零,而是在每次调用时累积。

假设我们有一张灰度图像 img,我们可以使用以下代码计算其直方图:

实例

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# 计算直方图
hist = cv2.calcHist([img], [0], None, [256], [0, 256])

# 绘制直方图
plt.plot(hist)
plt.title('Grayscale Histogram')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.show()

直方图均衡化

直方图均衡化是一种增强图像对比度的方法,通过重新分配像素强度值,使直方图更加均匀。

语法:

equalized_image = cv2.equalizeHist(image)

实例

# 直方图均衡化
equalized_image = cv2.equalizeHist(image)

# 显示结果
cv2.imshow("Equalized Image", equalized_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

颜色直方图

计算颜色直方图

对于彩色图像,可以分别计算每个颜色通道的直方图。

实例

# 读取彩色图像
image = cv2.imread("path/to/image")

# 计算 BGR 各通道的直方图
colors = ('b', 'g', 'r')
for i, color in enumerate(colors):
    hist = cv2.calcHist([image], [i], None, [256], [0, 256])
    plt.plot(hist, color=color)

# 绘制直方图
plt.title("Color Histogram")
plt.xlabel("Pixel Intensity")
plt.ylabel("Pixel Count")
plt.show()

颜色直方图均衡化

对于彩色图像,可以对每个通道分别进行直方图均衡化。

实例

# 分离通道
b, g, r = cv2.split(image)

# 对每个通道进行直方图均衡化
b_eq = cv2.equalizeHist(b)
g_eq = cv2.equalizeHist(g)
r_eq = cv2.equalizeHist(r)

# 合并通道
equalized_image = cv2.merge([b_eq, g_eq, r_eq])

# 显示结果
cv2.imshow("Equalized Color Image", equalized_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

直方图比较

OpenCV 提供了 cv2.compareHist() 函数,用于比较两个直方图的相似度。

语法:

similarity = cv2.compareHist(hist1, hist2, method)
  • hist1: 第一个直方图。

  • hist2: 第二个直方图。

  • method: 比较方法,例如 cv2.HISTCMP_CORREL(相关性比较)。

实例

# 计算两个图像的直方图
hist1 = cv2.calcHist([image1], [0], None, [256], [0, 256])
hist2 = cv2.calcHist([image2], [0], None, [256], [0, 256])

# 比较直方图
similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
print("Histogram Similarity:", similarity)

直方图的应用

  • 图像增强: 通过直方图均衡化,可以增强图像的对比度,使细节更加清晰。
  • 图像分割: 过分析直方图,可以确定阈值,用于图像分割。
  • 图像匹配: 通过比较直方图,可以判断两幅图像的相似度,用于图像匹配和检索。
  • 颜色分析: 通过颜色直方图,可以分析图像的颜色分布,用于颜色校正和风格化处理。

以下是一个完整的直方图计算和均衡化示例代码:

实例

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取灰度图像
image = cv2.imread("path/to/image", cv2.IMREAD_GRAYSCALE)

# 计算灰度直方图
hist = cv2.calcHist([image], [0], None, [256], [0, 256])

# 绘制直方图
plt.plot(hist)
plt.title("Grayscale Histogram")
plt.xlabel("Pixel Intensity")
plt.ylabel("Pixel Count")
plt.show()

# 直方图均衡化
equalized_image = cv2.equalizeHist(image)

# 显示结果
cv2.imshow("Equalized Image", equalized_image)
cv2.waitKey(0)
cv2.destroyAllWindows()