《opencv实用探索·十六》opencv直方图计算calcHist函数解析

直方图理解:
(对于8位灰度图像亮度/灰度为(0-255),12位灰度图像亮度/灰度为(0-4095))
以8位图像为例,亮度分为0到255共256个数值,数值越大,代表的亮度越高。其中0代表纯黑色的最暗区域,255表示最亮的纯白色。亮度分为了5个区域,分别是黑色,阴影,中间调,高光和白色。直方图用来统计一幅图像某个亮度像素数量。
在这里插入图片描述

直方图函数解析:

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

images:输入的图像的指针,可以是多幅图像,所有的图像必须有同样的深度(CV_8U or CV_32F)。同时一副图像可以有多个channes。
nimages:输入图像的个数
channels:需要统计直方图的第几通道。用来计算直方图的channes的数组。比如输入是2副图像,第一副图像有0,1,2共三个channel,第二幅图像只有0一个channel,那么输入就一共有4个channes,如果int channels[3] = {3, 2, 0},那么就表示是使用第二副图像的第一个通道和第一副图像的第2和第0个通道来计算直方图。
mask:掩膜,如果是空矩阵则表示图像中所有位置的像素都计入直方图中,如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且与输入图像尺寸相同,找到mask非0像素区域,把这些区域对应到输入图像区域,然后把这些区域参与直方图计算。
hist:输出的直方图数组
dims:需要统计直方图通道的个数,通常为1
histSize:指的是直方图分成多少个区间,就是 bin的个数。
const float** ranges: 统计像素值得区间。
uniform=true::是否对得到的直方图数组进行归一化处理
accumulate=false:在多个图像时,是否累计计算像素值得个数

几个例子理解直方图参数含义:
首先我们对一个mat图像做几个设定如下:
(1)8位单通道灰度图,那么这个图像灰度范围为0-255
(2)mat图像总像素个数为10000
(3)灰度范围在0-127时像素个数为8000, 灰度范围128-255时像素个数为2000
(3)灰度范围在0-84时像素个数为3000, 灰度范围85-170时像素个数为6000,灰度范围171-255时像素个数为1000

int main()
{Mat mat = cv::imread("1.tif", -1);int max_value = 0;int channels[] = { 0 };const int histSize[] = { 256 };float range[] = { 0, 256};const float* ranges[] = { range };cv::Mat hist;cv::calcHist(&mat, 1, channels, cv::Mat(), hist, 1, histSize, ranges, true, false);int sum = 0;for (int i = 0; i < 255; i++){sum += hist.at<float>(i);}return 0;
}

上面代码中可知像素值范围range为0-255(不包含256),histSize为256相当于把rang(0-255)分为256份。for循环对histSize总份数进行遍历,相当于遍历0-255每个灰度,这样可以拿到每个灰度下的像素个数,最终sum总和等于10000。

int main()
{Mat mat = cv::imread("1.tif", -1);int max_value = 0;int channels[] = { 0 };const int histSize[] = { 2 };float range[] = { 0, 256};const float* ranges[] = { range };cv::Mat hist;cv::calcHist(&mat, 1, channels, cv::Mat(), hist, 1, histSize, ranges, true, false);int sum = 0;for (int i = 0; i < 2; i++){sum += hist.at<float>(i);}return 0;
}

上面代码中range灰度范围为0-255,histSize把灰度范围分为两份,第一份灰度范围0-127,第二份灰度范围128-255
for循环中遍历总份数,即遍历两份,第一份可以拿到灰度范围0-127的所有像素之和,即8000,第二份可以拿到128-255范围所有像素之和,即2000

int main()
{Mat mat = cv::imread("1.tif", -1);int max_value = 0;int channels[] = { 0 };const int histSize[] = { 3 };float range[] = { 0, 256};const float* ranges[] = { range };cv::Mat hist;cv::calcHist(&mat, 1, channels, cv::Mat(), hist, 1, histSize, ranges, true, false);int sum = 0;for (int i = 0; i < 3; i++){sum += hist.at<float>(i);}return 0;
}

上面代码中range范围0-255,histSize把range总共分为三份,即0-84,85-170,171-255
for循环遍历histSize,在第一份中可以拿到灰度范围在0-84的总像素个数,即3000,在第二份中可以拿到灰度范围在85-170的总像素个数,即6000,第三份可以拿到171-255范围的总像素个数,即1000

