opencv对直方图的计算和绘制

news2025/1/19 16:11:23

【欢迎关注编码小哥,学习更多实用的编程方法和技巧】

1、直方图的计算

cv::calcHist 是 OpenCV 中用于计算图像直方图的函数。它可以处理多通道图像,并通过指定图像、通道、掩膜、直方图大小和范围等参数来生成直方图。

函数原型

void cv::calcHist(
     const Mat* images, 
     int nimages, 
     const int* channels, 
     InputArray mask, 
     OutputArray hist, 
     int dims, 
     const int* histSize, 
     const float** ranges, 
     bool uniform = true, 
     bool accumulate = false)

参数

  • images: 要计算的原图,类型为 const Mat*,表示一个图像数组。
  • nimages: 图像数组的大小,类型为 int
  • channels: 指定计算的通道,类型为 const int*,表示一个通道数组。每个通道对应一个图像。
  • mask: 用于计算特定区域的掩膜,类型为 InputArray,表示一个图像或矩形区域。
  • hist: 输出的直方图,类型为 OutputArray,表示一个多维数组。
  • dims: 直方图的维度,类型为 int,表示直方图的维度。
  • histSize: 直方图的大小,类型为 const int*,表示一个大小数组,每个大小对应一个维度。
  • ranges: 像素值范围,类型为 const float**,表示一个范围数组,每个范围对应一个维度。
  • uniform: 是否使用均匀的直方图,类型为 bool,默认为 true
  • accumulate: 是否累积计算结果,类型为 bool,默认为 false

返回值

  • 无返回值,该函数直接修改输出直方图。
  • #include <opencv2/opencv.hpp>
    
    int main() {
        // 读取图像
        cv::Mat img = cv::imread("image.jpg");
    
        // 计算灰度图直方图
        cv::Mat gray;
        cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
        int histSize = 256;
        float range[] = {0, 256};
        cv::Mat hist;
        cv::calcHist(&gray, 1, &0, cv::Mat(), hist, 1, &histSize, &range);
    
        // 计算彩色图直方图
        int channels[] = {0, 1, 2};
        cv::Mat hist_b, hist_g, hist_r;
        cv::calcHist(&img, 1, channels, cv::Mat(), hist_b, 1, &histSize, &range);
        cv::calcHist(&img, 1, channels + 1, cv::Mat(), hist_g, 1, &histSize, &range);
        cv::calcHist(&img, 1, channels + 2, cv::Mat(), hist_r, 1, &histSize, &range);
    
        // 绘制直方图
        cv::Mat hist_img(256, 256, CV_8UC3);
        cv::normalize(hist, hist, 0, hist_img.rows, cv::NORM_MINMAX);
        for (int i = 0; i < histSize; i++) {
            cv::line(hist_img, cv::Point(i, hist_img.rows), cv::Point(i, hist_img.rows - cvRound(hist.at<float>(i))), cv::Scalar(255, 0, 0));
        }
        cv::imshow("Histogram", hist_img);
        cv::waitKey(0);
        cv::destroyAllWindows();
    
        return 0;
    }

  • cv::calcHist 函数可以处理多通道图像,但必须指定计算的通道。
  • cv::calcHist 函数可以计算多个直方图,但必须具有相同的尺寸和类型。
  • cv::calcHist 函数可以累积计算结果,但必须指定输出直方图。

2、一维直方图的绘制

一维直方图是一种常见的数据可视化方法,用于显示数据的分布情况。在 OpenCV 中,可以使用以下步骤绘制一维直方图:

  1. 计算直方图:使用 cv::calcHist 函数计算图像的直方图。
  2. 归一化直方图:使用 cv::normalize 函数将直方图归一化到指定的范围。
  3. 绘制直方图:使用 cv::line 函数绘制直方图。
#include <opencv2/opencv.hpp>

int main() {
    // 读取图像
    cv::Mat img = cv::imread("image.jpg");

    // 计算灰度图直方图
    cv::Mat gray;
    cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
    int histSize = 256;
    float range[] = {0, 256};
    cv::Mat hist;
    cv::calcHist(&gray, 1, &0, cv::Mat(), hist, 1, &histSize, &range);

    // 归一化直方图
    cv::Mat hist_norm;
    cv::normalize(hist, hist_norm, 0, 256, cv::NORM_MINMAX);

    // 绘制直方图
    cv::Mat hist_img(256, 256, CV_8UC3);
    for (int i = 0; i < histSize; i++) {
        cv::line(hist_img, cv::Point(i, hist_img.rows), cv::Point(i, hist_img.rows - cvRound(hist_norm.at<float>(i))), cv::Scalar(255, 0, 0));
    }

    // 显示直方图
    cv::imshow("Histogram", hist_img);
    cv::waitKey(0);
    cv::destroyAllWindows();

    return 0;
}

 在这个示例中,我们首先读取一张图像,然后计算其灰度图直方图。接着,我们将直方图归一化到 0-256 的范围,然后绘制直方图。最后,我们显示直方图。

