使用 OpenCV 和 Matplotlib:绘制其彩色直方图以及拓展

如何使用 OpenCV 和 Matplotlib 读取、处理并显示图像。即将为您解答:

绘制其彩色直方图

代码解释

  1. 读取图像并转换颜色空间:

    复制代码
     
    python 复制代码
    image = cv2.imread('001.jpg')
    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    • cv2.imread('001.jpg'):从文件中读取图像,图像默认以 BGR 格式加载。
    • cv2.cvtColor(image, cv2.COLOR_BGR2RGB):将图像从 BGR 格式转换为 RGB 格式,便于 Matplotlib 正确显示。
  2. 拆分通道:

    复制代码
     
    python 复制代码
    channels = cv2.split(image)
    colors = ('b', 'g', 'r')
    • cv2.split(image):将图像的 BGR 三个通道分开,分别对应蓝色、绿色、红色。
    • colors:定义颜色顺序,用于在直方图中标记不同通道。
  3. 创建图形和子图:

    复制代码
     
    python 复制代码
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8), gridspec_kw={'height_ratios': [1, 3]})
    • plt.subplots(2, 1):创建一个包含两个子图的图形,图像的布局为上下结构。
    • figsize=(10, 8):设置图形的大小,宽度为 10 英寸,高度为 8 英寸。
    • gridspec_kw={'height_ratios': [1, 3]}:设置子图的高度比例,上方直方图高度为 1,图像高度为 3。
  4. 绘制彩色直方图:

    复制代码
     
    python 复制代码
    for (channel, color) in zip(channels, colors):
        hist = cv2.calcHist([channel], [0], None, [256], [0, 256])
        ax1.plot(hist, color=color, linewidth=2.5, alpha=0.75)
    • cv2.calcHist([channel], [0], None, [256], [0, 256]):计算每个颜色通道的直方图,256 个 bins 表示像素值范围从 0 到 255。
    • ax1.plot(hist, color=color, linewidth=2.5, alpha=0.75):在 ax1 子图上绘制每个通道的直方图,不同颜色曲线对应不同通道。
  5. 设置直方图子图:

    复制代码
     
    python 复制代码
    ax1.set_title('Color Histogram', fontsize=15)
    ax1.set_xlabel('Bins', fontsize=12)
    ax1.set_ylabel('# of Pixels', fontsize=12)
    ax1.grid(color='gray', linestyle='--', linewidth=0.5)
    ax1.set_xlim([0, 256])
    ax1.set_xticks([])
    ax1.set_yticks([])
    • 设置标题、轴标签、网格线,并移除坐标轴的刻度。
  6. 显示图像:

    复制代码
     
    python 复制代码
    ax2.imshow(image_rgb)
    ax2.set_title('Original Image', fontsize=15)
    ax2.axis('off')
    • 在 ax2 子图上显示原始图像,并设置标题,移除坐标轴。
  7. 调整布局并显示:

    复制代码
     
    python 复制代码
    plt.tight_layout()
    plt.show()
    • plt.tight_layout():自动调整子图之间的间距,使图形布局更加紧凑。
    • plt.show():显示图形。

总结

  • 功能:该代码实现了图像的读取、颜色直方图的计算与绘制,并将图像和直方图在同一个图形中显示。
  • 目的:直方图提供了图像像素值的分布情况,而图像显示则有助于直观理解图像内容,两者结合能够更好地分析图像的颜色信息。

整体代码

python 复制代码
import cv2
import matplotlib.pyplot as plt

# 读取图像
image = cv2.imread('001.jpg')
# 将图像从 BGR 转换为 RGB 格式
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 拆分通道
channels = cv2.split(image)
colors = ('b', 'g', 'r')

# 创建一个包含两个子图的图形
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8), gridspec_kw={'height_ratios': [1, 3]})

# 绘制直方图在第一个子图
ax1.set_title('Color Histogram', fontsize=15)
ax1.set_xlabel('Bins', fontsize=12)
ax1.set_ylabel('# of Pixels', fontsize=12)
ax1.grid(color='gray', linestyle='--', linewidth=0.5)

for (channel, color) in zip(channels, colors):
    hist = cv2.calcHist([channel], [0], None, [256], [0, 256])
    ax1.plot(hist, color=color, linewidth=2.5, alpha=0.75)

ax1.set_xlim([0, 256])
ax1.set_xticks([])
ax1.set_yticks([])

# 绘制图像在第二个子图
ax2.imshow(image_rgb)
ax2.set_title('Original Image', fontsize=15)
ax2.axis('off')

# 调整布局,使图形更加紧凑
plt.tight_layout()

plt.show()

效果展示


衍生操作

1.色彩平衡和直方图均衡化

代码说明

  • 图像读取与颜色空间转换:

    • 首先,使用 cv2.imread() 函数读取图像,并将其从 BGR 格式转换为 RGB 格式,以便使用 Matplotlib 显示。
  • 通道分离与直方图均衡化:

    • 将图像的 RGB 通道分离出来,并对每个通道单独进行直方图均衡化处理,以平衡颜色和改善对比度。
  • 图像合并与显示:

    • 将均衡化后的通道合并成一张图像,并使用 Matplotlib 显示原始图像、均衡化图像以及它们对应的直方图。

整体代码

python 复制代码
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像
image = cv2.imread('001.jpg')

# 将图像从 BGR 转换为 RGB 格式
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 分离图像的三个通道
r, g, b = cv2.split(image_rgb)

# 对每个通道应用直方图均衡化
r_equalized = cv2.equalizeHist(r)
g_equalized = cv2.equalizeHist(g)
b_equalized = cv2.equalizeHist(b)

