opencv图像的直方图,二维直方图,直方图均衡化

文章目录

    • opencv图像的直方图,二维直方图,直方图均衡化
      • 一、图像的直方图
        • 1、什么是图像的直方图:
        • 2、直方图的作用:
        • 3、如何绘制图像的直方图:
          • (1)cv::calcHist()函数原型:英文单词 calculator histogram
          • (2)代码示例:
            • cv::cvRound()函数:将浮点数值四舍五入为最接近的整数;
            • 灰度图像直方图:
            • 彩色图像直方图:
      • 二、二维直方图
        • 1、什么是二维直方图:
        • 2、二维直方图与直方图有哪些不同:
        • 3、二维直方图的作用:
        • 4、如何绘制二维直方图:
      • 三、直方图均衡化
        • 1、直方图均衡化的原理:
        • 2、opencv中,可以使用 `cv::equalizeHist()`函数来实现直方图均衡化:
          • (1)cv::equalizeHist()函数原型:
          • (2)代码示例:
            • 灰度直方图均衡化:
            • 彩色直方图均衡化:

opencv图像的直方图,二维直方图,直方图均衡化

一、图像的直方图

1、什么是图像的直方图:
  • 要理解直方图,绕不开“亮度”这个概念,人们把亮度分为0到255共256个数值,数值越大,代表的亮度越高,其中0代表纯黑色,最暗区域,255表示最亮,纯白色,而中间的数字就是不同亮度的灰色;
  • 图像的直方图是一种统计图,它显示了图像中各个灰度级别的分布情况(也就是统计一幅图某个亮度像素的数量),通常它的横轴代表像素的灰度级别(从0到255),而纵轴代表该灰度级别在图像中出现的频次或概率;
2、直方图的作用:
  • 可视化图像亮度分布:直方图能够帮助我们直观地了解图像的亮度分布情况,从而为图像处理提供重要参考;
  • 对比度调整:通过观察直方图,我们可以确定图像的对比度是否合适,从而决定是否需要进行对比度调整;
  • 灰度级别选择:直方图可以帮助我们选择合适的灰度级别,以使图像的细节更加清晰;
3、如何绘制图像的直方图:

在opencv中,可以使用 cv::calcHist()函数来计算图像的直方图,这个函数可以接受一个通道的图像(灰度图像)或多个通道的图像(彩色图像);

(1)cv::calcHist()函数原型:英文单词 calculator histogram
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:输入图像,可以是单通道或多通道图像;
nimages:输入图像的个数(可以输入多张图像);
channels:需要统计直方图的第几通道,比如{0}表示统计第一个通道,{0, 1, 2}表示统计所有三个通道;
mask:掩膜,用于指定计算直方图的区域(必须是一个8(CV_8U)的数组并且和images的数组大小相同);
hist:输出的直方图数组,calcHist函数只是计算直方图的数据,直方图数据需要一个cv::Mat类型的变量来存储;
dims:输出直方图的维度(由channels值决定dims的数值;对于灰度图像dims为1,因为我们只考虑了一个通道(亮度通道);对于彩色图像,通常会考虑多个通道,比如在HSV色彩空间中,dims为2(H和S两个通道) 
);
histSize:指的是直方图横坐标分成多少个区间,就是bin的个数(用于控制直方图的精细度);把直方图横坐标ranges分成histSize个区间(比如ranges=180,histSize=30,则横坐标被分成了30个小竖条,每个小竖条的长度为6);
ranges:横轴代表像素的灰度级别,ranges相当于横坐标的取值范围(对于灰度图像,单通道只有1个range,灰度级别的范围从0255;对于彩色图像有多个通道就有多个range,对于每个通道,ranges指定了取值范围,通常在彩色图像中,H(色相)的范围是0180S(饱和度)V(明度)的范围是0255 );
uniform:是否对得到的直方图数组进行归一化处理;
accumulate:在多个图像时,是否累积计算像素值的个数;
(2)代码示例:
cv::cvRound()函数:将浮点数值四舍五入为最接近的整数;
// 函数在图像处理过程中经常用于处理像素值,特别是当需要将浮点数转换为整数时,可以保留最接近的整数值
int cvRound(double value)参数解释:
value:待四舍五入的浮点数;
灰度图像直方图:
#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>using namespace cv;
using namespace std;int main() {// 读取灰度图像cv::Mat image = cv::imread("C:\\cpp\\image\\suzy2.jpg", cv::IMREAD_GRAYSCALE);if (image.empty()) {std::cerr << "Error: 无法读取图像文件." << std::endl;return -1;}// 直方图计算的输出值,是一个cv::Mat对象cv::Mat hist;// X轴被分成了256个小区间int bins = 256;// 灰度图只有1个ranges,所以histSize跟要ranges对应,定义成1个int histSize[] = { bins };// X轴的取值范围float xRanges[] = { 0, 256 };// 在C++中,数组名本身就代表该数组的首地址,无需使用取地址符号&,// const float* ranges = xRanges;const float* ranges[] = { xRanges };// 我们要计算灰度图像的第0个通道,所以这里channels定义成{0}int channels[] = { 0 };calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges, true, false);// 待绘制的目标图像,将直方图计算的输出值hist,绘制到histImage图像上int histWidth = 512, histHeight = 400;int binWidth = cvRound( (double)histWidth/bins );cv::Mat histImage(histHeight, histWidth, CV_8UC3, cv::Scalar(0, 0, 0));// 使用normalize()函数将直方图的值缩放到图像的高度范围内normalize(hist, hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());// 使用cv::line()函数绘制直线for (int i = 1; i<bins; i++) {cv::line(histImage,Point(binWidth*(i - 1), histHeight - cvRound(hist.at<float>(i - 1))),Point(binWidth*(i), histHeight - cvRound(hist.at<float>(i))),Scalar(255, 0, 0),2,LINE_8,0);}// 显示图像和直方图cv::imshow("Image", image);cv::imshow("Histogram", histImage);waitKey();return 0;
}