注意:在绘制直方图时,我们使用 cv::line 函数绘制每个直方图条。我们将直方图条的高度设置为 hist_img.rows - cvRound(hist_norm.at<float>(i)),以便直方图条的高度与直方图值成比例。

如果想绘制彩色图直方图,可以使用以下代码:

// 计算彩色图直方图
int channels[] = {0, 1, 2};
cv::Mat hist_b, hist_g, hist_r;
cv::calcHist(&img, 1, channels, cv::Mat(), hist_b, 1, &histSize, &range);
cv::calcHist(&img, 1, channels + 1, cv::Mat(), hist_g, 1, &histSize, &range);
cv::calcHist(&img, 1, channels + 2, cv::Mat(), hist_r, 1, &histSize, &range);

// 归一化直方图
cv::Mat hist_b_norm, hist_g_norm, hist_r_norm;
cv::normalize(hist_b, hist_b_norm, 0, 256, cv::NORM_MINMAX);
cv::normalize(hist_g, hist_g_norm, 0, 256, cv::NORM_MINMAX);
cv::normalize(hist_r, hist_r_norm, 0, 256, cv::NORM_MINMAX);

// 绘制直方图
cv::Mat hist_img(256, 256, CV_8UC3);
for (int i = 0; i < histSize; i++) {
    cv::line(hist_img, cv::Point(i, hist_img.rows), cv::Point(i, hist_img.rows - cvRound(hist_b_norm.at<float>(i))), cv::Scalar(255, 0, 0));
    cv::line(hist_img, cv::Point(i, hist_img.rows), cv::Point(i, hist_img.rows - cvRound(hist_g_norm.at<float>(i))), cv::Scalar(0, 255, 0));
    cv::line(hist_img, cv::Point(i, hist_img.rows), cv::Point(i, hist_img.rows - cvRound(hist_r_norm.at<float>(i))), cv::Scalar(0, 0, 255));
}

在这个示例中,我们计算彩色图的直方图,然后归一化直方图。接着,我们绘制直方图,每个通道使用不同的颜色。

3、多维直方图的绘制 

2D直方图是一种用于表示两个变量之间关系的数据可视化方法。在 OpenCV 中,可以使用以下步骤绘制 2D 直方图:

  1. 计算直方图:使用 cv::calcHist 函数计算图像的直方图。
  2. 归一化直方图:使用 cv::normalize 函数将直方图归一化到指定的范围。
  3. 绘制直方图:使用 cv::imshow 函数显示直方图。

以下是示例代码:

#include <opencv2/opencv.hpp>

int main() {
    // 读取图像
    cv::Mat img = cv::imread("image.jpg");

    // 计算 2D 直方图
    int channels[] = {0, 1};
    int histSize[] = {256, 256};
    float range[] = {0, 256, 0, 256};
    cv::Mat hist;
    cv::calcHist(&img, 1, channels, cv::Mat(), hist, 2, histSize, range);

    // 归一化 2D 直方图
    cv::Mat hist_norm;
    cv::normalize(hist, hist_norm, 0, 256, cv::NORM_MINMAX);

    // 绘制 2D 直方图
    cv::Mat hist_img(256, 256, CV_8UC3);
    for (int i = 0; i < 256; i++) {
        for (int j = 0; j < 256; j++) {
            int index = i * 256 + j;
            cv::Vec3b color = cv::Vec3b(i, j, 0);
            hist_img.at<cv::Vec3b>(i, j) = color * (hist_norm.at<float>(index) / 256.0f);
        }
    }

    // 显示 2D 直方图
    cv::imshow("2D Histogram", hist_img);
    cv::waitKey(0);
    cv::destroyAllWindows();

    return 0;
}

 在这个示例中,我们计算 2D 直方图,然后归一化 2D 直方图。接着,我们绘制 2D 直方图,每个像素的颜色根据 2D 直方图值计算。

注意:在绘制 2D 直方图时,我们使用 cv::Vec3b 类型表示颜色,每个颜色通道的值根据 2D 直方图值计算。

如果想绘制 3D 直方图,可以使用以下代码:

// 计算 3D 直方图
int channels[] = {0, 1, 2};
int histSize[] = {256, 256, 256};
float range[] = {0, 256, 0, 256, 0, 256};
cv::Mat hist;
cv::calcHist(&img, 1, channels, cv::Mat(), hist, 3, histSize, range);