# 合并均衡化后的通道
equalized_image = cv2.merge((r_equalized, g_equalized, b_equalized))

# 创建一个包含原始图像和均衡化图像的图形
plt.figure(figsize=(12, 6))

# 显示原始图像
plt.subplot(2, 2, 1)
plt.imshow(image_rgb)
plt.title('Original Image')
plt.axis('off')

# 显示均衡化图像
plt.subplot(2, 2, 2)
plt.imshow(equalized_image)
plt.title('Histogram Equalized Image')
plt.axis('off')

# 显示原始图像的直方图
plt.subplot(2, 2, 3)
for channel, color in zip([r, g, b], ['r', 'g', 'b']):
    hist = cv2.calcHist([channel], [0], None, [256], [0, 256])
    plt.plot(hist, color=color)
plt.title('Original Histogram')
plt.xlim([0, 256])
plt.xlabel('Pixel Intensity')
plt.ylabel('Frequency')

# 显示均衡化图像的直方图
plt.subplot(2, 2, 4)
for channel, color in zip([r_equalized, g_equalized, b_equalized], ['r', 'g', 'b']):
    hist = cv2.calcHist([channel], [0], None, [256], [0, 256])
    plt.plot(hist, color=color)
plt.title('Equalized Histogram')
plt.xlim([0, 256])
plt.xlabel('Pixel Intensity')
plt.ylabel('Frequency')

# 调整布局并显示图像
plt.tight_layout()
plt.show()

效果展示


2.动态直方图和实时摄像头图像分析

代码说明

  • 摄像头初始化:

    • cap = cv2.VideoCapture(0) 用于初始化摄像头。参数 0 表示使用默认摄像头。
  • 实时视频捕捉:

    • 使用 cap.read() 从摄像头捕捉实时视频帧。
  • 颜色空间转换:

    • 使用 cv2.cvtColor() 将 BGR 图像转换为 RGB 格式,以便 Matplotlib 正确显示颜色。
  • 直方图计算:

    • 将图像的 RGB 通道分离,并使用 cv2.calcHist() 计算每个通道的直方图。
  • 动态更新图像和直方图:

    • 使用 Matplotlib 的交互模式 (plt.ion()) 实时更新图像和直方图。
    • 每次读取一帧图像时,先清除之前的图像和直方图,然后重新绘制。
  • 按键退出:

    • 在循环中检测键盘按键,如果按下 q 键,则退出循环,停止视频捕捉并关闭窗口。

整体代码

python 复制代码
import cv2
import matplotlib.pyplot as plt
import numpy as np

# 初始化摄像头
cap = cv2.VideoCapture(0)

# 创建一个窗口来显示视频流和直方图
plt.ion()  # 打开交互模式
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8), gridspec_kw={'height_ratios': [1, 3]})

while True:
    # 读取摄像头的一帧
    ret, frame = cap.read()
    if not ret:
        break

    # 将图像从 BGR 转换为 RGB 格式
    image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # 分离图像的三个通道
    r, g, b = cv2.split(image_rgb)

    # 清除之前的图像和直方图
    ax1.clear()
    ax2.clear()

    # 显示当前帧
    ax2.imshow(image_rgb)
    ax2.set_title('Real-Time Camera Feed', fontsize=15)
    ax2.axis('off')

    # 计算直方图并绘制
    ax1.set_title('Color Histogram', fontsize=15)
    ax1.set_xlabel('Bins', fontsize=12)
    ax1.set_ylabel('# of Pixels', fontsize=12)
    ax1.grid(color='gray', linestyle='--', linewidth=0.5)

    for (channel, color) in zip([r, g, b], ['r', 'g', 'b']):
        hist = cv2.calcHist([channel], [0], None, [256], [0, 256])
        ax1.plot(hist, color=color, linewidth=2.5, alpha=0.75)

    ax1.set_xlim([0, 256])

    # 刷新绘图窗口
    plt.pause(0.001)

    # 检测按键,按 'q' 键退出循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放摄像头并关闭所有窗口
cap.release()
cv2.destroyAllWindows()
plt.ioff()
plt.show()

效果展示


相关推荐
benchmark_cc1 小时前
用 QuantDash 读取单只股票五档盘口:抽样、缺失值检查与复现记录
python·数据分析·pandas·量化交易·股票数据·quantdash
曲径海盗2 小时前
【Python 学习第 55 天】列表基础
python·学习笔记·编程入门
专注仿真2 小时前
知识问答模型用到的算法集详解及代码实例
python·算法·代码·大模型训练·控制算法
jyOverQ2 小时前
我写了一个 CSDN Markdown 图片助手:告别本地图片逐张上传
python·工具·csdn
刘马想放假6 小时前
CANviz 使用指南|Linux 安装、DBC 解码、实时曲线与 J1939 实战
linux·python·websocket
2601_967987376 小时前
python判断变量名不要调用任何函数实现
python·函数·语法·判断·变量名
卷无止境7 小时前
SALib敏感性分析的python库学习笔记
后端·python
duansamve8 小时前
Python3+Flask+PostgreSQL18+Vue3项目生产环境用docker如何部署?
python·docker·flask
特立独行的猫A8 小时前
少 3 个环节、少 1 次 ABI、少 3500 行代码:cj-tauri 与 Ionic/Capacitor 的鸿蒙桥接机制对比
java·后端·python
特立独行的猫A9 小时前
cj-tauri vs Rust/Tauri 同款播放器实测:编译 21 秒 vs 11 分钟,磁盘 12 MB vs 1.2 GB
java·后端·python