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

OpenCV直方图计算函数calcHist的使用

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

功能描述

图像的直方图是一种统计表示方法,用于展示图像中不同像素强度(通常是灰度值或色彩强度)出现的频率分布。具体来说,它将图像的整个色调范围(如0到255对于8位灰度图像)划分为若干个离散的bins(或区间),然后统计每个bin内像素值出现的次数,并以柱状图的形式展示出来。

通过图像的直方图,我们可以直观地了解到图像的亮度分布、对比度信息以及色彩分布情况。例如,如果一个图像的直方图集中在较暗的色调上,说明图像整体偏暗;如果直方图覆盖了较广的范围且分布均匀,表明图像具有良好的动态范围和对比度。

直方图对于图像处理和分析非常重要,常用于自动曝光、图像均衡化(如直方图均衡化)、图像分割、颜色校正等多种图像处理任务中。

calcHist函数

cv::calcHist函数用于计算一个或多个数组的直方图

函数原型1

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 
)		

参数1

  • 参数 images 源图像。它们都应该具有相同的深度,即CV_8U,CV_16U或CV_32F,并且具有相同的尺寸. 每个数组可以有任意数量的通道。

  • 参数 nimages 源图像个数.

  • 参数 channels 计算直方图的各个维度上所选择的通道列表.第一个数组的通道编号从0开始,一直到images[0].channels()-1;第二个数组的通道编号则从images[0].channels()开始,一直到images[0].channels() + images[1].channels()-1,以此类推.
    对于第一个图像数组images[0],其通道编号从0开始,一直到该数组通道数减一。
    第二个图像数组images[1]的通道编号紧接着第一个数组的通道编号之后,从images[0].channels()开始,直到images[0].channels() + images[1].channels()-1。
    同样的规则应用于后续的图像数组,每个数组的通道编号都是紧接在前一个数组的通道编号之后。
    这样的编号方式允许在计算直方图或其他涉及跨多个图像的通道操作时,可以统一地引用所有图像的通道,而不需要单独考虑每个图像的通道编号。这在处理复杂图像分析任务时特别有用,比如计算多图像的联合直方图或特征提取等。

  • 参数 mask 可选参数掩码。如果矩阵不为空,它必须是一个与images[i]相同尺寸的8位数组。非零的掩码元素标记出了将在直方图中计数的数组元素。.

  • 参数hist 输出的直方图,它是一个稠密或稀疏的dims维数组.

  • 参数dims 直方图的维度必须是正数,并且不能超过CV_MAX_DIMS(在当前OpenCV版本中等于32).

  • 参数histSize 在每一维度上的直方图大小的数组。

  • 参数ranges 数组ranges包含了dims个数组,每个数组表示直方图在对应维度上的bin边界。当直方图是均匀的(uniform=true),对于每个维度i,只需要指定第0个直方图bin的下界(包含) L 0 L_0 L0和最后一个binhistSize[i]-1的上界(不包含) U histSize [ i ] − 1 U_{\texttt{histSize}[i]-1} UhistSize[i]1。也就是说,在均匀直方图的情况下,ranges[i]是一个包含2个元素的数组,分别表示该维度上bin的起始和结束边界。
    然而,当直方图是非均匀的(uniform=false),ranges[i]则包含histSize[i]+1个元素: L 0 , U 0 = L 1 , U 1 = L 2 , . . . , U histSize[i] − 2 = L histSize[i] − 1 , U histSize[i] − 1 L_0, U_0=L_1, U_1=L_2, ..., U_{\texttt{histSize[i]}-2}=L_{\texttt{histSize[i]}-1}, U_{\texttt{histSize[i]}-1} L0,U0=L1,U1=L2,...,UhistSize[i]2=LhistSize[i]1,UhistSize[i]1。这里的Lj和Uj分别表示第j个bin的下界和上界。在非均匀直方图中,数组中的元素若不在 L 0 L_0 L0 U histSize[i] − 1 U_{\texttt{histSize[i]}-1} UhistSize[i]1之间,则不会被计入直方图.

  • 参数 uniform 这是一个标志,指示直方图是否为均匀直方图(参见上述说明)

  • 参数 accumulate 累积标志。如果设置了这个标志,那么在分配直方图时,直方图不会在开始时被清零。这个特性使你能够在不同时刻从多组数组中计算单一的直方图,或者随时间更新直方图。

函数原型2

这是一个重载成员函数,提供是为了方便使用。它与上述函数的不同之处仅在于它接受的参数类型。