// 归一化 3D 直方图
cv::Mat hist_norm;
cv::normalize(hist, hist_norm, 0, 256, cv::NORM_MINMAX);

// 绘制 3D 直方图
cv::Mat hist_img(256, 256, CV_8UC3);
for (int i = 0; i < 256; i++) {
    for (int j = 0; j < 256; j++) {
        for (int k = 0; k < 256; k++) {
            int index = i * 256 * 256 + j * 256 + k;
            cv::Vec3b color = cv::Vec3b(i, j, k);
            hist_img.at<cv::Vec3b>(i, j) = color * (hist_norm.at<float>(index) / 256.0f);
        }
    }
}

// 显示 3D 直方图
cv::imshow("3D Histogram", hist_img);
cv::waitKey(0);
cv::destroyAllWindows();

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

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

相关文章

【实践】操作系统智能助手OS Copilot新功能测评

一、引言 数字化加速发展&#xff0c;尤其人工智能的发展速度越来越快。操作系统智能助手成为提升用户体验与操作效率的关键因素。OS Copilot借助语言模型&#xff0c;人工智能等&#xff0c;对操作系统的自然语言交互操作 推出很多功能&#xff0c;值得开发&#xff0c;尤其运…

人物一致性训练测评数据集

1.Pulid 训练:由1.5M张从互联网收集的高质量人类图像组成,图像标题由blip2自动生成。 测试:从互联网上收集了一个多样化的肖像测试集,该数据集涵盖了多种肤色、年龄和性别,共计120张图像,我们称之为DivID-120,作为补充资源,还使用了最近开源的测试集Unsplash-50,包含…

【深度学习实战】kaggle 自动驾驶的假场景分类

本次分享我在kaggle中参与竞赛的历程&#xff0c;这个版本是我的第一版&#xff0c;使用的是vgg。欢迎大家进行建议和交流。 概述 判断自动驾驶场景是真是假&#xff0c;训练神经网络或使用任何算法来分类驾驶场景的图像是真实的还是虚假的。 图像采用 RGB 格式并以 JPEG 格式…

网络编程 | UDP套接字通信及编程实现经验教程

1、UDP基础 传输层主要应用的协议模型有两种&#xff0c;一种是TCP协议&#xff0c;另外一种则是UDP协议。在上一篇博客文章中&#xff0c;已经对TCP协议及如何编程实现进行了详细的梳理讲解&#xff0c;在本文中&#xff0c;主要讲解与TCP一样广泛使用了另一种协议&#xff1a…

【Linux】线程全解:概念、操作、互斥与同步机制、线程池实现

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长&#xff0c;行则将至 目录 &#x1f4da;一、线程概念 &#x1f4d6; 回顾进程 &#x1f4d6; 引入线程 &#x1f4d6; 总结 &a…

掌握未来:从零开始学习生成式AI大模型!

随着人工智能技术的飞速发展&#xff0c;生成式AI大模型已成为当今科技领域的热点。从文本生成、图像创作到音乐创作&#xff0c;生成式AI大模型在各个领域展现出惊人的潜力。本文将带领大家从零开始&#xff0c;逐步学习生成式AI大模型&#xff0c;掌握未来的关键技术。 一、生…

多肽合成 -- 液相合成(liquid-phase peptide synthesis (LPPS))

液相合成的定义 液相合成&#xff08;Solution Synthesis&#xff09;是指在液体介质中进行的化学合成反应&#xff0c;是化学合成中一种基本且重要的方法。它涉及到将反应物溶解在溶剂中&#xff0c;在一定的温度、压力和其他反应条件下进行化学反应&#xff0c;从而生成所需的…

第23篇 基于ARM A9处理器用汇编语言实现中断<五>

Q&#xff1a;怎样修改HPS Timer 0定时器产生的中断周期&#xff1f; A&#xff1a;在上一期实验的基础上&#xff0c;可以修改按键中断服务程序&#xff0c;实现红色LED上的计数值递增的速率&#xff0c;主程序和其余代码文件不用修改。 实现以下功能&#xff1a;按下KEY0…

ChatGPT大模型极简应用开发-CH1-初识 GPT-4 和 ChatGPT

文章目录 1.1 LLM 概述1.1.1 语言模型和NLP基础1.1.2 Transformer及在LLM中的作用1.1.3 解密 GPT 模型的标记化和预测步骤 1.2 GPT 模型简史&#xff1a;从 GPT-1 到 GPT-41.2.1 GPT11.2.2 GPT21.2.3 GPT-31.2.4 从 GPT-3 到 InstructGPT1.2.5 GPT-3.5、Codex 和 ChatGPT1.2.6 …