下面是直方图的一个具体应用,8位三通道计算直方图案例:

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main() {// 读取图像Mat image = imread("your_image.jpg");if (image.empty()) {cerr << "Error: Could not read the image." << endl;return -1;}// 设置直方图参数int histSize = 256;  // 直方图的 bin 数量float range[] = {0, 256};  // 像素值范围const float* histRange = {range};bool uniform = true;  // 直方图是否均匀bool accumulate = false;  // 是否累积直方图// 计算蓝色通道的直方图int channelB = 0;  // 蓝色通道索引Mat histB;calcHist(&image, 1, &channelB, Mat(), histB, 1, &histSize, &histRange, uniform, accumulate);// 计算绿色通道的直方图int channelG = 1;  // 绿色通道索引Mat histG;calcHist(&image, 1, &channelG, Mat(), histG, 1, &histSize, &histRange, uniform, accumulate);// 计算红色通道的直方图int channelR = 2;  // 红色通道索引Mat histR;calcHist(&image, 1, &channelR, Mat(), histR, 1, &histSize, &histRange, uniform, accumulate);// 绘制直方图int histWidth = 512;int histHeight = 400;int binWidth = cvRound((double) histWidth / histSize);Mat histImage(histHeight, histWidth, CV_8UC3, Scalar(0, 0, 0));// 归一化直方图数据normalize(histB, histB, 0, histImage.rows, NORM_MINMAX, -1, Mat());normalize(histG, histG, 0, histImage.rows, NORM_MINMAX, -1, Mat());normalize(histR, histR, 0, histImage.rows, NORM_MINMAX, -1, Mat());// 绘制直方图for (int i = 1; i < histSize; ++i) {line(histImage, Point(binWidth * (i - 1), cvRound(histB.at<float>(i - 1))),Point(binWidth * (i), cvRound(histB.at<float>(i))),Scalar(255, 0, 0), 2, 8, 0);line(histImage, Point(binWidth * (i - 1), cvRound(histG.at<float>(i - 1))),Point(binWidth * (i), cvRound(histG.at<float>(i))),Scalar(0, 255, 0), 2, 8, 0);line(histImage, Point(binWidth * (i - 1),cvRound(histR.at<float>(i - 1))),Point(binWidth * (i), cvRound(histR.at<float>(i))),Scalar(0, 0, 255), 2, 8, 0);}// 显示原始图像和直方图imshow("Original Image", image);imshow("Histogram", histImage);waitKey(0);return 0;
}

在这里插入图片描述

也可也遍历拿到BGR每个通道下0-255每个灰度的像素个数
比如遍历B通道