此版本的函数使用SparseMat作为输出类型。

在OpenCV中,SparseMat是一种专门用于存储稀疏矩阵的容器。与常规的矩阵存储方式相比,SparseMat在存储和处理包含大量零值或无效值的大型矩阵时更加高效。它仅存储非零或有效元素及其位置,从而显著减少了内存占用和计算成本。

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

参数2

  • 参数 images 源图像。它们都应该具有相同的深度,即CV_8U,CV_16U或CV_32F,并且具有相同的尺寸. 每个数组可以有任意数量的通道。

  • 参数 nimages 源图像个数.

  • 参数 channels 计算直方图的各个维度上所选择的通道列表.第一个数组的通道编号从0开始,一直到images[0].channels()-1;第二个数组的通道编号则从images[0].channels()开始,一直到images[0].channels() + images[1].channels()-1,以此类推.
    对于第一个图像数组images[0],其通道编号从0开始,一直到该数组通道数减一。
    第二个图像数组images[1]的通道编号紧接着第一个数组的通道编号之后,从images[0].channels()开始,直到images[0].channels() + images[1].channels()-1。
    同样的规则应用于后续的图像数组,每个数组的通道编号都是紧接在前一个数组的通道编号之后。
    这样的编号方式允许在计算直方图或其他涉及跨多个图像的通道操作时,可以统一地引用所有图像的通道,而不需要单独考虑每个图像的通道编号。这在处理复杂图像分析任务时特别有用,比如计算多图像的联合直方图或特征提取等。

  • 参数 mask 可选参数掩码。如果矩阵不为空,它必须是一个与images[i]相同尺寸的8位数组。非零的掩码元素标记出了将在直方图中计数的数组元素。.

  • 参数hist 输出的直方图,使用SparseMat作为输出类型.

  • 参数dims 直方图的维度必须是正数,并且不能超过CV_MAX_DIMS(在当前OpenCV版本中等于32).

  • 参数histSize 在每一维度上的直方图大小的数组。

  • 参数ranges 数组ranges包含了dims个数组,每个数组表示直方图在对应维度上的bin边界。当直方图是均匀的(uniform=true),对于每个维度i,只需要指定第0个直方图bin的下界(包含) L 0 L_0 L0和最后一个binhistSize[i]-1的上界(不包含) U histSize [ i ] − 1 U_{\texttt{histSize}[i]-1} UhistSize[i]1。也就是说,在均匀直方图的情况下,ranges[i]是一个包含2个元素的数组,分别表示该维度上bin的起始和结束边界。
    然而,当直方图是非均匀的(uniform=false),ranges[i]则包含histSize[i]+1个元素: L 0 , U 0 = L 1 , U 1 = L 2 , . . . , U histSize[i] − 2 = L histSize[i] − 1 , U histSize[i] − 1 L_0, U_0=L_1, U_1=L_2, ..., U_{\texttt{histSize[i]}-2}=L_{\texttt{histSize[i]}-1}, U_{\texttt{histSize[i]}-1} L0,U0=L1,U1=L2,...,UhistSize[i]2=LhistSize[i]1,UhistSize[i]1。这里的Lj和Uj分别表示第j个bin的下界和上界。在非均匀直方图中,数组中的元素若不在 L 0 L_0 L0 U histSize[i] − 1 U_{\texttt{histSize[i]}-1} UhistSize[i]1之间,则不会被计入直方图.

  • 参数 uniform 这是一个标志,指示直方图是否为均匀直方图(参见上述说明)

  • 参数 accumulate 累积标志。如果设置了这个标志,那么在分配直方图时,直方图不会在开始时被清零。这个特性使你能够在不同时刻从多组数组中计算单一的直方图,或者随时间更新直方图。

函数原型3

这是一个重载的成员函数,提供以方便使用。它与上述函数的不同之处仅在于它接受的参数类型。

此版本的函数仅支持均匀直方图。

ranges参数可以是一个空向量,或者是一个包含histSize.size()*2个元素的扁平化向量(即histSize.size()对元素)。每一对元素中的第一个和第二个元素分别指定了对应维度的下界和上界。

void cv::calcHist	
(InputArrayOfArrays 	images,const std::vector< int > & 	channels,InputArray 	mask,OutputArray 	hist,const std::vector< int > & 	histSize,const std::vector< float > & 	ranges,bool 	accumulate = false 
)		

