OpenCV 二维直方图实战:用 cv.calcHist 与 np.histogram2d 计算并可视化 HSV 色彩直方图

发布时间:2026/10/28 18:26:58

OpenCV 二维直方图实战:用 cv.calcHist 与 np.histogram2d 计算并可视化 HSV 色彩直方图 OpenCV 二维直方图实战用 cv.calcHist 与 np.histogram2d 计算并可视化 HSV 色彩直方图【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv本文围绕 OpenCV 教程《Histograms - 3 : 2D Histograms》展开系统讲解如何计算和绘制二维直方图2D Histogram。读完本篇你将掌握三个核心技能用cv.calcHist()对 HSV 图像同时统计 Hue色相与 Saturation饱和度两个特征用np.histogram2d()在纯 NumPy 环境中完成同样的统计以及三种不同的二维直方图可视化方案——cv.imshow()、Matplotlib 的imshow()和带真实色彩标注的OpenCV 示例风格彩色直方图。这些能力是理解后续直方图反向投影Histogram Back-Projection等主题的基础。为什么需要二维直方图在前一篇教程一维直方图中我们只考虑单一特征——像素的灰度强度值因此得到一维直方图。而二维直方图同时考虑两个特征最典型的应用是颜色直方图color histogram每个像素有两个特征即 HSV 颜色空间中的 Hue色相与 Saturation饱和度值。一维灰度直方图只能回答图像中什么灰度等级的像素多无法回答图像中是什么颜色占主导。而色彩信息天然分布在 H 与 S 两个维度上必须用二维统计才能完整表达。例如在教程使用的示例图像home.jpg中可以看到 H ≈ 100、S ≈ 200 附近有明显高值峰对应天空的蓝色另一处 H ≈ 25、S ≈ 100 附近的峰对应宫殿的黄色。这种坐标位置 → 实际颜色的对应关系正是二维直方图的核心价值也可以用 GIMP 等图像编辑工具对原图取色加以验证。用 cv.calcHist 计算二维直方图OpenCV 中计算二维直方图与一维直方图使用同一个函数cv.calcHist()区别仅在于参数。对于颜色直方图需要先把图像从 BGR 转换到 HSV一维直方图时是从 BGR 转到 Grayscale。参数修改方式如下channels [0, 1]—— 因为需要同时处理 H 平面HSV 的第 0 通道和 S 平面第 1 通道bins [180, 256]—— H 平面取 180 个 binS 平面取 256 个 binrange [0, 180, 0, 256]—— OpenCV 中 8 位图像 HSV 转换后 Hue 的取值范围是 0–180Saturation 的取值范围是 0–256。完整代码import numpy as np import cv2 as cv img cv.imread(home.jpg) assert img is not None, file could not be read, check with os.path.exists() hsv cv.cvtColor(img, cv.COLOR_BGR2HSV) hist cv.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])几点说明第 1 个参数[hsv]是图像列表列表形式是为了兼容多图像统计第 2 个参数[0, 1]指定参与统计的通道索引0是 H、1是 S第 3 个参数None表示不使用掩码统计全图。传入掩码时只统计掩码非零区域的像素第 4 个参数[180, 256]是各维度 bin 数第 5 个参数[0, 180, 0, 256]是对应各维度的取值范围按维度顺序依次拼接。返回结果hist是一个180 × 256 的二维数组hist[h, s]表示色相落在第 h 个 bin、饱和度落在第 s 个 bin 的像素个数。这一参数模式在仓库官方教程代码中有真实印证。官方反向投影示例 calcBackProject_Demo2.py 中正是用同样的双通道 双维度 bins 拼接 range写法从 HSV 图像提取颜色直方图该示例使用更细粒度的h_bins30、s_bins32以减少计算量# samples/python/tutorial_code/Histograms_Matching/back_projection/calcBackProject_Demo2.py h_bins 30 s_bins 32 histSize [h_bins, s_bins] h_range [0, 180] s_range [0, 256] ranges h_range s_range # Concat list channels [0, 1] # Get the Histogram and normalize it hist cv.calcHist([hsv], channels, mask, histSize, ranges, accumulateFalse) cv.normalize(hist, hist, alpha0, beta255, norm_typecv.NORM_MINMAX) # Get Backprojection backproj cv.calcBackProject([hsv], channels, hist, ranges, scale1)从这段源码可以确认二维 HSV 直方图是反向投影cv.calcBackProject的直接输入——先统计出目标区域的直方图再用它生成反向投影图做相似区域检索。这正是本文档末尾提到的对后续主题有用的具体落点。用 np.histogram2d 在 NumPy 中计算NumPy 提供了专用函数np.histogram2d()对应一维时使用的np.histogram()可以在不依赖 OpenCV 直方图接口的前提下完成同样的统计import numpy as np import cv2 as cv from matplotlib import pyplot as plt img cv.imread(home.jpg) assert img is not None, file could not be read, check with os.path.exists() hsv cv.cvtColor(img, cv.COLOR_BGR2HSV) hist, xbins, ybins np.histogram2d(h.ravel(), s.ravel(), [180, 256], [[0, 180], [0, 256]])参数含义原文档逐一点明第 1 个参数H 平面数据h.ravel()把 H 通道展开为一维数组第 2 个参数S 平面数据s.ravel()第 3 个参数每个维度的 bin 数[180, 256]第 4 个参数每个维度的取值范围[[0, 180], [0, 256]]。函数返回三个值hist为统计结果形状为(len(xbins), len(ybins))的二维数组注意 NumPy 约定行轴对应第一个输入 xxbins、ybins是各维度的 bin 边界数组。与cv.calcHist相比NumPy 版本的直方图数值语义一致但绘制时需要自行处理轴方向与边界OpenCV 版本则与后续cv.calcBackProject、cv.compareHist等接口天然兼容工程链路上更顺。小提示若用np.split(hsv, 3, axis2)拆出h, s, v可避免在示例代码中手写hsv[:,:,0]、hsv[:,:,1]这类索引。二维直方图的三种可视化方法二维直方图的结果是 180 × 256 的矩阵怎么画直接影响可读性。教程给出了三种方案按信息量递增排列。方法一直接使用 cv.imshow()结果是一个 180 × 256 的二维数组可以直接当作灰度图像显示cv.imshow(2D Histogram, hist) cv.waitKey(0)它的局限在于显示的是灰度图除非你熟悉不同颜色对应的 Hue 数值区间否则看不出图中峰值代表什么颜色。优点是零依赖、适合在无 GUI 绘图库的环境如嵌入式、服务器快速查看直方图形态。方法二使用 Matplotlib推荐matplotlib.pyplot.imshow()可以配合不同的 color map 来绘制二维直方图能更直观地反映像素密度分布。同样地它无法直接告诉你峰值处是什么颜色除非你知道各 Hue 值对应的色相但教程作者明确表示更推荐这种方式——简单且效果好。import numpy as np import cv2 as cv from matplotlib import pyplot as plt img cv.imread(home.jpg) assert img is not None, file could not be read, check with os.path.exists() hsv cv.cvtColor(img, cv.COLOR_BGR2HSV) hist cv.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256]) plt.imshow(hist, interpolationnearest) plt.show()上面第一张配图2dhist_matplotlib.jpg即为该方法的输出。使用时的注意点插值标志应设为interpolationnearest以避免双线性插值模糊 bin 边界得到更准确的密度呈现。该图的坐标语义需要记住X 轴是 S 值0–255Y 轴是 Hue0–179。图中可见两类显著高密度区H ≈ 100、S ≈ 200 附近的蓝色天空以及 H ≈ 25、S ≈ 100 附近的黄色宫殿主体。方法三OpenCV 示例风格——输出彩色直方图教程提到 OpenCV-Python 示例中有一个samples/python/color_histogram.py运行后可看到直方图中带有真实色彩标注即color coded histogram。需要说明的是在当前仓库版本中该文件已不再位于 samples/python/ 目录下仓库的 Python 示例已重组为 tutorial_code/ 目录结构但教程对其实现原理的描述依然有参考价值作者先创建了一张 HSV 颜色映射图color map再将其转换为 BGR然后把直方图图像与该颜色映射图逐像素相乘。同时使用若干预处理步骤去除孤立的小像素点最终得到漂亮的直方图。这种方法的精髓可以概括为三步构造一张与直方图同尺寸180 × 256的色谱图横坐标位置 s 的像素取饱和度 s、纵坐标位置 h 的像素取色相 h整体转换到 BGR将归一化后的直方图与该色谱图逐元素相乘使每个 bin 位置呈现密度 × 颜色用形态学运算如开运算剔除孤立的微小亮点减少视觉噪声。教程给出的同一输入图像的输出结果如下可以清晰地看到蓝色、黄色的存在以及因棋盘格产生的白色成分如果你想自己复现这套效果核心骨架大致是import numpy as np import cv2 as cv img cv.imread(home.jpg) assert img is not None, file could not be read, check with os.path.exists() hsv cv.cvtColor(img, cv.COLOR_BGR2HSV) hist cv.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256]) cv.normalize(hist, hist, 0, 255, cv.NORM_MINMAX) hist_img np.uint8(hist) # 构造与直方图同尺寸的 HSV 色谱图S 随列变化H 随行变化 color_map np.zeros((180, 256, 3), dtypenp.uint8) color_map[:, :, 0] np.arange(256)[np.newaxis, :] # H 固定为 0 示例 color_map[:, :, 1] 255 # 实际应让 H 随行 h 变化 color_map[:, :, 2] 0 # 正确的完整做法H 平面 行索引 hS 平面 列索引 s hue_plane np.tile(np.arange(180)[:, np.newaxis], (1, 256)) sat_plane np.tile(np.arange(256)[np.newaxis, :], (180, 1)) color_map np.dstack((hue_plane, sat_plane, np.full((180, 256), 128))) color_map_bgr cv.cvtColor(color_map, cv.COLOR_HSV2BGR) # 直方图 × 颜色映射再去除孤立点 colored_hist (hist_img[..., np.newaxis] * color_map_bgr // 255) colored_hist cv.medianBlur(colored_hist, 3) cv.imshow(Color Histogram, colored_hist) cv.waitKey(0)参数速查与源码印证把本文涉及的参数集中对照如下方便直接复制到项目中项目cv.calcHistnp.histogram2d输入数据[hsv]图像列表h.ravel(),s.ravel()两个一维数组通道/维度[0, 1]H、S第 1 个参数对应 H第 2 个对应 Sbin 数[180, 256][180, 256]取值范围[0, 180, 0, 256]拼接形式[[0, 180], [0, 256]]嵌套形式返回形状180 × 256 矩阵(len(xbins), len(ybins))矩阵 两个边界数组再强调两条易错点Hue 的上界是 180 而不是 360。OpenCV 的 8 位图像 HSV 转换中H 被压缩到 0–180 区间cv.COLOR_BGR2HSV的约定这与度制色相 0–360 相差 2 倍range 写错会导致统计结果整体为零bins 与 range 必须按维度顺序一一对应。[180, 256]与[0, 180, 0, 256]中前 180 属于 H后 256 属于 S顺序颠倒会静默地得到错误直方图而不报错。一维直方图教程的官方代码 calcHist_Demo.py 展示了histSize、histRange、accumulate等参数在单通道场景下的用法与本文的双通道用法一脉相承单通道时channels[0]、bins[256]、range(0,256)双通道时维度翻倍范围拼接为[0, 180, 0, 256]。小结与延伸本篇覆盖的内容可以归纳为一句话BGR 转 HSV → 双通道双维度统计 → 矩阵结果可视化。具体落点统计入口cv.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])或np.histogram2d(h.ravel(), s.ravel(), [180, 256], [[0,180],[0,256]])可视化三法cv.imshow()最快、matplotlib.pyplot.imshow()推荐记得interpolationnearest、彩色映射相乘法信息量最大结果解读X 轴为 S、Y 轴为 H结合 Hue 数值区间判断颜色归属。在此基础上可以继续深入仓库中的相关示例反向投影 calcBackProject_Demo1.py 与 calcBackProject_Demo2.py二维直方图 → 反向投影 → 相似区域检索、直方图比较 compareHist_Demo.pycv.compareHist的多种度量方法、以及直方图均衡化 EqualizeHist_Demo.py。教程系列的完整入口见 py_tutorials 目录。【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/28 18:26:38

