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

news2024/10/5 22:23:32

文章目录

    • opencv图像的直方图,二维直方图,直方图均衡化
      • 一、图像的直方图
        • 1、什么是图像的直方图:
        • 2、直方图的作用:
        • 3、如何绘制图像的直方图:
          • (1)cv::calcHist()函数原型:
          • (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()函数原型:
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:直方图计算的输出值,是一个cv::Mat对象;
dims:输出直方图的维度(
	由channels值决定dims的数值;
	对于灰度图像dims为1,因为我们只考虑了一个通道(亮度通道);
	对于彩色图像,通常会考虑多个通道,比如在HSV色彩空间中,dims为2(H和S两个通道) 
);
histSize:指定每个dims维度需要分成多少个区间(用于控制直方图的精细度);
ranges:用于指定每个dims维度(通道)的取值范围,包含了每个通道的最小值和最大值(
	对于灰度图像,单通道只有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;
	// 亮度级别的个数
	int histSize = 256; 
	// 亮度值的范围
	float range[] = { 0, 256 };
	// 在C++中,数组名本身就代表该数组的首地址,无需使用取地址符号&,
	const float* histRange = range;
	cv::calcHist(&image, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange);

	// 待绘制的目标图像,将直方图计算的输出值hist,绘制到histImage图像上
	int histWidth = 512, histHeight = 400;
	int binWidth = cvRound( (double)histWidth/histSize );
	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<histSize; 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>
#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;
	}

	// 将图像从BGR颜色空间转换为HSV颜色空间
	cv::Mat hsvImage;
	cv::cvtColor(image, hsvImage, cv::COLOR_BGR2HSV);

	// 分离H和S通道
	std::vector<cv::Mat> channels;
	cv::split(hsvImage, channels);
	int channelNumbers[] = { 0, 1 };
	int histSize[] = { 256, 256 };
	float hueRanges[] = { 0, 256 };
	float satRanges[] = { 0, 256 };
	const float* ranges[] = { hueRanges, satRanges };

	// 计算直方图
	cv::Mat hist;
	cv::calcHist(&channels[0], 1, channelNumbers, cv::Mat(), hist, 2, histSize, ranges, true, false);

	// 绘制直方图
	int histWidth= 512, histHeight = 512;
	int binWidth = histWidth/histSize[0];
	int binHeight = histHeight/histSize[1];
	cv::Mat histImage(histHeight, histWidth, CV_8UC3, cv::Scalar(0, 0, 0));

	cv::normalize(hist, hist, 0, 255, cv::NORM_MINMAX);

	for (int i = 0; i < histSize[0]; i++) {
		for (int j = 0; j < histSize[1]; j++) {
			int x = i * binWidth;
			int y = j * binHeight;
			int w = (i + 1) * binWidth - x;
			int h = (j + 1) * binHeight - y;
			cv::rectangle(histImage, cv::Rect(x, y, w, h), cv::Scalar(hist.at<float>(i, j), 0, 0), -1);
		}
	}

	// 显示图像和直方图
	cv::imshow("Image", image);
	cv::imshow("2D 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.coloradmin.cn/o/1069469.html

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

相关文章

土地证、工程规划许可证、建设用地规划许可证

土地证、工程规划许可证、建设用地规划许可证办理是房地产开发最基础和初开始的工作流程。 一、土地证是简称&#xff0c;全称为《中华人民共和国国有土地使用证》&#xff0c;发证部门是当地国有土地资源局。 申办单位经当地规划部门审批通过某项目备案审批&#xff0c;在办理…

想要精通算法和SQL的成长之路 - 简化路径

想要精通算法和SQL的成长之路 - 简化路径 前言一. 简化路径 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 简化路径 原题连接 思路如下&#xff1a; 我们根据 "/" 去拆分字符串&#xff0c;得到每个子目录。这里拿到的子目录可能是空字符串&#xff0c;需要…

【Vue2.0源码学习】生命周期篇-销毁阶段(destroy)

文章目录 1. 前言2. 销毁阶段分析3. 总结 1. 前言 接下来到了生命周期流程的最后一个阶段——销毁阶段。从官方文档给出的生命周期流程图中可以看到&#xff0c;当调用了vm.$destroy方法&#xff0c;Vue实例就进入了销毁阶段&#xff0c;该阶段所做的主要工作是将当前的Vue实例…

buuctf PWN warmup_csaw_2016

下载附件&#xff0c;IDA查看 发现直接有显示flag函数 int sub_40060D() {return system("cat flag.txt"); }查看程序起始地址0x40060D ; Attributes: bp-based framesub_40060D proc near ; __unwind { push rbp mov rbp, rsp mov edi, offset comman…

Vue中如何进行音视频录制与视频剪辑

在Vue中进行音视频录制与视频剪辑 随着互联网的发展&#xff0c;音视频处理已经成为前端开发中一个越来越重要的领域。Vue.js作为一款流行的前端框架&#xff0c;为我们提供了丰富的工具和生态系统&#xff0c;使得音视频录制和编辑变得更加容易。本文将介绍如何在Vue中进行音…

SpringMVC修炼之旅(1)什么是SpringMVC

一、什么是MVC 1.1概述 MVC是模型(Model)、视图(View)、控制器(Controller)的简写&#xff0c;是一种软件设计规范。 是将业务逻辑、数据、显示分离的方法来组织代码。 MVC主要作用是降低了视图与业务逻辑间的双向偶合。 MVC不是一种设计模式&#xff0c;MVC是一种架构模式…

[Android]问题解决-Device must be bootloader unlocked

现象 在push文件时&#xff0c;remount命令发生如下报错&#xff1a; $ adb remount Device must be bootloader unlocked解决 1. 打开 开发者模式中的OEM unlocking开关 2. fastboot unlock设置 adb reboot bootloader fastboot flashing unlock根据屏幕提示&#xff0c;…

Python爬取小说(requests和BeautifulSoup)

1.用requests和BeautifulSoup爬取起点中文网小说(https://www.qidian.com/free/all/) 2.选择一篇小说(https://www.qidian.com/book/1037297523/&#xff09; 3.查看小说的卷章和每章对应的章节 4.Chrome浏览器&#xff0c;使用F12&#xff0c;打开开发者模式&#xff0c;查看章…

C超市商品信息查询系统

一、系统界面介绍 1. 超市商品信息查询系统 1、显示商品信息&#xff0c;包括&#xff1a;商品名称、商品种类&#xff08;休闲食品、奶品水饮、生鲜水果&#xff09;、商品价格、商品保质期、商品生产日期&#xff1b; 2、从文件中导入数据、显示、排序、查询的功能。&…

Javascript笔记 rest VS spread

1 rest 2 spread 3 二者区别 在 JavaScript 中&#xff0c;spread 操作符 ... 和 rest 参数都使用三个点 ... 作为前缀&#xff0c;但它们在使用上有一些区别&#xff0c;主要体现在它们的作用和使用场景上。 Spread 操作符 ... 作用&#xff1a; "展开"数组或对象的…

分类预测 | MATLAB实现SSA-CNN麻雀算法优化卷积神经网络数据分类预测

分类预测 | MATLAB实现SSA-CNN麻雀算法优化卷积神经网络数据分类预测 目录 分类预测 | MATLAB实现SSA-CNN麻雀算法优化卷积神经网络数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现SSA-CNN麻雀算法优化卷积神经网络数据分类预测&#xff0c;多特…

2023年中国家用智能微投市场销售概况分析:家用智能微投销量为727万台,销售额为131亿元[图]

随着中国主机游戏市场的开放、电影市场的逐步繁荣&#xff0c;大屏幕带来的体验远高于电视&#xff0c;智能微投设备将成为主机游戏玩家、电影爱好者的选择。2022年&#xff0c;我国家用智能微投销量为727万台&#xff0c;销售额为131亿元&#xff1b;预计2023年家用智能微投行…

问题:remote: HTTP Basic: Access denied

参看文章&#xff1a;https://baijiahao.baidu.com/s?id1740126019873950482&wfrspider&forpc 解决方法一 (最有效) 输入&#xff1a;git config --system --unset credential.helper 再次进行 Git 操作&#xff0c;输入正确的用户名&#xff0c;密码即可。

免费使用,媲美Midjourney!微软在Bing Chat等提供—DALL-E 3

微软在官网宣布&#xff0c;将OpenAI最新模型DALL-E 3集成在Bing Chat和Bing Image Create中&#xff0c;并免费提供给用户使用。 据悉&#xff0c;DALL-E 3是一款类Midjourney产品&#xff0c;通过文本就能生成二次元、3D、朋克、涂鸦、素描、黑白、极简、印象派、位面像素等…

【Phoenix】在Kerberos认证下使用JDBC连接Phoenix 和 Phoenix各数据类型测试表创建

本案例使用的是CDH集群。 phoenix语法 一、Phoenix连接sqlline # 先检查一下kerberos cache是否过期了。 klist# 使用Phoenix的sqlline连接集群 sqlline.py zkhost1,zkhost2,zkhost3:2181二、sqlline中创建测试表 -- 查看帮助 !help-- 查看所有表 !tables-- 创建schema CRE…

IS-IS

二、IS-IS中的DIS与OSPF中的DR Level-1和Level-2的DIS是分别选举的&#xff0c;用户可以为不同级别的DIS选举设置不同的优先级。DIS的选举规则如下&#xff1a;DIS优先级数值最大的被选为DIS。如果优先级数值最大的路由器有多台&#xff0c;则其中MAC地址最大的路由器会成为DI…

算法竞赛备赛进阶之数字三角形模型训练

目录 1.数字三角形 2.摘花生.1015 3.最低通行费 4.方格取数 在算法竞赛中&#xff0c;有时候会遇到一些图形相关的题目&#xff0c;需要运用图论相关的知识进行求解。今天我们将一起探讨一个比较常见的模型——数字三角形模型。 在数字三角形模型中&#xff0c;每个位置的…

Redis 群集模式

目录 1 Redis 群集模式 1.1 集群的作用&#xff0c;可以归纳为两点 1.2 Redis集群的数据分片 2 搭建Redis 群集模式 2.1 开启群集功能 2.2 启动redis节点 2.3 启动集群 2.4 测试群集 1 Redis 群集模式 集群&#xff0c;即Redis Cluster&#xff0c;是Redis 3.0开始引入…

Android攻城狮学鸿蒙 -- 点击事件

具体参考&#xff1a;华为官网学习地址 1、点击事件&#xff0c;界面跳转 对于一个按钮设置点击事件&#xff0c;跳转页面。但是onclick中&#xff0c;如果pages前边加上“/”&#xff0c;就没法跳转。但是开发工具加上“/”才会给出提示。不知道是不是开发工具的bug。&#…

用正则表达式验证用户名和跨域postmessage

正则验证用户名 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </hea…