【完整带注释版】图像直方图绘制教程(OpenCV+Matplotlib)

下面是整理好的带详细注释 + 教学说明的代码,既可以直接运行,也适合作为学习笔记:

python

运行

复制代码
# 导入核心库
import cv2          # OpenCV:用于图像读取、直方图计算
import matplotlib.pyplot as plt  # Matplotlib:用于绘图展示

# ===================== 一、灰度图直方图(Matplotlib直接绘制) =====================
"""
核心原理:
将灰度图像的二维像素矩阵展平为一维数组,统计每个灰度值(0-255)的像素数量
适合快速查看整体灰度分布,代码更简洁
"""
# 1. 读取灰度图:cv2.IMREAD_GRAYSCALE 指定以灰度模式读取
phone_gray = cv2.imread(filename='phone.png', flags=cv2.IMREAD_GRAYSCALE)
# 检查图片是否读取成功(避坑:路径/文件名错误会导致返回None)
if phone_gray is None:
    print("❌ 错误:找不到phone.png,请检查文件路径/名称!")
else:
    # 2. 将二维图像矩阵展平为一维数组(比如200x200的图→40000个像素值的一维数组)
    pixel_values = phone_gray.ravel()
    
    # 3. 绘制直方图
    plt.figure(figsize=(8, 4))  # 设置画布大小
    plt.hist(pixel_values, bins=256, range=[0, 256])  # bins=256表示分256个区间(对应0-255灰度)
    plt.title('灰度图直方图(Matplotlib版)')  # 标题
    plt.xlabel('灰度值(0=黑,255=白)')        # X轴标签
    plt.ylabel('像素数量')                    # Y轴标签
    plt.xlim([0, 256])                       # 限定X轴范围(仅显示0-255)
    plt.show()  # 显示图像

# ===================== 二、灰度图直方图(OpenCV计算+Matplotlib绘图) =====================
"""
核心原理:
先用cv2.calcHist计算直方图数据,再用plt.plot绘制曲线
适合自定义区间(比如合并灰度级),灵活性更高
"""
if phone_gray is not None:
    # 1. 计算直方图:cv2.calcHist(图像列表, 通道, 掩码, 区间数, 灰度范围)
    # - images=[phone_gray]:传入要计算的图像(需用列表包裹)
    # - channels=[0]:灰度图只有1个通道,固定传0;彩色图传0/1/2对应B/G/R
    # - mask=None:不使用掩码(计算整张图)
    # - histSize=[16]:将0-255灰度级合并为16个区间(每个区间包含16个灰度值)
    # - ranges=[0, 256]:灰度值的范围(固定0-256)
    phone_hist = cv2.calcHist(images=[phone_gray], channels=[0], mask=None, histSize=[16], ranges=[0, 256])
    
    # 2. 绘制直方图曲线
    plt.figure(figsize=(8, 4))
    plt.plot(phone_hist, color='black', linewidth=2)  # 黑色曲线,线宽2
    plt.title('灰度图直方图(OpenCV计算版)')
    plt.xlabel('灰度区间(共16个)')
    plt.ylabel('像素数量')
    plt.show()

# ===================== 三、彩色图三通道直方图(B/G/R分别绘制) =====================
"""
核心原理:
OpenCV读取的彩色图是BGR格式(不是RGB),需分别计算B/G/R三个通道的直方图
适合分析彩色图像的色彩分布(比如偏蓝/偏红)
"""
# 1. 读取彩色图(默认BGR格式)
img_color = cv2.imread('phone.png')
if img_color is None:
    print("❌ 错误:找不到phone.png,请检查文件路径/名称!")
else:
    # 2. 定义通道对应的颜色(B→蓝色,G→绿色,R→红色)
    color = ('blue', 'green', 'red')
    
    # 3. 遍历三个通道,分别计算+绘制直方图
    plt.figure(figsize=(8, 4))
    for i, col in enumerate(color):
        # 计算当前通道的直方图(histSize=256:每个通道分256个区间)
        histr = cv2.calcHist(images=[img_color], channels=[i], mask=None, histSize=[256], ranges=[0, 256])
        # 绘制曲线(颜色与通道对应,更直观)
        plt.plot(histr, color=col, label=f'{col}通道')
    
    # 4. 美化图表
    plt.title('彩色图三通道直方图')
    plt.xlabel('像素值(0-255)')
    plt.ylabel('像素数量')
    plt.legend()  # 显示图例(区分三个通道)
    plt.show()

📝 关键知识点总结

  1. 两种绘制方式对比
    • Matplotlib plt.hist():适合快速查看灰度分布,代码简洁,直接处理像素数组。
    • OpenCV cv2.calcHist():适合自定义区间 / 掩码,灵活性高,先算数据再绘图。
  2. 避坑要点
    • 图片路径 / 名称必须正确(建议将phone.png和代码放在同一文件夹);
    • OpenCV 彩色图是BGR 格式,不是 RGB,绘制时需注意通道对应关系;
    • if img is None检查图片读取状态,避免后续代码报错。
  3. 应用场景
    • 灰度直方图:判断图像亮度(峰值偏左 = 偏暗,偏右 = 偏亮)、对比度;
    • 彩色直方图:分析图像色彩偏向,用于图像增强 / 色彩校正。

直接运行这段代码,会依次弹出 3 个直方图窗口,清晰展示不同方式的绘制效果。如果需要调整图片路径、区间数等参数,注释里都标注了修改位置,新手也能轻松上手~

相关推荐
zyq99101_11 小时前
蓝桥杯刷题算法实战解析
数据结构·python·算法·蓝桥杯
sali-tec1 小时前
C# 基于OpenCv的视觉工作流-章39-FL特征匹配
图像处理·人工智能·opencv·算法·计算机视觉
好家伙VCC2 小时前
# 发散创新:用 Rust构建高并发虚拟世界引擎核心模块在当今游戏开发与元宇宙构建中,**虚拟世界的性能瓶颈往往不是图形渲染,而是底
java·开发语言·python·rust·图形渲染
超级璐璐2 小时前
fast-livo2修改笔记
笔记
IT19952 小时前
计算机理论文档阅读笔记-MQTT vs WebSocket
笔记·websocket·网络协议
for_syq2 小时前
trace抓取工具
android·python
猹叉叉(学习版)2 小时前
【ASP.NET CORE】 14. RabbitMQ、洋葱架构
笔记·后端·架构·c#·rabbitmq·asp.net·.netcore
Pyeako2 小时前
基于Qt和PaddleOCR的工业视觉识别报警系统开发
人工智能·python·深度学习·数码相机·opencv·ocr·pyqt5
左左右右左右摇晃2 小时前
JVM 整理(四) 堆
jvm·笔记