选课系统课设全指南:从数据库设计到并发控制与答辩避坑

简介:这是一套面向高校学生网上选课场景的Java毕业设计项目,采用Spring Boot与Vue的前后端分离架构,覆盖教室管理、老师管理、课程管理、教学计划管理、选课管理、成绩管理、学生管理等功能模块,可有效解决传统人工选课信息维护困…

2026/10/25 0:08:22

SpringJDBC条件进阶:JdbcTemplate动态查询与参数安全实践

1. 先理解“条件进阶”到底在解决什么问题SpringJDBC 是 Spring 框架里处理数据库访问的基础方案,很多项目在没有引入 MyBatis、JPA 这类重量级 ORM 框架时,都会直接用它来操作数据库。JDBC 本身写起来啰嗦,SpringJDBC 通过JdbcTemplate把连接…

2026/10/26 2:52:01

Python GIL深度解析:多线程为何难用满CPU?多进程实战指南

想先问一个很现实的问题:你写过这样的代码吗——在一个 4 核机器上,用ThreadPoolExecutor(max_workers4)开了 4 个线程做纯计算任务,满心期待 CPU 能直接在 4 个核上并行运行。结果跑起来之后打开任务管理器,CPU 总占用率只有 110…

2026/10/28 18:23:55

Delphi 12 安装 Indy 10.6.3.3 与阻塞式 Socket 实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/28 18:23:55

