点云处理PCL常用函数与工具
点云处理PCL常用函数与工具
文章目录
- 点云处理PCL常用函数与工具
- 前言
- 一、点云读取与保存
- 数据读取
- 数据保存
- 自定义的点云保存格式
- 二、点云显示
- 点云显示-根据颜色
- 点云显示-根据指定轴数值
- 点云显示-根据指定信息显示
- 多组点云显示
- 三、点云滤波
- 直通滤波
- 统计滤波
- 均匀下采样滤波
- VoxelGrid 点云体素下采样滤波
- RadiusOutlierRemoval 半径滤波
- ConditionRemoval 条件滤波器
- 平面投影滤波器
- 球面投影滤波器
- 四、点云轮廓提取
- 点云轮廓点提取
- 提取凸包轮廓
- 提取凹包轮廓
- 常用处理工具
- 点云沿指定轴旋转
- 点云沿向量旋转
- 贪婪三角剖分
前言
本文主要记录pcl点云处理常用工具,在此将每种方法写为一个函数,便于使用的时候直接调用。
一、点云读取与保存
数据读取
数据读取的类型包括.pcd和.ply文件
void loadFile(std::string path, pcl::PointCloud<POINTTYPE>::Ptr cloud) {std::cout << path << endl;std::string fileType = path.substr(path.find_last_of('.') + 1);//获取文件后缀if (fileType == "ply") {if (pcl::io::loadPLYFile <POINTTYPE>(path, *cloud) == -1){std::cout << "Cloud reading .ply failed." << std::endl;}}else if (fileType == "pcd") {if (pcl::io::loadPCDFile <POINTTYPE>(path, *cloud) == -1){std::cout << "Cloud reading .pcd failed." << std::endl;}}
}
数据保存
数据保存的格式将根据自定义的文件名后缀确定,包括ply和pcd两种类型
int saveFile(std::string path, pcl::PointCloud<POINTTYPE>::Ptr cloud) {std::string fileType = path.substr(path.find_last_of('.') + 1);//获取文件后缀if (fileType == "ply") {if (pcl::io::savePLYFile(path, *cloud) == -1){std::cout << "Cloud saving .ply failed." << std::endl;return 0;}}else if (fileType == "pcd") {if (pcl::io::savePCDFile(path, *cloud) == -1){std::cout << "Cloud saving .pcd failed." << std::endl;return 0;}}return 1;
}
以上两种点云保存的数据格式包括:
pcl::PointXYZI
pcl::PointXYZRGB
pcl::PointXYZ
自定义的点云保存格式
那么除了以上几种点云数据格式,如果需要保存自定义的数据格式,例如在包含坐标、法线、颜色、强度信息外、额外的保存一些其信息(标签、id)等信息那么就需要对保存的点云格式进行自定义,具体方法如下:
//首先定义新增数据格式的结构体
#define PCL_ADD_LABEL \struct \{ \int p_label;\int p_id;\}; \
// 定义点云数据类型的结构体
struct PointXYZRGBINormalLI
{PCL_ADD_POINT4D;PCL_ADD_RGB;PCL_ADD_INTENSITY;PCL_ADD_NORMAL4D;PCL_ADD_LABEL;EIGEN_MAKE_ALIGNED_OPERATOR_NEW
}EIGEN_ALIGN16;
POINT_CLOUD_REGISTER_POINT_STRUCT(PointXYZRGBINormalLI,(float, x, x)(float, y, y)(float, z, z)(uint8_t, b, b)(uint8_t, g, g)(uint8_t, r, r)(float, rgb, rgb)(float, intensity, intensity)(float, normal_x, normal_x)(float, normal_y, normal_y)(float, normal_z, normal_z)(int, p_label, p_label)(int, p_id, p_id)
)
以上数据结构体几乎包含了点特征的基本信息,如果有其他信息需要保存可自行修改。
随后保存的时候将 POINTTYPE的类型改为PointXYZRGBINormalLI即可
pcl::PointCloud<PointXYZRGBINormalSI>::Ptr point_cloud(new pcl::PointCloud<PointXYZRGBINormalSI>);
pcl::io::loadPCDFile(pcd_path, *point_cloud);// 点云读取
saveFile(pcd_path, point_cloud);//点云保存
二、点云显示
点云显示-根据颜色
void ShowPCLPointsXYZRGB(pcl::PointCloud<pcl::PointXYZRGB>::Ptr color_cloud)
{cout << "point size:" << color_cloud->size() << endl;boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer1(new pcl::visualization::PCLVisualizer("3D Viewer"));viewer1->addPointCloud<pcl::PointXYZRGB>(color_cloud);viewer1->setBackgroundColor(0, 0, 0); // 设置点云大小viewer1->addCoordinateSystem(0);while (!viewer1->wasStopped()){viewer1->spinOnce(100);}
}
根据点云指定轴数值进行颜色显示
点云显示-根据指定轴数值
void ShowPCLPointsXYZRGB(pcl::PointCloud<pcl::PointXYZ>::Ptr color_cloud)
{cout << "point size:" << color_cloud->size() << endl;boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer1(new pcl::visualization::PCLVisualizer("3D Viewer"));viewer1->addPointCloud<pcl::PointXYZ>(color_cloud);viewer1->setBackgroundColor(0, 0, 0); // 设置点云大小viewer1->addCoordinateSystem(0);while (!viewer1->wasStopped()){viewer1->spinOnce(100);}
}
点云显示-根据指定信息显示
void ShowPCLPointsInput(pcl::PointCloud<pcl::PointXYZI>::Ptr color_cloud,std::string str)
{// str: x,y,z intensitystd::cout << "point size:" << color_cloud->size() << endl;boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer1(new pcl::visualization::PCLVisualizer("3D Viewer"));pcl::visualization::PointCloudColorHandlerGenericField<PointT> fildColor(Input_cloud, str); // 按照x字段进行渲染viewer1->addPointCloud<PointT>(color_cloud, fildColor, "Input_RGB"); // 显示点云,其中fildColor为颜色显示viewer1->setBackgroundColor(0, 0, 0); // 设置点云大小viewer1->addCoordinateSystem(0);while (!viewer1->wasStopped()){viewer1->spinOnce(100);}
}
多组点云显示
给定一个vector容器,里面用于存储多组不同的点云,然后为每组点云随机赋予颜色
#define Random(x) (rand() % x)
void ShowClusterPointsXYZRGB(std::vector<pcl::PointCloud<pcl::PointXYZ>>& cloud_clusters) {pcl::PointCloud<pcl::PointXYZRGB>::Ptr pointXYZRBG(new pcl::PointCloud<pcl::PointXYZRGB>);pcl::PointXYZRGB point;cout << "End show particle size:" << cloud_clusters.size() << endl;for (int i = 0; i < cloud_clusters.size(); i++) {int color_B = Random(255);int color_G = Random(255);int color_R = Random(255);for (int j = 0; j < cloud_clusters[i].size(); j++) {point.x = cloud_clusters[i].points[j].x;point.y = cloud_clusters[i].points[j].y;point.z = cloud_clusters[i].points[j].z;point.r = color_R;point.g = color_G;point.b = color_B;pointXYZRBG->push_back(point);}}ShowPCLPointsXYZRGB(pointXYZRBG);
}
三、点云滤波
直通滤波
// 点云直通滤波
void parrProcessZ(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, std::vector<float>& start_end, pcl::PointCloud<pcl::PointXYZ>::Ptr pass_cloud) {pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>());pcl::PassThrough<pcl::PointXYZ>pass;//沿z轴过滤pass.setInputCloud(cloud); //输入点云pass.setFilterFieldName("z"); // 沿Z轴滤波,也可沿 X Ypass.setFilterLimits(start_end[0], start_end[1]); //选取0-1之间//pass.setFilterLimitsNegative(true); //可选择0-1之间数据保留还是舍弃pass.filter(*pass_cloud); //过滤
}
统计滤波
void StatisticalFilterCloud(pcl::PointCloud<pcl::PointXYZRGB>::Ptr inputCloud, int k, int std, pcl::PointCloud<pcl::PointXYZRGB>::Ptr &outCloud)
{pcl::PointCloud<pcl::PointXYZRGB>::Ptr filterCloud(new pcl::PointCloud<pcl::PointXYZRGB>);pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB> sta;sta.setInputCloud(inputCloud);sta.setMeanK(k);sta.setStddevMulThresh(std);sta.filter(*filterCloud);outCloud = filterCloud;
}
均匀下采样滤波
void UniformSamplingFilterCloud(pcl::PointCloud<PointT>::Ptr inputCloud, pcl::PointCloud<PointT>::Ptr &outCloud)
{pcl::UniformSampling<PointT> us; //创建滤波器对象us.setInputCloud(inputCloud); //设置待滤波点云us.setRadiusSearch(0.005f); //设置滤波球半径us.filter(*outCloud); //执行滤波
}
VoxelGrid 点云体素下采样滤波
void VoxelGridFilterCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud, pcl::PointCloud<pcl::PointXYZ>::Ptr &outCloud)
{pcl::VoxelGrid<pcl::PointXYZ> vg; //创建滤波器对象vg.setInputCloud(inputCloud); //设置待滤波点云vg.setLeafSize(0.05f, 0.05f, 0.05f); //设置体素大小vg.filter(*outCloud); //执行滤波
}
RadiusOutlierRemoval 半径滤波
void RadiusOutlierFilterCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud, pcl::PointCloud<pcl::PointXYZ>::Ptr &outCloud)
{pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror; //创建滤波器对象ror.setInputCloud(inputCloud); //设置待滤波点云ror.setRadiusSearch(0.02); //设置查询点的半径范围ror.setMinNeighborsInRadius(5); //设置判断是否为离群点的阈值,即半径内至少包括的点数//ror.setNegative(true); //默认false,保存内点;true,保存滤掉的外点ror.filter(*outCloud); //执行滤波
}
ConditionRemoval 条件滤波器
#include <pcl/filters/conditional_removal.h>
void ConditionalFilterCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud, pcl::PointCloud<pcl::PointXYZ>::Ptr &outCloud)
{/*创建条件限定下的滤波器*/pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());//创建条件定义对象range_cond//为条件定义对象添加比较算子range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(newpcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::GT, -0.1)));//添加在x字段上大于 -0.1 的比较算子range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(newpcl::FieldComparison<pcl::PointXYZ>("x", pcl::ComparisonOps::LT, 1.0)));//添加在x字段上小于 1.0 的比较算子pcl::ConditionalRemoval<pcl::PointXYZ> cr; //创建滤波器对象cr.setCondition(range_cond); //用条件定义对象初始化cr.setInputCloud(inputCloud); //设置待滤波点云//cr.setKeepOrganized(true); //设置保持点云的结构//cr.setUserFilterValue(5); //将过滤掉的点用(5,5,5)代替cr.filter(*outCloud); //执行滤波,保存滤波结果于cloud_filtered
平面投影滤波器
void SACMODEL_PLANEFilterCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud, pcl::PointCloud<pcl::PointXYZ>::Ptr &outCloud)
{//平面投影//创建 x+y+z=0 平面pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());coefficients->values.resize(4); //设置模型系数的大小coefficients->values[0] = 1.0; //x系数coefficients->values[1] = 1.0; //y系数coefficients->values[2] = 1.0; //z系数coefficients->values[3] = 0.0; //常数项//投影滤波pcl::ProjectInliers<pcl::PointXYZ> proj;//创建投影滤波器对象proj.setModelType(pcl::SACMODEL_PLANE); //设置对象对应的投影模型proj.setInputCloud(inputCloud); //设置输入点云proj.setModelCoefficients(coefficients);//设置模型对应的系数proj.filter(*outCloud); //执行投影滤波//圆柱投影
}
球面投影滤波器
void SACMODEL_SPHEREFilterCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud, pcl::PointCloud<pcl::PointXYZ>::Ptr &outCloud)
{//--------- 创建球面模型 (x - x0)^2 + (y - y0)^2 + (z - z0)^2 = r^2 -------------pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());coefficients->values.resize(4);coefficients->values[0] = 0;coefficients->values[1] = 0;coefficients->values[2] = -1.0;coefficients->values[3] = 2.0;//========= 创建球面模型 (x - x0)^2 + (y - y0)^2 + (z - z0)^2 = r^2 ============//-------------------------------- 执行投影滤波 --------------------------------PointCloudT::Ptr cloud_projected(new PointCloudT);pcl::ProjectInliers<pcl::PointXYZ> proj;proj.setModelType(pcl::SACMODEL_SPHERE); //球面模型proj.setInputCloud(inputCloud);proj.setModelCoefficients(coefficients);proj.filter(*outCloud);
}
四、点云轮廓提取
点云轮廓点提取
void GetEageXYZ(pcl::PointCloud<pcl::PointXYZ>cloud_clusters, pcl::PointCloud<pcl::PointXYZ>& boundPointsXYZ) {pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> est;pcl::search::Search<pcl::PointXYZ>::Ptr GetEageTree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZ> >(new pcl::search::KdTree<pcl::PointXYZ>);pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normEst;pcl::PointCloud<pcl::Normal>::Ptr beGetEageNormals(new pcl::PointCloud<pcl::Normal>);pcl::PointCloud<pcl::Boundary> boundaries;pcl::PointCloud<pcl::PointXYZ>::Ptr beGetEageClusters(new pcl::PointCloud<pcl::PointXYZ>);beGetEageClusters = cloud_clusters.makeShared(); //use .makeShared() -> pcl::PointCloud<pcl::PointXYZ> -> pcl::PointCloud<pcl::PointXYZ>::Ptr normEst.setInputCloud(beGetEageClusters);normEst.setSearchMethod(GetEageTree);normEst.setKSearch(9);normEst.compute(*beGetEageNormals);est.setInputCloud(beGetEageClusters);est.setInputNormals(beGetEageNormals);/*M_PI_2 */est.setAngleThreshold(M_PI_2); ///在这里 由于构造函数已经对其进行了初始化 为Π/2 ,必须这样 使用 M_PI/2 M_PI_2 est.setSearchMethod(GetEageTree);est.setKSearch(30); //一般这里的数值越高,最终边界识别的精度越好 20// est.setRadiusSearch(everagedistance); //搜索半径est.compute(boundaries);pcl::PointCloud<pcl::PointXYZ>::Ptr boundPoints(new pcl::PointCloud<pcl::PointXYZ>);int countBoundaries = 0;for (int j = 0; j < beGetEageClusters->size(); j++) {uint8_t x = (boundaries.points[j].boundary_point);int a = static_cast<int>(x); //该函数的功能是强制类型转换if (a == 1){boundPoints->push_back(beGetEageClusters->points[j]);}}boundPointsXYZ = *boundPoints;
}
提取凸包轮廓
/** 提取轮廓凸包*/
void getPointCloudConvexBoundary(pcl::PointCloud<pcl::PointXYZ> inputCluster, pcl::PointCloud<pcl::PointXYZ>& outputTbBoundary) {// 采用Graham凸包检测算法获取点云的2D凸包轮廓pcl::ConvexHull<pcl::PointXYZ> convexhull;convexhull.setInputCloud(inputCluster.makeShared());//载入点云convexhull.setDimension(2);//设置凸包维度为2维std::vector<pcl::Vertices> polygons;//保存凸包的容器convexhull.reconstruct(outputTbBoundary, polygons);//计算凸包结果
}
提取凹包轮廓
/** 提取轮廓凹包*/
void getPointCloudConcaveBoundary(pcl::PointCloud<pcl::PointXYZ> inputCluster, pcl::PointCloud<pcl::PointXYZ>& outputAbBoundary) {// pcl::ConcaveHull<pcl::PointXYZ> concavehull;concavehull.setInputCloud(inputCluster.makeShared());//载入点云concavehull.setDimension(2);//设置凹包维度为2维concavehull.setAlpha(2);std::vector<pcl::Vertices> polygons;//保存凹包的容器concavehull.reconstruct(outputAbBoundary, polygons);//计算凹包结果
}
常用处理工具
点云沿指定轴旋转
//点云旋转
void PointCloudRoate(pcl::PointCloud<pcl::PointXYZ>::Ptr inputcloud,int type, pcl::PointCloud<pcl::PointXYZ>::Ptr outcloud) {double angle = M_PI;Eigen::Matrix4f transform_z = Eigen::Matrix4f::Identity();//沿X旋转if (type == 1) {transform_z(1, 1) = cos(angle);transform_z(1, 2) = -sin(angle);transform_z(2, 1) = sin(angle);transform_z(2, 2) = cos(angle);pcl::transformPointCloud(*inputcloud, *outcloud, transform_z);}//沿X旋转if (type == 2) {transform_z(0, 0) = cos(angle);transform_z(0, 2) = sin(angle);transform_z(2, 0) = -sin(angle);transform_z(2, 2) = cos(angle);pcl::transformPointCloud(*inputcloud, *outcloud, transform_z);}//沿X旋转if (type == 3) {transform_z(0, 0) = cos(angle);transform_z(0, 1) = -sin(angle);transform_z(1, 0) = sin(angle);transform_z(1, 1) = cos(angle);pcl::transformPointCloud(*inputcloud, *outcloud, transform_z);}
}
点云沿向量旋转
void RoateByVector(pcl::PointCloud<PointT>::Ptr input, pcl::PointCloud<PointT>::Ptr& out,double v_y,double v_z,double v_z){//向量旋转到(0,0,1)Eigen::Vector3f vecbefore;vecbefore << v_x, v_y, v_z;Eigen::Vector3f vecafter;vecafter << 0, 0, 1;double tem = vecbefore.dot(vecafter);//分子double tep = sqrt(vecbefore.dot(vecbefore) * vecafter.dot(vecafter));//分母double angle = acos(tem / tep);if (isnan(angle))//acos取值范围[-1,1],若超出范围则越界,输出-1.#IND00{angle = acos(tep / tem);}Eigen::Vector3f axis2 = vecbefore.cross(vecafter);Eigen::Affine3f RoatTransform = Eigen::Affine3f::Identity();// Define a translation of 2.5 meters on the x axis.RoatTransform.translation() << 0, 0, 0;// The same rotation matrix as before; theta radians arround Z axisRoatTransform.rotate(Eigen::AngleAxisf(angle, axis2.normalized()));pcl::transformPointCloud(*input, *out, RoatTransform);
贪婪三角剖分
void Greedy_projection_triangulation(pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud, pcl::PointCloud<pcl::PointXYZ>::Ptr &out_Cloud) {// 法线估计pcl::search::Search<pcl::PointXYZ>::Ptr InputTree = boost::shared_ptr<pcl::search::Search<pcl::PointXYZ> >(new pcl::search::KdTree<pcl::PointXYZ>);pcl::PointCloud <pcl::Normal>::Ptr Inputnormals(new pcl::PointCloud <pcl::Normal>);pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;normal_estimator.setSearchMethod(InputTree);normal_estimator.setInputCloud(inputCloud);normal_estimator.setKSearch(20);normal_estimator.compute(*Inputnormals);// 将点云位姿、颜色、法线信息连接到一起pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);pcl::concatenateFields(*inputCloud, *Inputnormals, *cloud_with_normals);pcl::search::KdTree<pcl::PointNormal>::Ptr tree(new pcl::search::KdTree<pcl::PointNormal>);tree->setInputCloud(cloud_with_normals);//三角化pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;pcl::PolygonMesh triangles;gp3.setSearchRadius(1);gp3.setMu(5); //设置被样本点搜索其邻近点的最远距离为2.5,为了适应点云密度的变化gp3.setMaximumNearestNeighbors(100); //设置样本点可搜索的邻域个数为100gp3.setMinimumAngle(M_PI / 18); // 设置三角化后得到的三角形内角的最小的角度为10°gp3.setMaximumAngle(2 * M_PI / 3); // 设置三角化后得到的三角形内角的最大角度为120°gp3.setMaximumSurfaceAngle(M_PI / 4); // 设置某点法线方向偏离样本点法线的最大角度45°,如果超过,连接时不考虑该点gp3.setNormalConsistency(false); //设置该参数为true保证法线朝向一致,设置为false的话不会进行法线一致性检查gp3.setInputCloud(cloud_with_normals); //设置输入点云为有向点云gp3.setSearchMethod(tree); //设置搜索方式gp3.reconstruct(triangles); //重建提取三角化boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));viewer->setBackgroundColor(0, 0, 0); //viewer->addPolygonMesh(triangles, "wangge"); // 基于三角剖分的曲面重建while (!viewer->wasStopped()){viewer->spinOnce(100);}//std::vector<int> parts = gp3.getPartIDs();//获得重建后每点的 ID, Parts 从 0 开始编号, a-1 表示未连接的点。/*获得重建后每点的状态,取值为 FREE 、 FRINGE 、 BOUNDARY 、 COMPLETED 、 NONE 常量,其中 NONE 表示未定义,FREE 表示该点没有在 三 角化后的拓扑内,为自由点,COMPLETED 表示该点在三角化后的拓扑内,并且邻域都有拓扑点,BOUNDARY 表示该点在三角化后的拓扑边缘,FRINGE 表示该点在 三 角化后的拓扑内,其连接会产生重叠边。*///std::vector<int> states = gp3.getPointStates();// First get the xyz informationpcl::PointCloud<pcl::PointXYZ> xyz_cloud;pcl::fromPCLPointCloud2(triangles.cloud, xyz_cloud);out_Cloud = xyz_cloud.makeShared();
}
持续更新…
相关文章:
点云处理PCL常用函数与工具
点云处理PCL常用函数与工具 文章目录点云处理PCL常用函数与工具前言一、点云读取与保存数据读取数据保存自定义的点云保存格式二、点云显示点云显示-根据颜色点云显示-根据指定轴数值点云显示-根据指定信息显示多组点云显示三、点云滤波直通滤波统计滤波均匀下采样滤波VoxelGri…...

FyListen 在 MVP 架构中的内存优化表现
FyListen 在 MVP 中的内存优化表现 本文只是分享个人开源框架的内存优化测试,你可以直接跳到最后,参考内存泄漏的分析过程! 项目地址: https://github.com/StudyNoteOfTu/fylisten2-alpha1 由于使用到 AOP,所以直接…...

Qt代码单元测试以及报告生成
简介 单元测试是所有测试中最底层的一类测试,是第一个环节,也是最重要的一个环节,是唯一一次有保证能够代码覆盖率达到100%的测试,是整个软件测试过程的基础和前提,单元测试防止了开发的后期因bug过多而失控࿰…...

vscode构建Vue3.0项目(vite,vue-cli)
构建Vue3.0项目构建Vue3.0项目1.使用Vite构建vue项目的方法以及步骤1. 安装vite2. 运行vite vue 项目3.说明2.使用vue-cli构建vue项目的方法以及步骤1.安装全局vue cli —— 脚手架2、VSCode3.报错4.运行构建Vue3.0项目 1.使用Vite构建vue项目的方法以及步骤 1. 安装vite n…...
【2023】华为OD机试真题Java-题目0215-优雅数组
优雅数组 题目描述 如果一个数组中出现次数最多的元素出现大于等于 k k k 次,被称为k-优雅数组, k k k 也可以被称为优雅阈值。 例如,数组[1, 2, 3, 1, 2, 3, 1],它是一个3-优雅数组,因为元素1出现次数大于等于3次...

通过Prowork每日自动提醒待处理工作任务
对于中小团队来说,由于不需要繁琐的流程和高频的异地沟通,需要一款更适合中小团队的日程和项目管理工具。而Prowork就是这样一款敏捷高效的协同平台。Prowork与以往各种项目管理⼯具最⼤的不同在于,其弱化流程和弱化权限的特性,不…...
Linux自定义系统服务
文章目录一. Linux系统服务二. 自定义系统服务一. Linux系统服务 Linux 系统服务有时也称为守护程序,是在Linux启动时自动加载并在Linux退出时自动停止的系统任务,CentOS 7.x开始,CentOS开始使用 systemd服务来代替 daemon ,原来…...
mongodb lambda 查询插件
需求背景需要一个像mybatis plus 一样的基于lambda, 且面向对象的查询mongo数据的插件。在网上找了很久,没有发现有类似功能的插件。于是自己手写了一个,借助mongoTemplate屏蔽了底层查询语句的实现细节。在此基础上,实现了查询的统一封装。技…...

C++设计模式(16)——责任链模式
亦称: 职责链模式、命令链、CoR、Chain of Command、Chain of Responsibility 意图 责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理…...

springmvc+jsp电影院购票售票选座推荐网站java ssm
本电影购票推荐网站以SSM作为框架,B/S模式以及MySql作为后台运行的数据库。本系统主要包括以下功能模块:个人中心、用户管理、电影信息管理、电影类型管理、影院信息管理、系统管理、订单管理等模块,通过这些模块的实现能够基本满足日常电影购…...

ASEMI高压MOS管4N65SE,4N65SE参数,4N65SE特征
编辑-Z ASEMI高压MOS管4N65SE参数: 型号:4N65SE 漏极-源极电压(VDS):650V 栅源电压(VGS):30V 漏极电流(ID):4A 功耗(PD…...

第46章 自定义静态与数据库动态授权依赖注入的定义实现
1 数据库动态授权表授权原理 2 准备工作 2.1 重构Program.cs using Framework.Infrastructure.Extensions; var builder WebApplication.CreateBuilder(args); //如果启动项中不存在“appsettings.json”文件,则通过.Net(Core)的内置方法自动新建“appsettings.…...
Go语言面试题
请解释 Go 语言中的 goroutine 是什么。请解释 Go 语言中的 channel 是什么,并举例说明它的用途。请解释 Go 语言中的 interface 是什么,并举例说明它的用途。请解释 Go 语言中的 map 和 slice 是什么,并举例说明它们的用途。请解释 Go 语言中…...

Kubernetes入门级教程
Kubernetes入门级教程1. Introduction1.1 概述1.2 关键字介绍2. Cluster Install2.1 Big Data -- Postgres3. 基础知识3.1 Pod3.2 控制器3.3 通讯模式3.4 服务发现4. Command4.0 编辑文件4.1 在宿主机执行命令4.2 创建资源对象4.3 查询资源对象4.4 查询资源描述4.5 修改资源4.6…...
15个顶级思维模型
今天给大家分享几个思维模型,无论是数分、数开还是其他岗位,都会有所启发。 查理芒格认为,每个学科都是从一个独特的角度去切入了解这个世界,都是一个摸象的瞎子。 要超越普通人的认知决策,就必须掌握多个核心思维模…...

外贸谷歌优化,外贸google SEO优化费用是多少?
本文主要分享关于做外贸网站的谷歌seo成本到底需要投入多少这一件事。 本文由光算创作,有可能会被剽窃和修改,我们佛系对待这种行为吧。 那么外贸google SEO优化费用是多少? 答案是:2w~25w。 好,看到这个答案先别激…...
华为OD机试 - 统计匹配的二元组个数(Python) | 机试题算法思路
最近更新的博客 华为OD机试 - 招聘(Python) | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 五键键盘 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 热点网络统计 | 备考思路,刷题要点,答疑 【新解法】华为OD机试 - 路灯照明 | 备考思路,刷题要点,答疑 【新解…...

Java 日志简介
目录1、Slf4j2、Log4j3、LogBack4、Logback 优点5、ELK1、Slf4j slf4j 的全称是 Simple Loging Facade For Java,即它仅仅是一个为 Java 程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就比如 JDBC 一样,只是一种规则…...

HTTPS协议原理---详解六个加密方案
目录 一、HTTPS 1.加密与解密 2.我们为什么要加密? 3.常见加密方式 ①对称加密 ②非对称加密 4.数据摘要 5.数字签名 二、HTTPS的加密方案 1.只是用对称加密 2.只使用非对称加密 3.双方都使用非对称加密 4.非对称加密+对称加密 中间人攻…...
纯css实现坤坤经典动作-“铁山靠”
背景 2023年2月16日,晴,今天没有工作,一直在掘金摸鱼,摸的我好累。 不行!我得找点有意义的事情做! 此时间,我发的一条沸点竟然有小黑子给我评论,\ 我看到之后气不打一处来ÿ…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...