参数3

  • 参数 images 源图像。它们都应该具有相同的深度,即CV_8U,CV_16U或CV_32F,并且具有相同的尺寸. 每个数组可以有任意数量的通道。

  • 参数 channels 计算直方图的各个维度上所选择的通道列表.第一个数组的通道编号从0开始,一直到images[0].channels()-1;第二个数组的通道编号则从images[0].channels()开始,一直到images[0].channels() + images[1].channels()-1,以此类推.
    对于第一个图像数组images[0],其通道编号从0开始,一直到该数组通道数减一。
    第二个图像数组images[1]的通道编号紧接着第一个数组的通道编号之后,从images[0].channels()开始,直到images[0].channels() + images[1].channels()-1。
    同样的规则应用于后续的图像数组,每个数组的通道编号都是紧接在前一个数组的通道编号之后。
    这样的编号方式允许在计算直方图或其他涉及跨多个图像的通道操作时,可以统一地引用所有图像的通道,而不需要单独考虑每个图像的通道编号。这在处理复杂图像分析任务时特别有用,比如计算多图像的联合直方图或特征提取等。

  • 参数 mask 可选参数掩码。如果矩阵不为空,它必须是一个与images[i]相同尺寸的8位数组。非零的掩码元素标记出了将在直方图中计数的数组元素。.

  • 参数hist 输出的直方图,使用SparseMat作为输出类型.

  • 参数histSize 在每一维度上的直方图大小的数组。

  • 参数ranges 数组ranges包含了dims个数组,每个数组表示直方图在对应维度上的bin边界。当直方图是均匀的(uniform=true),对于每个维度i,只需要指定第0个直方图bin的下界(包含) L 0 L_0 L0和最后一个binhistSize[i]-1的上界(不包含) U histSize [ i ] − 1 U_{\texttt{histSize}[i]-1} UhistSize[i]1。也就是说,在均匀直方图的情况下,ranges[i]是一个包含2个元素的数组,分别表示该维度上bin的起始和结束边界。
    然而,当直方图是非均匀的(uniform=false),ranges[i]则包含histSize[i]+1个元素: L 0 , U 0 = L 1 , U 1 = L 2 , . . . , U histSize[i] − 2 = L histSize[i] − 1 , U histSize[i] − 1 L_0, U_0=L_1, U_1=L_2, ..., U_{\texttt{histSize[i]}-2}=L_{\texttt{histSize[i]}-1}, U_{\texttt{histSize[i]}-1} L0,U0=L1,U1=L2,...,UhistSize[i]2=LhistSize[i]1,UhistSize[i]1。这里的Lj和Uj分别表示第j个bin的下界和上界。在非均匀直方图中,数组中的元素若不在 L 0 L_0 L0 U histSize[i] − 1 U_{\texttt{histSize[i]}-1} UhistSize[i]1之间,则不会被计入直方图.

  • 参数 accumulate 累积标志。如果设置了这个标志,那么在分配直方图时,直方图不会在开始时被清零。这个特性使你能够在不同时刻从多组数组中计算单一的直方图,或者随时间更新直方图。

代码示例

#include "opencv2/core/utility.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int _brightness = 100;
int _contrast   = 100;
Mat image;
/* brightness/contrast callback function */
static void updateBrightnessContrast( int /*arg*/, void* )
{int histSize   = 64;int brightness = _brightness - 100;int contrast   = _contrast - 100;/** The algorithm is by Werner D. Streidt* (http://visca.com/ffactory/archives/5-99/msg00021.html)*/double a, b;if ( contrast > 0 ){double delta = 127. * contrast / 100;a            = 255. / ( 255. - delta * 2 );b            = a * ( brightness - delta );}else{double delta = -128. * contrast / 100;a            = ( 256. - delta * 2 ) / 255.;b            = a * brightness + delta;}Mat dst, hist;image.convertTo( dst, CV_8U, a, b );imshow( "image", dst );calcHist( &dst, 1, 0, Mat(), hist, 1, &histSize, 0 );Mat histImage = Mat::ones( 200, 320, CV_8U ) * 255;normalize( hist, hist, 0, histImage.rows, NORM_MINMAX, CV_32F );histImage = Scalar::all( 255 );int binW  = cvRound( ( double )histImage.cols / histSize );for ( int i = 0; i < histSize; i++ )rectangle( histImage, Point( i * binW, histImage.rows ), Point( ( i + 1 ) * binW, histImage.rows - cvRound( hist.at< float >( i ) ) ), Scalar::all( 0 ), -1, 8, 0 );imshow( "histogram", histImage );
}
const char* keys = { "{help h||}{@image|baboon.jpg|input image file}" };
int main( int argc, const char** argv )
{// Load the source image. HighGUI use.image = imread( "/media/dingxin/data/study/OpenCV/sources/images/white.jpg", cv::IMREAD_GRAYSCALE );if ( image.empty() ){std::cerr << "Cannot read image file" << std::endl;return -1;}Size sz2Sh( 300, 400 );resize( image, image, sz2Sh, 0, 0, INTER_LINEAR_EXACT );namedWindow( "image", 0 );namedWindow( "histogram", 0 );createTrackbar( "brightness", "image", &_brightness, 200, updateBrightnessContrast );createTrackbar( "contrast", "image", &_contrast, 200, updateBrightnessContrast );updateBrightnessContrast( 0, 0 );waitKey();return 0;
}

