PCL点云库入门——PCL库点云特征之PFH点特征直方图(Point Feature Histograms -PHF)
1、算法原理
PFH点(Point Feature Histogram)特征直方图的原理涉及利用参数化查询点与邻域点之间的空间差异,并构建一个多维直方图以捕捉点的k邻域几何属性。这个高维超空间为特征表示提供了一个可度量的信息空间,对于点云对应曲面的六维姿态,它具有不变性,并且在不同的采样密度或邻域噪声水平下表现出鲁棒性。PFH特征描述表示法基于点与其k邻域之间的关系以及它们的估计法线,简而言之,它考虑了所有估计法线方向之间的相互作用,试图捕捉最佳的样本表面变化情况,以描述样本的几何特征。因此,合成特征超空间依赖于每个点的表面法线估计质量。图1展示了查询点Pq的PFH计算影响区域,Pq以红色标记并置于圆球中心,半径为r,所有与Pq的距离小于半径r的k邻元素(即所有点)都相互连接在一个网络中。最终的PFH特征描述子是通过计算邻域内所有点对之间关系得到的直方图,公用有K*(K+1)/2个点对。
图1
PFH特征描述实现的步骤如下:
第1步:构建局部坐标系
为了描述两点Ps和Pt及与它们对应的法线Ns和Nt之间的相对偏差,我们在其中一个点上定义一个固定的 Darboux标系,为了使该坐标架被唯一的确定,如图2所示。
图2
其中u,v,w具体如下:
其中,Ps被定义为源点,Pt被定义为目标点。源点即Ps的选择是使得其关联的法线与连接两点的直线之间的角度最小。
第2步:特征描述
在第1步中的vuw坐标系下,法线Ns和Nt之间的相对偏差可以用一组角度特征描述,定义为下:
其中α和ϕ为单位向量的内积,取值范围为[-1,1],θ为角度,取值范围[-π/2,π/2];d为两点欧式距离,取值范围为(0,2r)。Pq点的PFH特征为α,θ,ϕ,d组成的四元特征。
第3步:特征编码:
为计算查询点Pq的PFH特征,根据点的四元特征(α,θ,ϕ,d)构建频率直方图,具体而言,先将<α,θ,ϕ,d>中的每个特征值范围划分为b个子区间(默认为5,可自行计算并设置),则4个特征共有b^4个区间,然后,统计对应特征值落在每个子区间的点的数目,由于<α,ϕ,θ>三个特征都是法线之间的角度息,则它们可归为同一个空间,最后,计算每一个点对的特征值,直方图中对应于该点对四个特征值区间的统计个数加1,效果图3所示。
图3
在实际工作中距离特征d通常跟设备捕获2.5D深度数据是相关的,临近点的距离d是从视点开始递增的,在不同视角下,这些值的变化意义不大,所以在扫描局部点密度影响特征时,省略距离d效果会更好。在PCL 点云库中 FPH 特征描述只用了三个角度特征,因而特征矢量是5^3=125 维,对应PCL中的pcl::PFHSignature125数据类型。内容如下:
struct PFHSignature125{float histogram[125] = {0.f};static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<PFHSignature125>; }inline PFHSignature125 () = default;friend std::ostream& operator << (std::ostream& os, const PFHSignature125& p);};
2、主要成员函数和变量
1、主要成员变量
1)、每个角度特征区间的划分数,默认为5。
int nr_subdiv_;
2)、点的PFH特征描述的占位符。
Eigen::VectorXf pfh_histogram_;
3)、PFH的4元特征的占位符。
Eigen::Vector4f pfh_tuple_;
4)、map数据类型,用于优化冗余计算的效率。
std::map<std::pair<int, int>, Eigen::Vector4f, std::less<>,Eigen::aligned_allocator<std::pair<const std::pair<int, int>, Eigen::Vector4f> > > feature_map_;
5)、中间计算结果保存的对队列。
std::queue<std::pair<int, int> > key_list_;
6)、设置最大内部缓存大小。
unsigned int max_cache_size_;
7)、设置为true表示使用缓存中间计算结果,减少冗余计算。
bool use_cache_;
2、主要成员函数
1)、设置最大内部缓存大小。默认值为2GB。
inline voidsetMaximumCacheSize (unsigned int cache_size);
2)、设置是否使用内部缓存机制减少冗余计算。
inline voidsetUseInternalCache (bool use_cache);
3)、计算点三个角度和两点之间的距离的4元特征。
bool computePairFeatures (const pcl::PointCloud<PointInT> &cloud, const pcl::PointCloud<PointNT> &normals,int p_idx, int q_idx, float &f1, float &f2, float &f3, float &f4);
4)、基于具有法线的三维点的空间邻域,估计给定点的三个角(f1, f2, f3)特征的PFH特征直方图。
void computePointPFHSignature (const pcl::PointCloud<PointInT> &cloud, const pcl::PointCloud<PointNT> &normals,const std::vector<int> &indices, int nr_split, Eigen::VectorXf &pfh_histogram);
3、主要部分代码注解
1、计算点对的四元特征
//1、计算点对的四元特征
//
template <typename PointInT, typename PointNT, typename PointOutT> bool
pcl::PFHEstimation<PointInT, PointNT, PointOutT>::computePairFeatures(const pcl::PointCloud<PointInT>& cloud, const pcl::PointCloud<PointNT>& normals,int p_idx, int q_idx, float& f1, float& f2, float& f3, float& f4)
{pcl::computePairFeatures(cloud.points[p_idx].getVector4fMap(), normals.points[p_idx].getNormalVector4fMap(),cloud.points[q_idx].getVector4fMap(), normals.points[q_idx].getNormalVector4fMap(),f1, f2, f3, f4);return (true);
}
//算法具体实现,对应1中第2步的公式;
bool pcl::computePairFeatures(const Eigen::Vector4f& p1, const Eigen::Vector4f& n1,const Eigen::Vector4f& p2, const Eigen::Vector4f& n2,float& f1, float& f2, float& f3, float& f4)
{//距离特征dEigen::Vector4f dp2p1 = p2 - p1;dp2p1[3] = 0.0f;f4 = dp2p1.norm();if (f4 == 0.0f){PCL_DEBUG("[pcl::computePairFeatures] Euclidean distance between points is 0!\n");f1 = f2 = f3 = f4 = 0.0f;return (false);}//计算ϕ角度特征Eigen::Vector4f n1_copy = n1,n2_copy = n2;n1_copy[3] = n2_copy[3] = 0.0f;float angle1 = n1_copy.dot(dp2p1) / f4;// 根据角度大小来选择源点Ps,选择角度最小的为Ps点,std::acos是递减函数float angle2 = n2_copy.dot(dp2p1) / f4;if (std::acos(std::fabs(angle1)) > std::acos(std::fabs(angle2))){// switch p1 and p2n1_copy = n2;n2_copy = n1;n1_copy[3] = n2_copy[3] = 0.0f;dp2p1 *= (-1);f3 = -angle2;}elsef3 = angle1;//创建 Darboux 坐标系 u-v-w// u = n1; v = (p_idx - q_idx) x u / || (p_idx - q_idx) x u ||; w = u x vEigen::Vector4f v = dp2p1.cross3(n1_copy);v[3] = 0.0f;float v_norm = v.norm();if (v_norm == 0.0f){PCL_DEBUG("[pcl::computePairFeatures] Norm of Delta x U is 0!\n");f1 = f2 = f3 = f4 = 0.0f;return (false);}// Normalize vv /= v_norm;Eigen::Vector4f w = n1_copy.cross3(v);// Do not have to normalize w - it is a unit vector by construction//计算θ精度特征v[3] = 0.0f;f2 = v.dot(n2_copy);w[3] = 0.0f;//计算α角度特征 4元特征(α,θ,ϕ,d)// Compute f1 = arctan (w * n2, u * n2) i.e. angle of n2 in the x=u, y=w coordinate systemf1 = std::atan2(w.dot(n2_copy), n1_copy.dot(n2_copy)); // @todo optimize thisreturn (true);
}
2、计算单点PFH特征信息
//2、计算单点PFH特征信息
//
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::PFHEstimation<PointInT, PointNT, PointOutT>::computePointPFHSignature(const pcl::PointCloud<PointInT>& cloud, const pcl::PointCloud<PointNT>& normals,const std::vector<int>& indices, int nr_split, Eigen::VectorXf& pfh_histogram)
{int h_index, h_p;//清楚上一次的PFH结果pfh_histogram.setZero();// 分解常数float hist_incr = 100.0f / static_cast<float> (indices.size() * (indices.size() - 1) / 2);std::pair<int, int> key;bool key_found = false;// Iterate over all the points in the neighborhoodfor (std::size_t i_idx = 0; i_idx < indices.size(); ++i_idx){for (std::size_t j_idx = 0; j_idx < i_idx; ++j_idx){// 无序点检测,是则跳过if (!isFinite(cloud.points[indices[i_idx]]) || !isFinite(cloud.points[indices[j_idx]]))continue;//使用缓存来加速计算if (use_cache_){// 创建map需要的键值,为点云的索引int p1, p2;// if (indices[i_idx] >= indices[j_idx])// {p1 = indices[i_idx];p2 = indices[j_idx];// }// else// {// p1 = indices[j_idx];// p2 = indices[i_idx];// }key = std::pair<int, int>(p1, p2);// 检查是否已经在map中已经估计的点对,就不需要重新计算,避免重复计算std::map<std::pair<int, int>, Eigen::Vector4f, std::less<>, Eigen::aligned_allocator<std::pair<const std::pair<int, int>, Eigen::Vector4f> > >::iterator fm_it = feature_map_.find(key);if (fm_it != feature_map_.end()){//已经有计算的直接用计算的结果pfh_tuple_ = fm_it->second;key_found = true;}else{//没有被估计过,需要计算,这对新的点对的4元特征if (!computePairFeatures(cloud, normals, indices[i_idx], indices[j_idx],pfh_tuple_[0], pfh_tuple_[1], pfh_tuple_[2], pfh_tuple_[3]))continue;key_found = false;}}else//不使用缓存,直接计算所有两对点之间的4元特征if (!computePairFeatures(cloud, normals, indices[i_idx], indices[j_idx],pfh_tuple_[0], pfh_tuple_[1], pfh_tuple_[2], pfh_tuple_[3]))continue;// 将f1, f2, f3特征归一化,并将它们存储到直方图f_index_[0] = static_cast<int> (std::floor(nr_split * ((pfh_tuple_[0] + M_PI) * d_pi_)));if (f_index_[0] < 0) f_index_[0] = 0;if (f_index_[0] >= nr_split) f_index_[0] = nr_split - 1;f_index_[1] = static_cast<int> (std::floor(nr_split * ((pfh_tuple_[1] + 1.0) * 0.5)));if (f_index_[1] < 0) f_index_[1] = 0;if (f_index_[1] >= nr_split) f_index_[1] = nr_split - 1;f_index_[2] = static_cast<int> (std::floor(nr_split * ((pfh_tuple_[2] + 1.0) * 0.5)));if (f_index_[2] < 0) f_index_[2] = 0;if (f_index_[2] >= nr_split) f_index_[2] = nr_split - 1;// 特征直方图统计h_index = 0;h_p = 1;for (const int& d : f_index_){h_index += h_p * d;h_p *= nr_split;}//统计直方图结果pfh_histogram[h_index] += hist_incr;//缓存新计算点对的4元特征if (use_cache_ && !key_found){//保存4元特征信息到map中,根据Key由点的索引值feature_map_[key] = pfh_tuple_;// 将计算过的点对保存起来,为了防止冗余计算key_list_.push(key);// 如果缓存的量操过设置的最大值,需要清除最先缓存的值if (key_list_.size() > max_cache_size_){//删除最先缓存的元素。feature_map_.erase(key_list_.front());key_list_.pop();}}}}
}
3、计算所有点的PFH特征信息
//3、计算所有点的PFH特征信息
//
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::PFHEstimation<PointInT, PointNT, PointOutT>::computeFeature(PointCloudOut& output)
{// 清除特征map信息feature_map_.clear();std::queue<std::pair<int, int> > empty;std::swap(key_list_, empty);//初始化PFH特征维度大小5^3=125,并初始化为{0}pfh_histogram_.setZero(nr_subdiv_ * nr_subdiv_ * nr_subdiv_);//分配需要参数vector的大小std::vector<int> nn_indices(k_);std::vector<float> nn_dists(k_);output.is_dense = true;// 稠密点云数据if (input_->is_dense){// 对每一个索引值进行遍历执行for (std::size_t idx = 0; idx < indices_->size(); ++idx){//点的最近邻域搜索if (this->searchForNeighbors((*indices_)[idx], search_parameter_, nn_indices, nn_dists) == 0){//如果最近邻域搜索失败,则将该点的PFH值重置为NAN无效值,跳过该点for (Eigen::Index d = 0; d < pfh_histogram_.size(); ++d)output.points[idx].histogram[d] = std::numeric_limits<float>::quiet_NaN();output.is_dense = false;continue;}// 估计每个patch的PFH特征computePointPFHSignature(*surface_, *normals_, nn_indices, nr_subdiv_, pfh_histogram_);// 将PFH特征特征信息拷贝到输出的数据中for (Eigen::Index d = 0; d < pfh_histogram_.size(); ++d)output.points[idx].histogram[d] = pfh_histogram_[d];}}else{// Iterating over the entire index vectorfor (std::size_t idx = 0; idx < indices_->size(); ++idx){//点的最近邻域搜索和无效值判断if (!isFinite((*input_)[(*indices_)[idx]]) ||this->searchForNeighbors((*indices_)[idx], search_parameter_, nn_indices, nn_dists) == 0){//如果最近邻域搜索失败,则将该点的PFH值重置为NAN无效值,跳过该点for (Eigen::Index d = 0; d < pfh_histogram_.size(); ++d)output.points[idx].histogram[d] = std::numeric_limits<float>::quiet_NaN();output.is_dense = false;continue;}// 估计每个patch的PFH特征computePointPFHSignature(*surface_, *normals_, nn_indices, nr_subdiv_, pfh_histogram_);// 将PFH特征特征信息拷贝到输出的数据中for (Eigen::Index d = 0; d < pfh_histogram_.size(); ++d)output.points[idx].histogram[d] = pfh_histogram_[d];}}
}
4、算法使用示例
/*****************************************************************//**
* \file PCLPFHFeaturemain.cpp
* \brief
*
* \author YZS
* \date January 2025
*********************************************************************/
#include<iostream>
#include <vector>
#include <ctime>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/auto_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/pfh.h>//包含PFH计算的模块
using namespace std;
void PCLPFHFeature()
{//加载点云数据pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>());std::string fileName = "E:/fragment.pcd";pcl::io::load(fileName, *cloud);std::cout << "Cloud Size:" << cloud->points.size() << std::endl;//计算点云数据的法向量pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> ne;ne.setInputCloud(cloud);pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>());ne.setSearchMethod(tree);pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);ne.setRadiusSearch(0.02);ne.compute(*cloud_normals);//计算点云数据的PFH特征信息//pcl::PFHEstimation PFH特征估计对象pcl::PFHEstimation<pcl::PointXYZRGB, pcl::Normal, pcl::PFHSignature125> pfh_estimation;// 设置需要计算PFH的点云数据pfh_estimation.setInputCloud(cloud);// 设置需要计算PFH的点云数据对应的法向量pfh_estimation.setInputNormals(cloud_normals);//设置最近KDtree方法pfh_estimation.setSearchMethod(tree);//创建保存PFH特征信息的对象pfh_featurespcl::PointCloud<pcl::PFHSignature125>::Ptr pfh_features(new pcl::PointCloud<pcl::PFHSignature125>);//设置搜索的邻域半径pfh_estimation.setRadiusSearch(0.08);//设置启用缓存计算结果,加快速度pfh_estimation.setUseInternalCache(true);// 计算PFH特征信息将结构保存到pfh_features中pfh_estimation.compute(*pfh_features);// 输出索引为2000的PFH特征信息pcl::PFHSignature125 descriptor = (*pfh_features)[2000];std::cout << descriptor << std::endl;
}
int main(int argc, char* argv[])
{PCLPFHFeature();std::cout << "Hello PCL World!" << std::endl;std::system("pause");return 0;
}
结果:只输出部分
5、PFH特征的的优缺点
1、PFH的优点
1、该方法的优点在于对噪声和遮挡具有较强的抗干扰能力,适用于复杂场景下的三维物体识别与分类。
2、PFH的缺点:
1、计算复杂度较高。假定点云P由n个点构成,且点云分布均匀,每个点在半径为r的邻域内平均能找到k个近邻点。那么,对于每个点计算点特征直方图(PFH)的时间复杂度为O(k²),因此,整个点云的PFH理论计算复杂度为O(nk²)。在实时或接近实时的应用场景中,对于密集点云的PFH计算,O(nk²)的计算复杂度显然不尽如人意,成为了一个显著的性能瓶颈。
2、存在大量重复计算。在计算PFH的三个特征元素时,邻域内任意两点都需要分别计算其三个特征元素值。即便相邻点的邻域可能不完全相同,但它们往往包含许多相同的近邻点(随着邻域半径的增加,这种重复的近邻点会更多)。这些共同的近邻点会被重复配对并计算特征元素值。尽管相关论文和PCL库中引入了高速缓存机制,将重复计算的开销转化为查找开销,但整体效率提升并不显著。
至此完成第十四节PCL库点云特征之PFH点特征直方图学习,下一节我们将进入《PCL库中点云特征之FPFH特征描述》的学习。
相关文章:
PCL点云库入门——PCL库点云特征之PFH点特征直方图(Point Feature Histograms -PHF)
1、算法原理 PFH点(Point Feature Histogram)特征直方图的原理涉及利用参数化查询点与邻域点之间的空间差异,并构建一个多维直方图以捕捉点的k邻域几何属性。这个高维超空间为特征表示提供了一个可度量的信息空间,对于点云对应曲面…...
基于vue的商城小程序的毕业设计与实现(源码及报告)
环境搭建 ☞☞☞ Vue入手篇(一),防踩雷(全网最详细教程)_vue force-CSDN博客 目录 一、功能介绍 二、登录注册功能 三、首页 四、项目截图 五、源码获取 一、功能介绍 用户信息展示:页面顶部设有用户头像和昵称展示区,方便用户识别…...
04-Linux系统编程之进程
一、进程的概述 1.什么是进程 进程:即进行中的程序,可执行文件从开始运行到结束运行这段过程就叫进程。 2.程序和进程的区别 程序:存储在磁盘上、占磁盘空间、静态的。如:我们编写的C语言代码就是程序,存储在我们电…...
分布式ID生成-雪花算法实现无状态
雪花算法这里不再赘述,其缺点是有状态(多副本隔离时,依赖手动配置workId和datacenterId),代码如下: /*** 雪花算法ID生成器*/ public class SnowflakeIdWorker {/*** 开始时间截 (2017-01-01)*/private st…...
在Linux系统上使用nmcli命令配置各种网络(有线、无线、vlan、vxlan、路由、网桥等)
1、更新于2024/5/13,新增Veth Pair配置 2、更新于2024/5/19,修复NetworkManager接管网络配置无效的错误 3、更新于2024/5/20,新增Ubuntu两种版本下NetworkManager接管网络的配置 目录 一、配置NetworkManager接管网络(选&…...
计算机网络 (25)IPV6
前言 IPv6,全称为“互联网协议第6版”(Internet Protocol Version 6),是由互联网工程任务组(IETF)设计的用于替代IPv4的下一代IP协议。 一、产生背景 IPv4,即互联网协议第4版,是现行…...
Git 安装 操作 命令 远程仓库 多人协作
Git作用 Git诞生史 很多人都知道,Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了。Linus虽然创建了Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在…...
线性回归的改进-岭回归
2.10 线性回归的改进-岭回归 学习目标 知道岭回归api的具体使用 1 API sklearn.linear_model.Ridge(alpha1.0, fit_interceptTrue,solver"auto", normalizeFalse) 具有l2正则化的线性回归alpha:正则化力度,也叫 λ λ取值:0~1 1~10solver:会根…...
【LC】2469. 温度转换
题目描述: 给你一个四舍五入到两位小数的非负浮点数 celsius 来表示温度,以 摄氏度(Celsius)为单位。 你需要将摄氏度转换为 开氏度(Kelvin)和 华氏度(Fahrenheit),并以…...
【在安卓平台上,Unity与C/C++编写的.so动态库交互的实现】
在安卓平台上,Unity与C/C++编写的.so动态库交互的实现,通常通过JNI(Java Native Interface)和P/Invoke机制来完成。通过这种方式,C#脚本可以调用C/C++代码中的函数,并与本地库进行交互。 以下是一个简单的步骤演示,展示如何在Unity中与安卓平台上的.so动态库交互。 步…...
【llm/ollama/qwen】在本地部署qwen2.5-coder并在vscode中集成使用代码提示功能
说在前面 操作系统:windows11ollama版本:0.5.4vscode版本:1.96.2continue插件版本:0.8.66 ollama安装 访问官网,点击下载安装即可 默认装在了C盘,比较蛋疼;但是可以指定路径安装:Ol…...
C语言练习:求数组的最大值与最小值
文章目录 1. 提出任务2. 完成任务2.1 方法一:通过返回结构体指针来间接返回结果2.1.1 编写程序,实现功能2.1.2 运行程序,查看结果 2.2 方法二:通过参数传递数组,并在函数中修改传入的参数2.2.1 编写程序,实…...
【TCP】SYN、ACK、FIN、RST、PSH、URG的全称
在 TCP 协议中,SYN、ACK、FIN、RST、PSH 和 URG 都是控制标志位(Flags),每个标志位对应不同的功能。它们的全称如下: URG:(URGent)紧急 ACK:(ACKnowledgment)确认 PSH:(PuSH)推送 RS…...
Re77 读论文:LoRA: Low-Rank Adaptation of Large Language Models
诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名:LoRA: Low-Rank Adaptation of Large Language Models ArXiv网址:https://arxiv.org/abs/2106.09685 官方GitHub网站(包含在RoBERTa、DeBERTa、GPT-2上用Lora微调…...
《OpenCV 4.10.0 实例:开启图像处理新世界》
《OpenCV 4.10.0 实例:开启图像处理新世界》 一、OpenCV 4.10.0 初印象二、环境搭建:开启 OpenCV 之旅(一)不同系统安装指南(二)配置细节与技巧 三、基础图像处理实例(一)图像读取、…...
硬件电路(3)-PT100温度采集电路
一、概述 PT100是铂热电阻,它的阻值会随着温度的变化而改变。PT后的100即表示它在0℃时阻值为100欧姆,在100℃时它的阻值约为138.5欧姆。它的工作原理:当PT100在0摄氏度的时候它的阻值为100欧姆,它的阻值会随着温度上升而成匀速增…...
计算机网络——数据链路层-流量控制和可靠传输
一、流量控制 流量控制是指由接收方及时控制发送方发送数据的速率,使接收方来得及接受。 • 停止等待流量控制 • 滑动窗口流量控制 1、停止—等待流量控制 停止-等待流量控制的基本原理是发送方每发出一帧后,就要等待接收方的应答信号ÿ…...
sqlserver数据库备份和还原
一、备份 打开smss,选中数据库-任务-备份 地址选择默认如:C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Backup\ (远程服务器文件夹,非本机文件夹) PS:备份后编辑下数据 二、还原 PS:如果提示数…...
Python爬虫基础——认识网页结构(各种标签的使用)
1、添加<div>标签的代码定义了两个区块的宽度和高度均为100px,边框的格式也相同,只是区块中显示的内容不同; 2、添加<ul>和<ol>标签分别用于定义无序列表和有序列表。<il>标签位于<ul>标签或<ol>标签之…...
Linux双端口服务器:端口1的文件系统目录挂载到端口2
目录 一、服务器安装NFS服务并配置二、文件挂载三、持久化挂载总结为什么服务器配置多个端口 目前有一台服务器,不过他设置了两个SSH的端口,通过下面方法可以让这两个端口连接的主机能够共享同一个文件系统,原本这两个端口的文件系统是隔离的…...
unity学习11:地图相关的一些基础
目录 1 需要从 unity的 Asset Store 下载资源 1.1 下载资源 1.2 然后可以从 package Manager 里选择下载好的包,import到项目里 2 创建地形 2.1 创建地形 2.2 地形 Terrain大小 2.3 各种网格的尺寸大小 2.4 比较这个地形尺寸和创建的其他物体的大小对比 3 …...
如何在 Spring Cloud Gateway 中创建全局过滤器、局部过滤器和自定义条件过滤器
Spring Cloud Gateway 是一个功能强大的 API 网关,能够处理 HTTP 请求、响应及路由。通过过滤器机制,您可以在请求和响应过程中进行各种处理操作,如记录日志、身份验证、限流等。Spring Cloud Gateway 提供了三种主要类型的过滤器:…...
总分支机构跨网文件交换解决方案几个关键要点
跨国公司和国内大型集团的日常运营中,总分支机构之间的文件交换已成为必不可少的环节。然而,跨网文件交换面临着诸多挑战,比如安全性、效率、合规性、管理便捷性、技术兼容性和成本效益等。 为了解决这些问题,在挑选总分支机构跨网…...
机器人手眼标定
机器人手眼标定 一、机器人手眼标定1. 眼在手上标定基本原理2. 眼在手外标定基本原理 二、眼在手外标定实验三、标定精度分析 一、机器人手眼标定 要实现由图像目标点到实际物体上抓取点之间的坐标转换,就必须拥有准确的相机内外参信息。其中内参是相机内部的基本参…...
将 Docker 数据迁移到新磁盘:详细操作指南
将 Docker 数据迁移到新磁盘:详细操作指南 背景 在容器化应用的部署中,Docker 通常将数据存储在默认的 /var/lib/docker 目录。然而,随着容器数量的增加和镜像的累积,该目录可能会迅速占满系统磁盘空间,从而影响系统…...
AWS re:Invent 的创新技术
本月早些时候,Amazon 于 12 月 1 日至 5 日在内华达州拉斯维加斯举行了为期 5 天的 re:Invent 大会。如果您从未参加过 re:Invent 会议,那么最能描述它的词是“巨大”——不仅从与会者人数(60,000 人)来看&…...
无人机低小慢探测难题!
一、探测难度增加 由于无人机的雷达散射面积小,雷达在探测时接收到的反射信号相对较弱。这使得雷达系统需要更高的灵敏度和更先进的信号处理算法才能有效捕捉到无人机的信号。在复杂环境中,如城市、山区或海洋,背景噪声和干扰源众多…...
第2章:Go语言基础语法
第2章:Go语言基础语法 1. 变量和数据类型 1.1 基本数据类型 Go语言提供了以下基本数据类型: // 整数类型 var intVar1 int // 根据系统位数,32或64位 var intVar2 int8 // -128 到 127 var intVar3 int16 // -32768 到 32767 var i…...
RP2K:一个面向细粒度图像的大规模零售商品数据集
这是一种用于细粒度图像分类的新的大规模零售产品数据集。与以往专注于相对较少产品的数据集不同,我们收集了2000多种不同零售产品的35万张图像,这些图像直接在真实的零售商店的货架上拍摄。我们的数据集旨在推进零售对象识别的研究,该研究具…...
pnpm安装与使用
pnpm官网 全局安装 npm install pnpm -g设置源 // 查看源 pnpm config get registry // 切换淘宝源 pnpm config set registry https://registry.npmmirror.com/ 移除 pnpm remove 包名称 // 移除包 pnpm remove 包名称 --global // 移除全局包 更新 pnpm up // 更新所有…...
c# 服务中启动exe窗体程序
Windows服务默认在会话0(Session 0)中运行,这是一个隔离的环境,旨在防止服务与应用程序和用户会话交互,从而提高系统的稳定性和安全性。由于这个原因,直接从服务启动的GUI应用程序将不会显示,因…...
使用pip-chill清理pip依赖包,清理不使用的包
最近需要精简python项目的依赖,需要清理一下哪些代码里面没有使用的包,查询了一下,记录 pip-chill 是一个用于管理 Python 项目中依赖项的工具,可以帮助您保持所需依赖项的清单简洁明了,并删除不必要的依赖。 1. 安装 …...
【算法题系列】LeetCode 5.最长回文子串|JavaScript 5种思路实现
题目描述 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1: 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2: 输入: "cbbd" 输出: &q…...
QT6编程入门(一)
1、QT6介绍 1.1、QT6概述 Qt 是一个跨平台的 C 应用程序框架,它被广泛用于开发图形用户界面(GUI)应用程序,同时也可以用于开发非GUI程序,如控制台工具和服务器。Qt 被设计成能够在多种操作系统上运行,包括…...
串口通信控制LED、马达、蜂鸣器、风扇
1.STM32U575RITx 设置引脚 编写main.c //对fputc重写,方便调用printf函数 int fputc(int ch, FILE* F){HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 10);return ch; } //main函数的主要循环while (1){char whole_buf[128];memset(whole_buf, 0, siz…...
每日一题:BM2 链表内指定区间反转
文章目录 链表区间反转教学内容1. 任务描述2. 题目分析例子 3. 思路4. 详细步骤4.1 创建虚拟头节点4.2 寻找反转区间的前一个节点4.3 反转区间中的节点4.4 重新连接链表4.5 返回结果 5. 代码实现6. 代码解析6.1 初始化虚拟头节点6.2 寻找反转区间的前一个节点6.3 反转区间中的节…...
Cherno C++学习笔记 P50 C++当中的动态库
在上一篇文章当中我们学习了C当中是如何使用静态库的,这一篇我们会讲一下如何使用动态库,并同样用GLFW这个已有的库来举例子。 有了静态库的经验,其实动态库就好理解和使用多了。这两者的区别是,静态链接发生在编译的时候&#x…...
【Flink CDC】Flink CDC的Schema Evolution表结构演变的源码分析和流程图
Flink CDC版本:3.2.1 说明:本文从SchemaOperator接收到,表结构变更事件开始,表结构变更事件应由source端产生,本文不讨论。 可以先看流程图,研究源码。 参考文章: Flink cdc3.0动态变更表结构—…...
计算机网络 (27)IP多播
前言 IP多播(也称多址广播或组播)技术是一种允许一台或多台主机(多播源)发送单一数据包到多台主机(一次性的、同时的)的TCP/IP网络技术。 一、基本概念 定义:多播作为一点对多点的通信ÿ…...
当算法遇到线性代数(四):奇异值分解(SVD)
SVD分解的理论与应用 线性代数系列相关文章(置顶) 1.当算法遇到线性代数(一):二次型和矩阵正定的意义 2.当算法遇到线性代数(二):矩阵特征值的意义 3.当算法遇到线性代数࿰…...
鸿蒙操作系统(HarmonyOS)
鸿蒙操作系统(HarmonyOS)是华为公司推出的一款面向未来、面向全场景的分布式操作系统。它旨在为用户提供一个更加智能、便捷和安全的操作环境,支持多种终端设备之间的无缝协作。在鸿蒙应用开发中,ArkUI作为官方推荐的用户界面开发…...
通义灵码在跨领域应用拓展之物联网篇
目录 一.引言 二.通义灵码简介 三.通义灵码在物联网领域的设备端应用 1.传感器数据采集 (1).不同类型传感器的数据读取 (2).数据转换与预处理 2.设备控制指令接收和执行 (1).指令解析与处理 (2).设备动作执行 四.通义灵码在物联网领域的云端平台应用 1.数据存储和管…...
CSS语言的数据库交互
CSS语言的数据库交互:一种新潮流的探索 引言 在现代网页开发中,CSS(层叠样式表)无疑是构建优美和响应式网页的重要工具。然而,关于CSS和数据库之间的直接交互,尽管并不是一种常见的做法,却引发…...
[SMARTFORMS] 创建二维码
我们可以使用事务码SE73创建二维码 选择系统条形码,点击"更改"按钮 点击 创建选项 选择"新" 输入二维码名称和简短描述,点击"确认"按钮 选择"QR CODE 2005",点击"确认"按钮 选择"No…...
数据项目相关的AWS云计算架构设计
电商数据平台架构 高性能:使用Amazon EC2的计算优化实例处理业务逻辑和数据计算,搭配Amazon ElastiCache内存缓存,加速数据读取。应用负载均衡器(ALB)在EC2实例间分发流量,实现负载均衡。高可用性…...
智慧农业应用场景|珈和科技高标准农田信息化监管平台解决方案
近年来,珈和科技持续深耕农业领域,深耕农业时空大数据服务。 珈和利用遥感大数据、云计算、移动互联网、物联网、人工智能等先进技术,搭建“天空地一体化”监测体系,并创新建设了150的全球领先算法模型,可为100多种农作…...
C++ operator = 返回void 会发生什么?
1.operator 正常情况 #include <iostream> using namespace std;class Box { public:Box(double L) : length(L) {}Box(const Box& b){}Box& operator (const Box&){return *this;}public:double length; // 长度 };int main() {Box box1(1.0);Box box2(…...
Scala 模式匹配
Scala 模式匹配 引言 Scala 作为一种多范式编程语言,不仅支持面向对象编程,还融合了函数式编程的特性。在其丰富的特性集中,模式匹配(Pattern Matching)尤为引人注目,它是一种在许多编程语言中都有应用的编程范式,但在 Scala 中得到了特别强大的支持。模式匹配允许开发…...
微信小程序中 “页面” 和 “非页面” 的区别
微信小程序中 “页面” 和 “非页面” 的区别,并用表格进行对比。 核心概念: 页面 (Page): 页面是微信小程序中用户可以直接交互的视图层,也是小程序的基本组成部分。每个页面都有自己的 WXML 结构、WXSS 样式和 JavaScript 逻辑…...
解耦Java应用程序的方法和技巧
解耦 Java 应用程序是一项重要的设计原则是减少组件之间的依赖关系,使系统更加模块化、灵活和可维护。通过分离,您可以更轻松地更改、扩展或测试应用程序的各个部分,而不会影响其他部分。 分离 Java 应用程序需要应用减少组件之间直接依赖关系…...