运行结果:
在这里插入图片描述

彩色图像直方图:

对于彩色图像,你可以分别计算其颜色通道(蓝色、绿色、红色)的直方图,或者将其转换为灰度图像后计算整体的亮度直方图;

在这个示例中,我们首先读取了一个彩色图像,然后使用 cv::split() 函数将图像分离成蓝色、绿色和红色通道,接着,我们分别计算了每个通道的直方图,最后我们绘制了各个通道的直方图并显示了原始图像和直方图;

#include <opencv2\opencv.hpp>
#include <iostream>
#include <demo.h>using namespace cv;
using namespace std;int main() {// 读取彩色图像cv::Mat image = cv::imread("C:\\cpp\\image\\suzy2.jpg");if (image.empty()) {std::cerr << "Error: 无法读取图像文件." << std::endl;return -1;}// 分离通道std::vector<cv::Mat> bgrPlanes;cv::split(image, bgrPlanes);// 计算直方图int histSize = 256; // 亮度级别的个数float range[] = { 0, 256 };const float* histRange = range;cv::Mat bHist, gHist, rHist;cv::calcHist(&bgrPlanes[0], 1, 0, cv::Mat(), bHist, 1, &histSize, &histRange);cv::calcHist(&bgrPlanes[1], 1, 0, cv::Mat(), gHist, 1, &histSize, &histRange);cv::calcHist(&bgrPlanes[2], 1, 0, cv::Mat(), rHist, 1, &histSize, &histRange);// 绘制直方图int histWidth=512, histHeight=400;int binWidth = cvRound( (double)histWidth/histSize );cv::Mat histImage(histHeight, histWidth, CV_8UC3, cv::Scalar(0, 0, 0));normalize(bHist, bHist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());normalize(gHist, gHist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());normalize(rHist, rHist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());for (int i=1; i<histSize; i++) {// 绘制蓝色分量直方图cv::line( histImage, cv::Point( binWidth*(i-1), histHeight-cvRound(bHist.at<float>(i-1)) ),cv::Point( binWidth*(i), histHeight-cvRound(bHist.at<float>(i)) ),cv::Scalar(255, 0, 0), 2, LINE_8,0);// 绘制绿色分量直方图cv::line(histImage, cv::Point( binWidth*(i-1), histHeight-cvRound(gHist.at<float>(i-1)) ),cv::Point( binWidth*(i), histHeight-cvRound(gHist.at<float>(i)) ),cv::Scalar(0, 255, 0), 2, LINE_8,0);// 绘制红色分量直方图cv::line(histImage, cv::Point( binWidth*(i-1), histHeight-cvRound(rHist.at<float>(i-1)) ),cv::Point( binWidth*(i), histHeight-cvRound(rHist.at<float>(i)) ),cv::Scalar(0, 0, 255), 2, LINE_8,0);}// 显示图像和直方图cv::imshow("Image", image);cv::imshow("Histogram", histImage);cv::waitKey(0);return 0;}

运行结果:
在这里插入图片描述

二、二维直方图

1、什么是二维直方图:

二维直方图是对彩色图像进行分析时的一个重要工具,与一维直方图不同,它同时考虑了两个通道的信息,通常是颜色空间中的两个分量,例如在HSV色彩空间中的H(色相)和S(饱和度);

2、二维直方图与直方图有哪些不同:
  • 维度:直方图是一维的,它只考虑了图像的亮度或色彩信息;而二维直方图考虑了两个通道的信息,因此是二维的;
  • 通道:直方图通常只针对一个通道(灰度图只有亮度通道);而二维直方图可以同时考虑多个通道,通常是颜色空间中的两个分量;
3、二维直方图的作用:
  • 颜色分布分析:通过二维直方图,我们可以了解图像中各个颜色组合的分布情况,有助于理解图像的颜色特性;
  • 图像分割与对象识别:在图像分割和对象识别任务中,二维直方图可用于将图像的颜色特征映射到特定的空间,从而实现对图像中的对象进行定位和识别;
  • 颜色调整与匹配:通过分析二维直方图,我们可以进行颜色调整,使图像的颜色分布更加符合预期;
4、如何绘制二维直方图:

首先读取了一个彩色图像,然后将其从BGR颜色空间转换为HSV颜色空间,接着我们分离了H和S通道,并指定了直方图的维度、通道数、亮度级别个数和范围,然后我们使用 cv::calcHist()计算了二维直方图并使用 cv::rectangle()绘制;

#include <opencv2\opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main() {// 读取彩色图像cv::Mat image = cv::imread("C:\\cpp\\image\\suzy2.jpg");if (image.empty()) {std::cerr << "Error: 无法读取图像文件." << std::endl;return -1;}// 2D 直方图Mat hsv, hist;cvtColor(image, hsv, COLOR_BGR2HSV);// H通道X轴被分成了30个小区间,S通道X轴被分成了32个小区间int hueBins = 30, satBins = 32;// 彩色图像有多个ranges,所以histSize跟ranges对应也要定义多个,定义成数组的形式int histSize[] = { hueBins, satBins };float hueRanges[] = { 0, 180 };	// H通道X轴的取值范围float satRanges[] = { 0, 256 };	// S通道X轴的取值范围// 彩色图像有多个ranges,定义成数组的形式const float* ranges[] = { hueRanges, satRanges };// 我们要计算HSV图像的第0个通道和第1个通道的直方图,所以这里channels也要定义多个int channels[] = { 0, 1 };calcHist(&hsv, 1, channels, Mat(), hist, 2, histSize, ranges, true, false);// 画出计算后的直方图double maxVal = 0;minMaxLoc(hist, 0, &maxVal, 0, 0);int scale = 10;Mat histImage = Mat::zeros(satBins*scale, hueBins*scale, CV_8UC3);for (int h=0; h<hueBins; h++) {for (int s=0; s<satBins; s++){float binVal = hist.at<float>(h, s);int intensity = cvRound( binVal*255 / maxVal );rectangle(histImage, Point( h*scale, s*scale ),Point( (h+1)*scale - 1, (s+1)*scale - 1 ),Scalar::all(intensity),-1);}}applyColorMap(histImage, histImage, COLORMAP_JET);imshow("Image", image);imshow("H-S Histogram", histImage);cv::waitKey(0);return 0;}

运行结果:
在这里插入图片描述

三、直方图均衡化

直方图均衡化是一种用于增强图像对比度的图像处理技术,它通过重新分配图像的像素值,使得整个亮度范围得到充分利用,从而使图像看起来更清晰和具有更好的对比度;

1、直方图均衡化的原理:
  • 计算直方图:首先计算原始图像的灰度直方图,这个直方图描述了图像中各个灰度级别的分布情况;
  • 计算累积分布函数(CDF):将灰度直方图转换为累积分布函数,CDF表示了每个灰度级别的累积概率;
  • 映射新的像素值:对于每个像素,将其原始灰度值映射到新的值,使得新的值在整个亮度范围内均匀分布;
2、opencv中,可以使用 cv::equalizeHist()函数来实现直方图均衡化:
(1)cv::equalizeHist()函数原型:
void cv::equalizeHist(InputArray src, OutputArray dst
);参数解释:
src:输入图像(灰度图像);
dst:输出图像,用于存储均衡化后的结果;
(2)代码示例:
灰度直方图均衡化:
#include <opencv2\opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main() {// 读取灰度图像cv::Mat image = cv::imread("C:\\cpp\\image\\suzy2.jpg", cv::IMREAD_GRAYSCALE);if (image.empty()) {std::cerr << "Error: 无法读取图像文件." << std::endl;return -1;}// 均衡化灰度直方图cv::Mat equalizedImage;cv::equalizeHist(image, equalizedImage);cv::imshow("Original Gray Image", grayImage);cv::imshow("Equalized Gray Image", equalizedImage);cv::waitKey(0);return 0;}

运行结果:
在这里插入图片描述

彩色直方图均衡化:

首先将彩色图像转换为HSV色彩空间,然后对亮度(Value/V通道)进行均衡化,最后将其转换回BGR色彩空间以显示

#include <opencv2\opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int main() {// 读取彩色图像cv::Mat image = cv::imread("C:\\cpp\\image\\suzy2.jpg", cv::IMREAD_COLOR);if (image.empty()) {std::cerr << "Error: 无法读取图像文件." << std::endl;return -1;}// 将图像从BGR色彩空间转换为HSV色彩空间cv::Mat hsvImage;cv::cvtColor(image, hsvImage, cv::COLOR_BGR2HSV);// 均衡化HSV通道的直方图std::vector<cv::Mat> channels;cv::split(hsvImage, channels);cv::equalizeHist(channels[2], channels[2]);cv::Mat equalizedHSV;cv::merge(channels, equalizedHSV);cv::cvtColor(equalizedHSV, equalizedHSV, cv::COLOR_HSV2BGR);cv::imshow("Original Color Image", image);cv::imshow("Equalized Color Image", equalizedHSV);cv::waitKey(0);return 0;}

运行结果:
在这里插入图片描述

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

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

相关文章

协议栈——创建套接字

前面几篇文章讲解的是应用程序使用Socket间接通知协议栈进行的连接&#xff0c;通信阶段&#xff0c;那么从现在开始讲解协议栈和网卡驱动的故事 回顾上篇文章&#xff0c;我们从第一阶段创建套接字&#xff0c;协议栈返回描述符讲起~~~ 协议栈结构 首先来看下协议栈的大致结…

计算机视觉: 基于隐式BRDF自编码器的文生三维技术

论文链接: MATLABER: Material-Aware Text-to-3D via LAtent BRDF auto-EncodeR 背景 得益扩散模型和大量的text - image 成对的图片&#xff0c; 现在文生2D的模型已经比较成熟的框架和模型&#xff0c;主流的技术比如说stable diffusion 和 midjourney 以及工业领域runway 等…

计算机毕设 招聘网站爬取与大数据分析可视化 - python 分析 可视化 flask

文章目录 0 前言1 课题背景2 实现效果3 Flask框架4 Echarts5 爬虫6 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自…

制作长图海报的详细指南,制作长图海报的5个步骤

制作长图海报是宣传活动、产品或服务的重要方式之一。乔拓云后台提供了丰富的海报模板&#xff0c;让你轻松制作出专业级的长图海报。下面将介绍如何使用乔拓云后台制作长图海报的技巧。 一、选择模板 首先&#xff0c;注册并登录乔拓云后台&#xff0c;进入云设计页面。在选择…

A (1087) : DS单链表--类实现

Description 用C语言和类实现单链表&#xff0c;含头结点 属性包括&#xff1a;data数据域、next指针域 操作包括&#xff1a;插入、删除、查找 注意&#xff1a;单链表不是数组&#xff0c;所以位置从1开始对应首结点&#xff0c;头结点不放数据 类定义参考 #include<…

Qt_基础

目录 1概述1.1 什么是QT1.2 QT的发展史1.3 支持的平台1.4 QT版本1.5 下载与安装1.6 QT的优点1.7 成功案例 2 创建 Qt 项目2.1 使用向导创建2.2 .pro文件2.3 帮助文档(QTcreator自带的)2.4 QT应用程序介绍 3 创建第一个小程序3.1 按钮的创建3.1.1 设置主窗口标题的函数3.1.2 **固…

小谈设计模式(23)—桥接模式

小谈设计模式&#xff08;23&#xff09;—桥接模式 专栏介绍专栏地址专栏介绍 桥接模式主要角色抽象部分实现部分分析 核心思想应用场景123 优缺点分析优点123 缺点12 总结 专栏介绍 专栏地址 link 专栏介绍 主要对目前市面上常见的23种设计模式进行逐一分析和总结&#x…

三极管及继电器的使用(单片机如何控制灯泡等大型电器)

1.对于初入硬件的小伙伴一定会用到三极管和继电器&#xff0c;如下图&#xff08;三极管&#xff09; 如下图&#xff08;继电器&#xff09; 当然上述三极管和继电器&#xff0c;只是众多的其中一种&#xff0c;而且继电器是包装好了的&#xff0c;这个应该叫继电器模块&#…

SpringBoot 实现数据脱敏

SpringBoot 实现数据脱敏 前言Hutool 实现数据脱敏引入依赖脱敏工具类代码实现 使用注解的方式定义枚举自定义序列化类定义注解测试 前言 数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形&#xff0c;实现敏感隐私数据的可靠保护。 数据脱敏常用规则有替换、重排、加密…

MYSQL06高级_为什么使用索引、优缺点、索引的设计、方案、聚簇索引、联合索引、注意事项

文章目录 ①. 为什么使用索引②. 索引及其优缺点③. InnoDb - 索引的设计④. InnoDb中的索引方案⑤. 索引 - 聚簇索引⑥. 索引 - 二级索引⑦. B树索引的注意事项⑧. MyISAM中索引方案 ①. 为什么使用索引 ①. 索引是存储引擎用于快速找到数据记录的一种数据结构,就好比去图书馆…

leetCode 1143.最长公共子序列 动态规划

1143. 最长公共子序列 - 力扣&#xff08;LeetCode&#xff09; 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串…

2021-06-09 51单片机:两个独立按键控制一个led,k1按下松开led闪烁三次,k2按下LED闪烁五次

缘由51单片机:两个独立按键控制一个led,k1按下松开led闪烁三次,k2按下LED闪烁五次_嵌入式-CSDN问答 #include "REG52.h" sbit K1 P1^0; sbit K2 P1^1; sbit LEDP0^0; void main() {unsigned char Xd0,ss0;unsigned int wei0;while(1){if(K10&&Xd0){ss3*2;…

Mysql存储-EAV模式

Mysql存储-EAV模式 最近又又又搞一点新东西&#xff0c;要整合不同业务进行存储和查询&#xff0c;一波学习过后总结了一下可扩展性MAX的eav模式存储。 在eav这里的数据结构设计尤为关键&#xff0c;需要充分考虑你需要使用的字段、使用场景&#xff0c;当数据结构设计完成后便…

单目标应用:猎豹优化算法(The Cheetah Optimizer,CO)求解微电网优化MATLAB

一、微网系统运行优化模型 微电网优化模型介绍&#xff1a; 微电网多目标优化调度模型简介_IT猿手的博客-CSDN博客 二、猎豹优化算法CO 猎豹优化算法&#xff08;The Cheetah Optimizer&#xff0c;CO&#xff09;由MohammadAminAkbari等人于2022年提出&#xff0c;该算法性…

数字IC前端学习笔记:数字乘法器的优化设计(Dadda Tree乘法器)

相关阅读 数字IC前端https://blog.csdn.net/weixin_45791458/category_12173698.html?spm1001.2014.3001.5482 华莱士树仍然是一种比较规则的结构&#xff08;这使得可以方便地生成树的结构&#xff09;&#xff0c;这导致了它所使用的全加器和半加器个数不是最少的&#xff…

大数据概述(林子雨慕课课程)

文章目录 1. 大数据概述1.1 大数据概念和影响1.2 大数据的应用1.3 大数据的关键技术1.4 大数据与云计算和物联网的关系云计算物联网 1. 大数据概述 大数据的四大特点&#xff1a;大量化、快速化、多样化、价值密度低 1.1 大数据概念和影响 大数据摩尔定律 大数据由结构化和非…

C++简单上手helloworld 以及 vscode找不到文件的可能性原因

helloworld #include <iostream>int main() {std::cout << "hello world!" << std::endl;return 0; }输入输出小功能 #include <iostream> using namespace std; /* *主函数 *输出一条语句 */int main() {// 输出一条语句cout << &q…

智慧茶园:茶厂茶园监管可视化视频管理系统解决方案

一、方案背景 我国是茶叶生产大国&#xff0c;茶叶销量全世界第一。随着经济社会的发展和人民生活水平的提高&#xff0c;对健康、天然的茶叶产品的消费需求量也在逐步提高。茶叶的种植、生产和制作过程工序复杂&#xff0c;伴随着人力成本的上升&#xff0c;传统茶厂的运营及…

拉线位移编码器要检查机械装置的安装状态

拉线位移编码器要检查机械装置的安装状态 1、先要检查机械装置的安装状态&#xff0c;看看是不是机械故障的原因&#xff0c;这个原因是很简单的就可以去排除。 2、判别显示器是否有故障&#xff1a;用一台同类型不同量程的高准确度位移传感器当作标准信号发生器来测量。 3、…

【周末闲谈】“PHP是最好的语言”这个梗是怎么来的?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 系列目录 ✨第一周 二进制VS三进制 ✨第二周 文心一言&#xff0c;模仿还是超越&#xff1f; ✨第二周 畅想AR 文章目录 系列目录前言最早的出处关于PHP语言优点缺点网络评价 总结 前言 …