运行结果

原图:
在这里插入图片描述

直方图:
在这里插入图片描述
你可以调整亮度的滑动块,或者对比度的滑动块,来观察直方图的变化,从而更好地去理解直方图的概念。

相关文章:

OpenCV直方图计算函数calcHist的使用

操作系统&#xff1a;ubuntu22.04OpenCV版本&#xff1a;OpenCV4.9IDE:Visual Studio Code编程语言&#xff1a;C11 功能描述 图像的直方图是一种统计表示方法&#xff0c;用于展示图像中不同像素强度&#xff08;通常是灰度值或色彩强度&#xff09;出现的频率分布。具体来说…...

09 docker 安装tomcat 详解

目录 一、安装tomcat 1. tomcat镜像的获取 2. docker创建容器实列 3. 访问测试 404错误 4. 解决方案 5. 使用免修改版容器镜像 5.1. 运行实列的创建 5.2. 出现问题及解决&#xff1a; 6. 验证 OK 一、安装tomcat 1. tomcat镜像的获取 docker search tomcat #docker …...

44.实现管理HOOK点的链表对象

上一个内容&#xff1a;43.实现HOOK接管寄存器数据 以 43.实现HOOK接管寄存器数据 它的代码为基础进行修改 首先创建一个类 这里创建的名为HOOKPOINT.h HOOKPOINT.cpp文件里面的内容 #include "pch.h" #include "HOOKPOINT.h"HOOKPOINT::HOOKPOINT() {…...

Unity小知识

1.当我们把摄像机的内容渲染到RenderTexture上而不是屏幕上时,那么相机的Aspect默认会设置成和RenderTexture的分辨率一样.不过最终如果把RenderTexture作为贴图贴到模型上去的时候还是会被UV拉伸和缩小的。 2.要想自定义UnityPackage的内容&#xff0c;只要找到UnityProject/L…...

【Jupyter Notebook与Git完美融合】在Notebook中驾驭版本控制的艺术

标题&#xff1a;【Jupyter Notebook与Git完美融合】在Notebook中驾驭版本控制的艺术 Jupyter Notebook是一个流行的开源Web应用程序&#xff0c;允许用户创建和共享包含实时代码、方程、可视化和解释性文本的文档。而Git是一个广泛使用的分布式版本控制系统&#xff0c;用于跟…...

Python开发者必看:内存优化的实战技巧

更多Python学习内容&#xff1a;ipengtao.com Python是一种高级编程语言&#xff0c;以其易读性和强大的功能而广受欢迎。然而&#xff0c;由于其动态类型和自动内存管理&#xff0c;Python在处理大量数据或高性能计算时&#xff0c;内存使用效率可能不如一些低级语言。本文将介…...

Golang | Leetcode Golang题解之第214题最短回文串

题目&#xff1a; 题解&#xff1a; func shortestPalindrome(s string) string {n : len(s)fail : make([]int, n)for i : 0; i < n; i {fail[i] -1}for i : 1; i < n; i {j : fail[i - 1]for j ! -1 && s[j 1] ! s[i] {j fail[j]}if s[j 1] s[i] {fail[i…...

【ajax实战08】分页功能

本文章目标&#xff1a;点击上/下一页按钮&#xff0c;实现对应页面的变化 实现基本步骤&#xff1a; 一&#xff1a;保存并设置文章总条数 设置一个全局变量&#xff0c;将服务器返回的数据返回给全局变量 二&#xff1a;点击下一页&#xff0c;做临界值判断&#xff0c;并…...

基于Hadoop平台的电信客服数据的处理与分析②项目分析与设计---需求分析-项目场景引入

