opencv的直方图

理解并运用 OpenCV 中的图像直方图 📊🖼️

图像直方图是计算机视觉和图像处理中一种基本且强大的工具,它提供了图像像素强度分布的图形化表示。OpenCV 作为一个全面的计算机视觉库,内置了计算和可视化直方图的强大功能。本文将深入探讨直方图的概念、其在 OpenCV 中的实现以及一些常见的应用场景。


什么是图像直方图?🤔

图像直方图是一个统计图表,显示了图像中每个强度级别(或颜色级别)的像素数量。对于灰度图像,直方图会显示从 0(黑色)到 255(白色)每个灰度值出现的频率。对于彩色图像,可以为每个颜色通道(例如 BGR 或 HSV 的各个通道)分别计算直方图,或者计算组合的颜色直方图。

直方图可以帮助我们理解:

  • 图像的亮度与对比度:直方图的分布可以揭示图像是偏暗、偏亮,还是对比度良好。
  • 颜色分布:在彩色图像中,可以了解哪些颜色占主导地位。
  • 阈值选择:直方图的波谷通常是选择分割阈值的良好指示。
  • 图像相似性:比较两张图像的直方图可以作为衡量它们内容相似度的一种方法。

OpenCV 中的直方图计算:cv::calcHist 🌟

OpenCV 中计算直方图的核心函数是 cv::calcHist。它非常灵活,可以处理单通道或多通道图像,并允许用户指定各种参数。

函数原型 (C++)

void cv::calcHist(const cv::Mat* images,      // 输入图像数组 (通常只有一个图像)int nimages,                // 输入图像的数量const int* channels,        // 需要计算直方图的通道索引数组cv::InputArray mask,        // 可选的掩码,如果提供,则只计算掩码区域内的像素cv::OutputArray hist,       // 输出的直方图int dims,                   // 直方图的维度 (通常为 1D, 2D, 或 3D)const int* histSize,        // 每个维度上直方图 "bin" (条柱) 的数量数组const float** ranges,       // 每个维度上像素值的范围数组bool uniform = true,        // 直方图的 bin 是否具有统一的大小bool accumulate = false     // 如果为 true,则在多次调用中累积直方图
);

参数详解:

  • images: 指向输入图像的指针数组。即使只处理一张图像,也需要将其地址放入一个数组中。
  • nimages: 输入图像的数量。通常为 1
  • channels: 一个整数数组,指定了要为哪些通道计算直方图。例如,对于灰度图,它是 {0};对于 BGR 彩色图的 B 通道,也是 {0};如果想计算 B 和 G 通道的二维直方图,则是 {0, 1}
  • mask: 一个可选的 cv::Mat 对象。如果非空,它必须是一个与输入图像大小相同的 8 位单通道图像。只有掩码中非零值的对应像素才会被包含在直方图计算中。
  • hist: 输出的直方图,通常是一个 cv::Mat 对象(浮点型)。
  • dims: 直方图的维度。对于单通道灰度图或单个颜色通道,通常是 1
  • histSize: 一个整数数组,表示每个维度上 “bin” 的数量。例如,对于一个灰度图,如果我们想将 0-255 的值分成 256 个 bin,那么 histSize 就是 {256}
  • ranges: 一个浮点型指针数组,定义了每个维度上像素值的范围。例如,对于 8 位灰度图,通常是 {{0.0f, 256.0f}} (注意上限是不包含的)。
  • uniform: 布尔值。如果为 true,则直方图的 bin 具有统一的大小;否则,bin 的大小可以不均匀(通过 ranges 定义)。默认为 true
  • accumulate: 布尔值。如果为 true,则直方图在多次调用 calcHist 时会累积结果到 hist 中,而不是重新开始计算。默认为 false

绘制直方图 🎨

计算出直方图后(它是一个数值数组或矩阵),我们通常需要将其可视化以便更好地理解。OpenCV 本身不直接提供复杂的绘图工具,但我们可以很容易地创建一个表示直方图的图像。

