当前位置: 首页 > news >正文

Ubuntu系统VScode实现opencv(c++)图像一维直方图

前言

在数字图像处理领域,直方图是一种极为重要的工具,而图像的一维直方图更是其中的基础与核心。一维直方图以简洁而直观的方式,将图像中像素的灰度值分布情况呈现出来,让我们能够快速了解图像的整体亮度、对比度等关键信息。通过对一维直方图的分析,我们可以轻松判断图像是否过亮或过暗,对比度是否合适,进而为后续的图像增强、分割、特征提取等一系列操作提供有力的依据。

直方图概念

实际上,一维直方图就是不同像素值出现频率的统计。如下图:

一维直方图一般是将多通道拆分为单通道,然后统计对应单通道像素出现频率,对于RGB图像来说一般有三个折线。

opencv中已经有相应的函数帮助我们生成直方图的数据,我们先了解每一个参数变量。

calcHist函数

1.函数原型:

void 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 );

 2.参数介绍:

(1)const Mat* images

输入图像数组。通常传入图像的地址(如 &image)。如果传入多个图像,它们必须具有相同的尺寸和通道数。

(2)int nimages

输入图像的数量。如果只有一个图像,传入 1;如果有多个图像,传入图像数组的长度。

(3)const int* channels

对于灰度图像,通常传入 0(表示单通道)。

对于彩色图像(如 BGR),可以传入 0(蓝色通道)、1(绿色通道)或 2(红色通道)。

如果需要同时计算多个通道的直方图,可以传入一个数组(例如,int channels[] = {0, 1} 表示计算蓝色和绿色通道的直方图)。

(4)InputArray mask:

掩码图像,如果传入掩码,直方图仅计算掩码中非零像素对应的值。

(5)OutputArray hist

输出的直方图。直方图是一个一维或多维数组。

(6)int dims

直方图的维度。对于一维直方图(例如,单通道图像),传入 1。对于多维直方图(例如,计算两个通道的联合直方图),传入相应的维度数(如 2)。

(7)const int* histSize

每个维度的直方图大小。对于一维直方图,传入一个整数值(如 256,表示灰度值范围为 0-255)。对于多维直方图,传入一个数组(例如,int histSize[] = {256, 256},表示两个通道的直方图大小均为 256)。

(8)const float** ranges

每个维度的值范围。对于一维直方图,传入一个包含两个值的数组(如 float range[] = {0, 256},表示灰度值范围为 0-255)。对于一维直方图,传入一个包含两个值的数组(如 float range[] = {0, 256},表示灰度值范围为 0-255)。

在了解每一个参数的作用之后就可以开始使用这个函数了。

函数使用 

对于三通道RGB图像,我们做一维的就是提取每个通道的直方图。那么首先就是分离通道,这里应该不用多说,前面已经知道怎么做了。

 vector<Mat> BGR;split(image,BGR);

接下来我们需要定义上述函数的参数,这里多看就会理解了。主要定义的有两个变量,分别是 const int* histSize和const float** ranges

const int bins[] = {256};
float hranges[] = {0,255};
const float* ranges[1] = {hranges};

其实 bins就是横坐标的取值长度,这里的像素是0-255,所以总共有256个灰度等级,而 ranges则是定义像素值范围的,这里之所以这么定义,是因为如果是多通道的,我们直接在ranges中加入另一个通道的范围值,例如这样:

    float h_ranges[] = {0,180};float s_ranges[] = {0,256};const float* ranges[] = {h_ranges,s_ranges};

接下来,定义三个用于接受三个通道直方图的Mat变量;整体代码就是这样:

    vector<Mat> BGR;split(image,BGR);const int bins[] = {256};float hranges[] = {0,255};const float* ranges[1] = {hranges};Mat b_hist,g_hist,r_hist;calcHist(&BGR[0],1,0,Mat(),b_hist,1,bins,ranges);calcHist(&BGR[1],1,0,Mat(),g_hist,1,bins,ranges);calcHist(&BGR[2],1,0,Mat(),r_hist,1,bins,ranges);