任务描述 需求分析是软件生命周期中一个非常重要的过程&#xff0c;它决定着整个软件项目的质量&#xff0c;也是整个软件开发的成败所在。本环节任务是完成软件需求规格说明书。 知识点 &#xff1a;软件需求规格说明书的编写 重 点 &#xff1a;软件需求规格说明书内容的…...

debug-mmlab

mmyolo bug1: MMYOLO for yolov5 instance segmentation on balloon dataset getting this error "ValueError: Key img_path is not in available keys. solution: pip install albumentations1.3.1 reference...

年轻人为什么那么爱喝奶茶?

作者 | 艾泊宇 为什么年轻人那么爱喝奶茶&#xff1f;答案很简单&#xff1a;对他们来说&#xff0c;奶茶之于年轻人&#xff0c;正如白酒之于中年人。 奶茶不仅仅是一种饮料&#xff0c;它已经演化成一种文化现象&#xff0c;代表着温暖和爱的象征&#xff0c;甚至在某种程度上…...

手写数组去重

方法1-判断相邻元素 function _deleteRepeat(arr){if(!Array.isArray(arr)){throw new Error(参数必须是数组)}let res[];// 使用slice创建arr的副本&#xff0c;并排序let sortArrarr.slice().sort((a,b)>a-b);for(let i0;i<sortArr.length;i){if(isortArr.length-1||s…...

Firewalld 防火墙

1. 概述 在 RHEL7 系统中&#xff0c;firewalld 防火墙取代了传统的 iptables 防火墙。iptables 的防火墙策略是通过内核层面的 netfilter 网络过滤器来处理的&#xff0c;而 firewalld 则是通过内核层面的 nftables 包过滤框架来处理。firewalld 提供了更为丰富的功能和动态更…...

Hive查询优化 - 面试工作不走弯路

引言&#xff1a;Hive作为一种基于Hadoop的数据仓库工具&#xff0c;广泛应用于大数据分析。然而&#xff0c;由于其依赖于MapReduce框架&#xff0c;查询的性能可能会受到影响。为了确保Hive查询能够高效运行&#xff0c;掌握查询优化技巧至关重要。在日常工作中&#xff0c;高…...

【VUE3】uniapp + vite中 uni.scss 使用 /deep/ 不生效(踩坑记录三)

vite 中使用 /deep/ 进行样式穿透报错 原因&#xff1a;vite 中不支持&#xff0c;换成 ::v-deep 或:deep即可...

容器部署rabbitmq集群迁移

1、场景&#xff1a; 因业务需要&#xff0c;要求把rabbitmq-A集群上的数据迁移到rabbitmq-B集群上&#xff0c;rabbitmq的数据包括元数据&#xff08;RabbitMQ用户、vhost、队列、交换和绑定&#xff09;和消息数据&#xff0c;而消息数据存储在单独的消息存储库中。 2、迁移要…...

DP:背包问题----0/1背包问题

文章目录 &#x1f497;背包问题&#x1f49b;背包问题的变体&#x1f9e1;0/1 背包问题的数学定义&#x1f49a;解决背包问题的方法&#x1f499;例子 &#x1f497;解决背包问题的一般步骤&#xff1f;&#x1f497;例题&#x1f497;总结 ❤️❤️❤️❤️❤️博客主页&…...

React antd umi 监听当前页面离开,在菜单栏提示操作

需求是我这里有个页面&#xff0c;离开当前页面之后&#xff0c;需要在菜单栏显示个提示&#xff0c;也就是Tour const [unblock, setUnblock] useState<() > void>(() > () > {});const [next, setNext] useState();useEffect(() > {const unblockHandler…...

在 Windows PowerShell 中模拟 Unix/Linux 的 touch 命令

在 Unix 或 Linux 系统中&#xff0c;touch 命令被广泛用于创建新文件或更新现有文件的时间戳。不过&#xff0c;在 Windows 系统中&#xff0c;尤其是在 PowerShell 环境下&#xff0c;并没有内置的 touch 命令。这篇博客将指导你如何在 Windows PowerShell 中模拟 touch 命令…...

鸿蒙NEXT

[中国&#xff0c;东莞&#xff0c;2024年6月24日] 华为开发者大会&#xff08;HDC&#xff09;正式开幕&#xff0c;带来全新的 HarmonyOS NEXT、盘古大模型5.0等最创新成果&#xff0c;持续为消费者和开发者带来创新体验。 HarmonyOS NEXT 鸿蒙生态 星河璀璨 鸿蒙生态设备数…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...