基本步骤如下:

  1. 找到直方图中的最大值,用于归一化。
  2. 创建一个空白图像作为画布。
  3. 对于直方图中的每个 bin,根据其值(可能经过归一化)绘制一条线或一个矩形。

示例:绘制单通道直方图 (C++)

#include <opencv2/opencv.hpp>
#include <iostream>// ... (加载图像到 srcImage) ...cv::Mat grayImage;
if (srcImage.channels() == 3) {cv::cvtColor(srcImage, grayImage, cv::COLORBGR2GRAY);
} else {grayImage = srcImage;
}// 设置直方图参数
int histSizeNum = 256; // bin 的数量
float range[] = {0, 256}; // 像素值范围 (不包括上限)
const float* histRange[] = {range};
bool uniform = true;
bool accumulate = false;
cv::Mat hist;// 计算直方图
cv::calcHist(&grayImage, 1, 0, cv::Mat(), hist, 1, &histSizeNum, histRange, uniform, accumulate);// 创建用于绘制直方图的图像
int hist_w = 512; // 直方图图像宽度
int hist_h = 400; // 直方图图像高度
int bin_w = cvRound((double)hist_w / histSizeNum); // 每个 bin 的宽度cv::Mat histImage(hist_h, hist_w, CV_8UC3, cv::Scalar(20, 20, 20)); // 深灰色背景// 归一化直方图到 [0, histImage.rows]
cv::normalize(hist, hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());// 绘制直方图
for (int i = 1; i < histSizeNum; i++) {cv::line(histImage,cv::Point(bin_w * (i - 1), hist_h - cvRound(hist.at<float>(i - 1))),cv::Point(bin_w * (i), hist_h - cvRound(hist.at<float>(i))),cv::Scalar(200, 200, 200), // 浅灰色线条2, 8, 0);
}// 显示原始图像和直方图
cv::imshow("Source Image", srcImage);
cv::imshow("Grayscale Image", grayImage);
cv::imshow("Histogram", histImage);
cv::waitKey(0);

直方图的应用 🚀

1. 直方图均衡化 (Histogram Equalization)

直方图均衡化是一种通过重新分布图像的像素强度来增强图像对比度的方法。其目标是使直方图尽可能平坦,从而扩展像素强度的动态范围。OpenCV 提供了 cv::equalizeHist() 函数专门用于灰度图像的直方图均衡化。

对于彩色图像,通常的做法是先将图像转换到像 HSV 或 YCrCb 这样的颜色空间,然后对亮度通道(V 或 Y 通道)进行均衡化,最后再转换回 BGR 空间。

2. 直方图比较 (Histogram Comparison)

比较两幅图像的直方图可以用来衡量它们的相似性。这在图像检索、对象识别等领域非常有用。OpenCV 的 cv::compareHist() 函数提供了多种比较方法,例如:

  • 相关性 (Correlation): cv::HISTCMP_CORREL
  • 卡方 (Chi-Square): cv::HISTCMP_CHISQR
  • 交叉点 (Intersection): cv::HISTCMP_INTERSECT
  • 巴氏距离 (Bhattacharyya distance): cv::HISTCMP_BHATTACHARYYA (或 cv::HISTCMP_HELLINGER,它与巴氏距离等价)

3. 直方图反向投影 (Histogram Backprojection)

这是一种基于颜色的图像分割技术。首先,计算你感兴趣的目标对象的颜色直方图(模型直方图)。然后,在输入图像中,对于每个像素,查找其颜色在模型直方图中的概率(或 bin 值)。这个概率图就是反向投影。概率高的区域表明该区域的颜色与目标对象的颜色相似。OpenCV 提供了 cv::calcBackProject() 函数。


总结 ✨

图像直方图不仅是分析图像像素分布的简单工具,更是许多高级图像处理和计算机视觉技术的基础。通过 OpenCV 的 cv::calcHist 函数,我们可以方便地计算直方图,并结合其他函数如 cv::equalizeHistcv::compareHistcv::calcBackProject 来实现各种强大的功能,从图像增强到对象检测。掌握直方图的原理和应用将极大地提升你在图像处理项目中的能力。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/80830.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 内核探秘:从零构建 GPIO 设备驱动程序实战指南

在嵌入式系统开发领域&#xff0c;GPIO&#xff08;通用输入 / 输出&#xff09;作为硬件与软件交互的桥梁&#xff0c;是实现设备控制与数据采集的基础。编写高效、稳定的 GPIO 设备驱动程序&#xff0c;对于发挥硬件性能至关重要。本文将深入剖析 Linux 内核中 GPIO 驱动开发…

嵌入式单片机中STM32F1演示寄存器控制方法

该文以STM32F103C8T6为示例,演示如何使用操作寄存器的方法点亮(关闭LED灯),并讲解了如何调试,以及使用宏定义。 第一:操作寄存器点亮LED灯。 (1)首先我们的目的是操作板子上的LED2灯,对其实现点亮和关闭操作。打开STM32F103C8T6的原理图,找到LED2的位置。 可以看到…

牛客网 NC16407 题解:托米航空公司的座位安排问题

牛客网 NC16407 题解&#xff1a;托米航空公司的座位安排问题 题目分析 解题思路 本题可以采用深度优先搜索(DFS)来解决&#xff1a; 从左上角开始&#xff0c;按行优先顺序遍历每个座位对于每个座位&#xff0c;有两种选择&#xff1a; 选择该座位&#xff08;如果满足条件…

智慧展馆数字孪生平台

2022年进博会上&#xff0c;国家会展中心凭借“数字孪生机器人调度平台”惊艳全球&#xff0c;实现人机协同、虚实联动的智慧运营&#xff1b;2023年天府农博园通过“BIMIoT”技术&#xff0c;贯穿展馆全生命周期管理&#xff0c;成为农业会展的数字化标杆。这些案例背后&#…

胡说八道1---豆包问答总结

用户提问 1 指令&#xff1a;25 - - [21/May/2025:01:35:45 0000] “POST /prod-api/system/base/getList HTTP/1.1” 405 559 “http://192.168.1.109:16380/login” “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 …

C# AOP编程

AOP(面向切片编程的概念我这里就不介绍了&#xff0c;这里先介绍一下C#中的AOP编程框架。 1.AOP的分类 .net下支持AOP的框架很多&#xff0c;搜了一下有&#xff1a;PostSharp、AspectInjector、Fody 、Castle Windsor、Spring.NET、Ninject、Unity等&#xff0c;实现的方式主要…

linux编译安装srs

下载编译运行 git clone https://github.com/ossrs/srs.git cd srs/trunk ./configure --h265on make需要安装 yum install -y patch yum install -y unzip yum install -y tcl编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/s…

EtherNet/IP机柜内解决方案在医疗控制中心智能化的应用潜能和方向分析

引言 在数智化转型浪潮席卷各行各业的今天,医疗领域同样面临着提升运营效率、改善患者体验和加强系统可靠性的多重挑战。Rockwell Automation于2025年5月20日推出的EtherNet/IP机柜内解决方案,为医疗中心的自动化升级提供了一种创新路径。本报告将深入分析这一解决方案的核心…

大模型下载到本地

一、huggingface 方式一 from huggingface_hub import snapshot_downloadlocal_dir "./origin" model_name "Qwen/Qwen2.5-1.5B"# snapshot_download(repo_idmodel_name, cache_dirlocal_dir) model_dir snapshot_download(model_name,cache_dirlocal…

【C++】vector容器实现

目录 一、vector的成员变量 二、vector手动实现 &#xff08;1&#xff09;构造 &#xff08;2&#xff09;析构 &#xff08;3&#xff09;尾插 &#xff08;4&#xff09;扩容 &#xff08;5&#xff09;[ ]运算符重载 5.1 迭代器的实现&#xff1a; &#xff08;6&…

PostgreSQL日常维护

目录 一、PostgreSQL 概述 二、基本使用 &#xff08;一&#xff09;登录数据库 &#xff08;二&#xff09;数据库操作 1. 列出数据库 2. 创建数据库 3. 删除数据库 4. 切换数据库 5. 查看数据库大小 &#xff08;三&#xff09;数据表操作 1. 列出表 2. 创建表 …

广东省省考备考(第十六天5.21)—言语:语句排序题(听课后强化)

错题 解析 对比选项&#xff0c;确定首句。①句介绍目前人类可以利用一些技术手段进入元宇宙&#xff0c;凭借网络重新定义自己&#xff0c;体验一种全新的生活&#xff0c;②句介绍对于多数人来说&#xff0c;首先要弄清楚什么是元宇宙&#xff0c;③句介绍元宇宙是指超越现实…

高并发架构设计之限流

一、引言 再强大的系统&#xff0c;也怕流量短事件内集中爆发&#xff0c;就像银行怕挤兑一样&#xff0c;所以&#xff0c;高并发另一个必不可少的模块就是限流。限流是一种通过控制请求的速率或数量来保护系统免受过载的技术。流控的精髓是限制单位时间内的请求量&#xff0…

视频监控联网系统GB28181协议中设备控制流程详解

文章目录 9.3 设备控制9.3.1 基本要求9.3.2 命令流程9.3.2.1 无应答命令流程 9.3.3 协议接口9.3.3.1 请求命令9.3.3.2 应答命令 智联视频超融合平台介绍 9.3 设备控制 9.3.1 基本要求 控制满足以下基本要求&#xff1a; a) 源设备向目标设备发送控制命令&#xff0c;控制命令…

深入剖析原型模式:原理、实现与应用实践

在软件开发的世界里,设计模式如同建筑师手中的蓝图,为复杂系统的构建提供了行之有效的解决方案。其中,原型模式(Prototype Pattern)作为创建型设计模式的重要一员,以其独特的对象创建方式,在提高代码复用性、增强系统灵活性等方面发挥着关键作用。本文将深入剖析原型模式…

图绘Linux:基础指令脉络阁

目录 Linux命令行介绍 目录操作 ls 目录所含文件信息 ls 常用选项 pwd 在那个目录下 cd 进入目录 mkdir 创建目录 文件操作 touch 创建普通文件 echo向文件写入 cat 输出文件内容 cp 拷贝文件/目录 mv剪切重命名 rm 删除文件/目录 查找 * 匹配符 man 查找指令 …

数据分析 —— 数据预处理

一、什么是数据预处理 数据预处理&#xff08;Data Preprocessing&#xff09;是数据分析和机器学习中至关重要的步骤&#xff0c;旨在将原始数据转换为更高质量、更适合分析或建模的形式。由于真实世界的数据通常存在不完整、不一致、噪声或冗余等问题&#xff0c;预处理可以…

【Redis】哨兵(Sentinel)机制

文章目录 1. Redis Sentinel的概念1.1 基本概念1.2 引出高可用 2. Redis Sentinel的部署&#xff08;基于docker&#xff09;2.1 部署2.2 验证2.3 选举流程 Redis 的主从复制模式下&#xff0c;⼀旦主节点由于故障不能提供服务&#xff0c;需要人工进行主从切换&#xff0c;同时…

初识Linux · 五种IO模型和非阻塞IO

目录 前言&#xff1a; 五种IO模型 什么是IO IO模型 非阻塞IO 前言&#xff1a; 前文我们已经将网络的基本原理介绍完了&#xff0c;都是通过围绕TCP/IP四层协议&#xff0c;将应用层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层全部介绍完毕&#xff0c…

Node.js 24发布:性能与安全双提升

在科技的迅速发展中&#xff0c;Node.js作为一个备受青睐的开源跨平台Java运行环境&#xff0c;近日迎来了其24.0版本的正式发布。此次更新不仅承诺提升性能和安全性&#xff0c;还为开发者提供了更为顺畅的开发体验&#xff0c;值得我们深入探讨。 Node.js 24.0的最大亮点之一…