for(int i = 0; i < 256; i++)
{float count = cvRound(histB.at<float>(i - 1);
}

0-256为每个灰度,for循环遍历每个灰度,并拿到该灰度下像素的个数,比如i=100,count=20表示,灰度为100的像素有20个。

在这里插入图片描述

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

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

相关文章

外包干了3个月,技术退步明显。。。

先说一下自己的情况&#xff0c;本科生生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…

索尼(ILCE-7M3)MP4文件只能播放前两分钟修复案例

索尼的ILCE-7M3是一款经典设备&#xff0c;其HEVC编码效果是比较不错的&#xff0c;因此受到很多专业人士的青睐。之前我们说过很多索尼摄像机断电生成RSV文件修复的案例&#xff0c;今天来讲一个特殊的&#xff0c;文件已经正常封装但仅能播放前两分钟多一点的画面。 故障文件…

静态路由原理与配置

文章目录 静态路由原理与配置一、路由器的工作原理1、路由概述2、路由器的工作原理 二、路由表的形成1、路由表2、路由表的形成 三、静态路由和默认路由1、静态路由的缺点2、默认路由&#xff08;是特殊的静态路由&#xff09;3、查看路由表 四、路由器转发数据包的封装过程五、…

FreeRtos里的几个中断屏蔽

1、primask 寄存器 PRIMASK用于禁止除NMI和HardFalut外的所有异常和中断&#xff0c;使用方法&#xff1a; cpsid i &#xff1b; //设置primask &#xff08;禁止中断&#xff09; cpsie i ; //清除primask (使能中断) 也可以 movs r0,#1 msr primask r0; //将 1写入p…

力扣刷题-二叉树-二叉树左叶子之和

404 左叶子之和 给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 示例 1&#xff1a; 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别是 9 和 15&#xff0c;所以返回 24 思路 迭代法 迭代法理解…

Java 第9章 房屋出租系统

设计 如图是系统的分层结构&#xff0c;包括了界面层、业务层和数据层。 单独建包&#xff1a;由于在实际开发过程中&#xff0c;可能会出现管理多个界面的情况&#xff0c;所以界面需要单独建包&#xff0c;其他同理。 开发任务&#xff1a;从界面层深入到业务层&#xff0c…

菜鸟学习日记(python)——匿名函数

Python 使用 lambda 来创建匿名函数。 lambda 函数是一种小型、匿名的内联函数&#xff0c;它可以具有任意数量的参数&#xff0c;但只能有一个表达式。 匿名函数的一般格式如下&#xff1a; lambda 参数列表:表达式 表达式用于计算并返回函数结果 lambda 函数通常用于编写…

基于Java SSM框架实现智能停车场系统项目【项目源码+论文说明】

基于java的SSM框架实现智能停车场系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个智能停车场管理系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述…

记录 | gpu docker启动报错libnvidia-ml.so.1: file exists: unknown

困扰了两天的问题&#xff0c;记录一下 问题出在启动一个本身已经安装 cuda 的镜像上&#xff0c;具体来说&#xff0c;我是启动地平线天工开物工具链镜像的时候出现的问题&#xff0c;具体报错如下&#xff1a; docker: Error response from daemon: failed to create task …

加密的艺术:对称加密的奇妙之处(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

第十二章 React 路由配置,路由参数获取

一、专栏介绍 &#x1f436;&#x1f436; 欢迎加入本专栏&#xff01;本专栏将引领您快速上手React&#xff0c;让我们一起放弃放弃的念头&#xff0c;开始学习之旅吧&#xff01;我们将从搭建React项目开始&#xff0c;逐步深入讲解最核心的hooks&#xff0c;以及React路由、…

QT第一步

文章目录 软件下载软件安装QT的程序组新建项目 软件下载 qt下载网址&#xff1a;https://download.qt.io/archive/qt/   关于版本&#xff1a;     我选择的版本是5.14.2&#xff0c;这个版本是最后的二进制安装包的版本&#xff0c;在往后的版本就需要在线安装了。并且5…

记一次挖矿病毒的溯源

ps&#xff1a;因为项目保密的原因部分的截图是自己在本地的环境复现。 1. 起因 客户打电话过来说&#xff0c;公司web服务异常卡顿。起初以为是web服务缓存过多导致&#xff0c;重启几次无果后觉得可能是受到了攻击。起初以为是ddos攻击&#xff0c;然后去查看web服务器管理…

Cannot find cache named ‘‘ for Builder Redis

当引入 Redissson 时&#xff0c;springCache 缓存机制失效 原因&#xff1a;springCache 默认使用本地缓存 Redisson 使用redis 缓存 最后都转成redis了。。。 总感觉哪不对 两者居然不共存

力扣刷题-二叉树-路径总和

112 路径总和 给定一个二叉树和一个目标和&#xff0c;判断该树中是否存在根节点到叶子节点的路径&#xff0c;这条路径上所有节点值相加等于目标和。 说明: 叶子节点是指没有子节点的节点。 示例: 给定如下二叉树&#xff0c;以及目标和 sum 22&#xff0c; 返回 true, 因为…

VRRP(虚拟路由冗余协议)

一.VRRP简介 1.VRRP是什么 Virtual route Redundancy Protocol&#xff0c;也叫虚拟路由器冗余协议。 利用VRRP&#xff0c;一组路由器协同工作&#xff0c;单只有一个处于Master状态&#xff0c;处于该状态的路由器&#xff08;的接口&#xff09;承担实际的数据流量转发任…

亚马逊云科技发布企业生成式AI助手Amazon Q,助力企业迈向智能化时代

&#xff08;声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 亚马逊云科技开发者社区、知乎、自媒体平台、第三方开发者媒体等亚马逊云科技官方渠道&#xff09; 一、前言 随着人工智能技术的快速发展和广泛应用&#xff0c;我们…

git 上传大文件操作 lfs 的使用

我们要先去下载 下载后安装 我最后还是下载到了D:\git\Git\bin这个目录下 如何检查是否下载成功呢&#xff0c;用 git lfs install 在命令行运行就可以查看 下面怎么上传文件呢 首先我们还是要初始化文件的 git init 下一步输入命令 git lfs install 下一步 git lfs tra…

MySQL之DML语句

文章目录 DML语句创建表添加表字段**插入数据**查询数据更新数据替换数据删除数据清除表数据删除表 DML语句 数据操作语言DML&#xff08;Data Manipulation Langua&#xff09; 是SQL语言的一个分类&#xff0c;用于对表的数据进行增&#xff0c;删&#xff0c;改&#xff0c…

成都工业学院2021级操作系统专周课程设计FCFS,SSTF,SCAN,LOOK算法的实现

运行环境 操作系统&#xff1a;Windows 11 家庭版 运行软件&#xff1a;CLion 2023.2.2 源代码文件 #include <iostream> #include <vector> #include <algorithm> #include <random> using namespace std;// 生成随机数 int generateRandomNumber…