2025春秋杯冬季赛 day1 crypto

文章目录 通往哈希的旅程小哈斯RSA1ez_rsa 通往哈希的旅程 根据提示推断是哈希函数&#xff0c;ai一下&#xff0c;推测大概率是一个sha1&#xff0c;让ai写一个爆破脚本即可 import hashlib# 给定目标 SHA-1 哈希值 target_hash "ca12fd8250972ec363a16593356abb1f3cf…

广播网络实验

1 实验内容 1、构建星性拓扑下的广播网络,实现hub各端口的数据广播,验证网络的连通性并测试网络效率 2、构建环形拓扑网络,验证该拓扑下结点广播会产生数据包环路 2 实验流程与结果分析 2.1 实验环境 ubuntu、mininet、xterm、wireshark、iperf 2.2 实验方案与结果分析…

RustDesk ID更新脚本

RustDesk ID更新脚本 此PowerShell脚本自动更新RustDesk ID和密码&#xff0c;并将信息安全地存储在Bitwarden中。 特点 使用以下选项更新RustDesk ID&#xff1a; 使用系统主机名生成一个随机的9位数输入自定义值 为RustDesk生成新的随机密码将RustDesk ID和密码安全地存储…

JavaEE之常见的锁策略

前面我们学习过线程不安全问题&#xff0c;我们通过给代码加锁来解决线程不安全问题&#xff0c;在生活中我们也知道有很多种类型的锁&#xff0c;同时在代码的世界当中&#xff0c;也对应着很多类型的锁&#xff0c;今天我们对锁一探究竟&#xff01; 1. 常见的锁策略 注意: …

数字图像处理:实验二

任务一&#xff1a; 将不同像素&#xff08;32、64和256&#xff09;的原图像放大为像素大 小为1024*1024的图像&#xff08;图像自选&#xff09; 要求&#xff1a;1&#xff09;输出一幅图&#xff0c;该图包含六幅子图&#xff0c;第一排是原图&#xff0c;第 二排是对应放大…

WEB渗透技术研究与安全防御

目录 作品简介I IntroductionII 1 网络面临的主要威胁1 1.1 技术安全1 2 分析Web渗透技术2 2.1 Web渗透技术的概念2 2.2 Web漏洞产生的原因2 2.3 注入测试3 2.3.1 注入测试的攻击流程3 2.3.2 进行一次完整的Sql注入测试4 2.3.3 Cookie注入攻击11 3 安全防御方案设计…

使用 Thermal Desktop 进行航天器热分析

介绍 将航天器保持在运行温度下的轨道上是一个具有挑战性的问题。航天器需要处理太空非常寒冷的背景温度&#xff0c;同时还要管理来自内部组件、地球反照率和太阳辐射的高热负荷。航天器在轨道上可以进行的各种轨道机动使解决这个问题变得更加复杂。 Thermal Desktop 是一款…

乘联会:1月汽车零售预计175万辆 环比暴跌33.6%

快科技1月18日消息&#xff0c;据乘联会的初步推算&#xff0c;2025年1月狭义乘用车零售总市场规模预计将达到约175万辆左右。与去年同期相比&#xff0c;这一数据呈现了-14.6%的同比下降态势&#xff1b;而相较于上个月&#xff0c;则出现了-33.6%的环比暴跌情况。 为了更清晰…

SQL 递归 ---- WITH RECURSIVE 的用法

SQL 递归 ---- WITH RECURSIVE 的用法 开发中遇到了一个需求&#xff0c;传递一个父类id&#xff0c;获取父类的信息&#xff0c;同时获取其所有子类的信息。 首先想到的是通过程序中去递归查&#xff0c;但这种方法着实孬了一点&#xff0c;于是想&#xff0c;sql能不能递归查…

【机器学习实战入门项目】使用深度学习创建您自己的表情符号

深度学习项目入门——让你更接近数据科学的梦想 表情符号或头像是表示非语言暗示的方式。这些暗示已成为在线聊天、产品评论、品牌情感等的重要组成部分。这也促使数据科学领域越来越多的研究致力于表情驱动的故事讲述。 随着计算机视觉和深度学习的进步&#xff0c;现在可以…

windows 搭建flutter环境,开发windows程序

环境安装配置&#xff1a; 下载flutter sdk https://docs.flutter.dev/get-started/install/windows 下载到本地后&#xff0c;随便找个地方解压&#xff0c;然后配置下系统环境变量 编译windows程序本地需要安装vs2019或更新的开发环境 主要就这2步安装后就可以了&#xff0…