具体数据可视化的代码段我使用辅助工具生成:

        // ---------- 1. 准备画布 ----------int hist_w = 512;          // 画布宽度int hist_h = 400;          // 画布高度int bin_w = cvRound(double(hist_w) / 256);   // 每个 bin 的像素宽度Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0)); // 白底// ---------- 2. 归一化到 [0, hist_h] ----------normalize(b_hist, b_hist, 0, histImage.rows - 20, NORM_MINMAX);normalize(g_hist, g_hist, 0, histImage.rows - 20, NORM_MINMAX);normalize(r_hist, r_hist, 0, histImage.rows - 20, NORM_MINMAX);// ---------- 3. 绘制折线 ----------for (int i = 1; i < 256; ++i){line(histImage,Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),Point(bin_w * i,       hist_h - cvRound(b_hist.at<float>(i))),Scalar(255, 0, 0), 2);          // B 通道,蓝色line(histImage,Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),Point(bin_w * i,       hist_h - cvRound(g_hist.at<float>(i))),Scalar(0, 255, 0), 2);          // G 通道,绿色line(histImage,Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),Point(bin_w * i,       hist_h - cvRound(r_hist.at<float>(i))),Scalar(0, 0, 255), 2);          // R 通道,红色}// ---------- 4. 显示 ----------imshow("BGR Histogram", histImage);waitKey(0);   // 按任意键关闭窗口

整个Demo的代码如下:

void Demo::calicHist_Demo(Mat &image)
{vector<Mat> BGR;split(image,BGR);const int bins[] = {256};float hranges[] = {0,255};const float* ranges[1] = {hranges};Mat b_hist,g_hist,r_hist;calcHist(&BGR[0],1,0,Mat(),b_hist,1,bins,ranges);calcHist(&BGR[1],1,0,Mat(),g_hist,1,bins,ranges);calcHist(&BGR[2],1,0,Mat(),r_hist,1,bins,ranges);// ---------- 1. 准备画布 ----------int hist_w = 512;          // 画布宽度int hist_h = 400;          // 画布高度int bin_w = cvRound(double(hist_w) / 256);   // 每个 bin 的像素宽度Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0)); // 白底// ---------- 2. 归一化到 [0, hist_h] ----------normalize(b_hist, b_hist, 0, histImage.rows - 20, NORM_MINMAX);normalize(g_hist, g_hist, 0, histImage.rows - 20, NORM_MINMAX);normalize(r_hist, r_hist, 0, histImage.rows - 20, NORM_MINMAX);// ---------- 3. 绘制折线 ----------for (int i = 1; i < 256; ++i){line(histImage,Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),Point(bin_w * i,       hist_h - cvRound(b_hist.at<float>(i))),Scalar(255, 0, 0), 2);          // B 通道,蓝色line(histImage,Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),Point(bin_w * i,       hist_h - cvRound(g_hist.at<float>(i))),Scalar(0, 255, 0), 2);          // G 通道,绿色line(histImage,Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),Point(bin_w * i,       hist_h - cvRound(r_hist.at<float>(i))),Scalar(0, 0, 255), 2);          // R 通道,红色}// ---------- 4. 显示 ----------imshow("BGR Histogram", histImage);waitKey(0);   // 按任意键关闭窗口
}

运行结果: 

http://www.dtcms.com/a/314254.html

相关文章:

  • Git如何同步本地与远程仓库并解决冲突
  • C#利用unity游戏引实现开发设备仿真系统步骤
  • 《解构Angular组件变化检测:从自动到手 动的效能突破》
  • Unity Shader编程完全入门指南:从零到实战 C# 实战案例
  • 雷达系统工程学习:自制极化合成孔径雷达无人机
  • 【OpenGL】LearnOpenGL学习笔记03 - 着色器
  • 2025年半导体探针卡市场深度调研:规模数据、竞争格局
  • 防火墙的进阶练习
  • PVE环境对网口和wifi的配置
  • Neo4j 基础语法指南
  • 基于Spring Cloud Gateway和Resilience4j的微服务容错与流量控制实战经验分享
  • javacc学习笔记 03、编译原理实践 - JavaCC解析表达式并生成抽象语法树
  • MySQL5.0数据库管理系统安装部署
  • PCB反焊盘的样子越诡异,高速过孔的性能越好?
  • [自动化Adapt] 父子事件| 冗余过滤 | SQLite | SQLAlchemy | 会话工厂 | Alembic
  • 【物联网】基于树莓派的物联网开发【23】——树莓派安装SQLite嵌入式数据库
  • 秋招笔记-8.4
  • 小实验:按键点灯(中断法)
  • QT的UDP
  • 【数据结构入门】链表
  • Solidity智能合约开发全攻略
  • Java基础-斗地主游戏
  • ArrayDeque双端队列--底层原理可视化
  • ubuntu修改时区
  • 【HZ-T536开发板免费体验】Cangjie Magic调用视觉语言大模型(VLM)真香,是不是可以没有YOLO和OCR了?
  • 通用 PDF 文件流 OCR 到文本 API 接口
  • 使用 Aspose.OCR 将图像文本转换为可编辑文本
  • 基础14-Java集合框架:掌握List、Set和Map的使用
  • 十字滑台:精密制造的“心脏“如何跳动?
  • 耘瞳科技国产化点云处理软件,开启智能化三维测量新时代