STM32时钟系统深度解析:RCC寄存器配置与72MHz实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/28 18:18:53

验证MYSQL安装成功+安装的前提

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/28 14:42:12

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/28 15:28:56

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/28 3:32:29

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/28 0:02:13

Python股票自动交易系统源码解析:从行情获取到风控的完整链路

简介:这份资源是面向高校计算机、金融相关专业毕业设计场景的完整项目源码包,主题为基于Python的股票自动交易系统,适合需要完成毕设选题、课程设计或自学金融量化交易开发的学生与开发者参考。压缩包共收录687个文件,整体约14.93…

2026/10/28 0:02:13

视酷酷信IM源码部署指南:Java 17+MySQL 8.0.33实战配置

简介:这是一套2024年亲测可部署的视酷酷信IM即时通讯系统源码,面向具备Java、OC、C#及Vue开发能力的技术人员,解决私有化即时通讯平台快速搭建与二次定制需求,尤其适用于需集成商城、保障数据主权的中小型企业或独立开发者。资源共…

2026/10/28 0:02:13

Python爬取百度迁徙数据:接口解析、批量采集与避坑指南

简介:这份资源是一个用Python爬取百度迁徙数据的脚本压缩包,面向具备Python基础、希望入门网络爬虫与数据解析的开发者,解决按日期获取全国热门城市人口迁徙数据的问题。包内共1个文件,为单个py脚本,压缩包约1KB&#…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