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

PCL从理解到应用【03】KDTree 原理分析 | 案例分析 | 代码实现

前言

本文分析KDTree的原理,集合案例深入理解,同时提供源代码。

三个案例:K近邻搜索、半径内近邻搜索、近似最近邻搜索。方法对比,如下表所示:

特性K近邻搜索半径内近邻搜索近似最近邻搜索
描述查找K个最近邻点查找指定半径内的所有点查找近似最近邻点
返回结果数量固定K个不固定,取决于半径内点的数量不固定,取决于近似效果
适用场景需要固定数量最近邻点的应用需要查找固定范围内点的应用需要快速查询的应用
精度
速度较慢(点云数据量大时)较慢(半径大时)
代码复杂度

看一下示例效果:

白色的是随机生成的原始点云,红色是查询点,绿色是找到的10个最近点。

一、KDTree 原理分析

KDTree(K-Dimensional Tree,K维树)是一种用于多维空间中数据点的快速点查找的数据结构。它是计算几何领域中的一种二叉树。 

  • 构建过程:

    • 将数据点递归地划分成两个子集,直到每个子集中的点数目小于等于一个。
    • 每次划分时,选择某个维度,将数据点按照该维度的中位数进行分割,这样一半的数据点在分割超平面的左侧,另一半在右侧。
    • 每个节点保存一个数据点及一个用于分割的维度。
  • 搜索过程:

    • 从根节点开始,递归地向下遍历树,根据查询点在当前分割维度上的值决定向左子树或右子树移动,直到达到叶节点。
    • 回溯过程中,检查是否需要跨越分割超平面搜索另一子树。
    • 使用一个优先级队列维护当前最优的 K 个最近邻点。

二、KDTree常用方法

KDTree常用的方法,汇总如下所示:

1. setInputCloud 方法
void setInputCloud(const PointCloudConstPtr &cloud, const IndicesConstPtr &indices = IndicesConstPtr())
设置输入点云数据。2. nearestKSearch 方法
int nearestKSearch(const PointT &point, int k, std::vector<int> &k_indices, std::vector<float> &k_sqr_distances) const
查找查询点的K近邻。3. radiusSearch 方法
int radiusSearch(const PointT &point, double radius, std::vector<int> &k_indices, std::vector<float> &k_sqr_distances, unsigned int max_nn = 0) const
查找查询点在指定半径内的所有近邻。4. getPointCloud 方法
const PointCloudConstPtr& getPointCloud() const
获取输入点云。5. getIndices 方法
const IndicesConstPtr& getIndices() const
获取索引。6. approxNearestSearch 方法
int approxNearestSearch(const PointT &point, int &index, float &sqr_distance) const
查找查询点的近似最近邻。近似最近邻搜索相对于精确最近邻搜索速度更快,但结果不是完全准确的。

官网:Introduction — Point Cloud Library 0.0 documentation

对应函数:Point Cloud Library (PCL): Module kdtree

  • Point Cloud Library (PCL): pcl::KdTree< PointT > Class Template Reference

三、KDTree优缺点分析

优点:

  • 高效邻近搜索: 在低维数据中,KDTree 提供了一种高效的 K 近邻和范围搜索方法。
  • 动态更新: KDTree 可以动态地插入和删除数据点,保持数据结构的有效性。
  • 适用多种距离度量: KDTree 可以使用多种距离度量,如欧氏距离、曼哈顿距离等,适应不同应用需求。

缺点:

  • 高维数据性能下降: 随着维度增加,KDTree 的性能会急剧下降,这是因为高维空间中的数据分布变得稀疏,导致分割效率降低。这种现象被称为“维度灾难”。
  • 构建和维护成本: 构建和维护 KDTree 的成本较高,尤其是在数据频繁变化的场景中。
  • 不适用于动态变化的场景: 如果数据频繁更新,KDTree 需要频繁重建,维护成本较高。

四、KDTree案例——K近邻搜索

K近邻搜索(K-Nearest Neighbors Search)是一种用于查找给定点的K个最近邻点的搜索方法,KDTree提供了一种高效的实现方式。

看一个示例深入理解,在这个示例中:

  1. 随机生成一个包含1000个点的点云。
  2. 随机选择一个查询点。
  3. 使用 kdtree.nearestKSearch 进行近似最近邻搜索,查找10个距离最近的点。
  4. 使用 pcl::visualization::PCLVisualizer 可视化原始点云、查询点和近似最近邻点。

代码示例:

#include <pcl/point_cloud.h>        // 点类型定义头文件
#include <pcl/kdtree/kdtree_flann.h> // kdtree类定义头文件
#include <pcl/visualization/pcl_visualizer.h> // PCL可视化类定义头文件#include <iostream>
#include <vector>
#include <ctime>
#include <chrono>
#include <thread>/*
函数功能:
K近邻搜索 (K-Nearest Neighbors, KNN):找到距离查询点最近的K个点。
*/int main (int argc, char** argv)
{srand(time(NULL)); // 用系统时间初始化随机种子// 创建一个PointCloud<pcl::PointXYZ>对象pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);// 随机点云生成cloud->width = 1000;  // 点云数量cloud->height = 1;    // 表示点云为无序点云cloud->points.resize(cloud->width * cloud->height);for (size_t i = 0; i < cloud->points.size(); ++i) // 循环填充点云数据{cloud->points[i].x = 1024.0f * rand() / (RAND_MAX + 1.0f); // 产生数值为0-1024的浮点数cloud->points[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f);cloud->points[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f);}// 创建KdTreeFLANN对象,并把创建的点云设置为输入pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;kdtree.setInputCloud(cloud);// 设置查询点并赋随机值pcl::PointXYZ searchPoint;searchPoint.x = 1024.0f * rand() / (RAND_MAX + 1.0f);searchPoint.y = 1024.0f * rand() / (RAND_MAX + 1.0f);searchPoint.z = 1024.0f * rand() / (RAND_MAX + 1.0f);// K近邻搜索int K = 10; // 设置K值为10,表示查找10个最近邻std::vector<int> pointIdxNKNSearch(K);         // 存储查询点近邻的索引std::vector<float> pointNKNSquaredDistance(K); // 存储近邻点对应的距离平方// 打印相关信息std::cout << "K近邻搜索,查询点为 (" << searchPoint.x << " " << searchPoint.y << " " << searchPoint.z<< "),K=" << K << std::endl;// 执行K近邻搜索if (kdtree.nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0){// 打印所有近邻坐标for (size_t i = 0; i < pointIdxNKNSearch.size(); ++i)std::cout << "    " << cloud->points[pointIdxNKNSearch[i]].x << " " << cloud->points[pointIdxNKNSearch[i]].y << " " << cloud->points[pointIdxNKNSearch[i]].z << " (距离平方: " << pointNKNSquaredDistance[i] << ")" << std::endl;}// 创建PCLVisualizer对象pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("nearestKSearch"));viewer->setBackgroundColor(0, 0, 0); // 设置背景色为黑色// 添加原始点云pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> originalColor(cloud, 255, 255, 255); // 白色viewer->addPointCloud<pcl::PointXYZ>(cloud, originalColor, "original cloud");// 添加查询点pcl::PointCloud<pcl::PointXYZ>::Ptr searchPointCloud(new pcl::PointCloud<pcl::PointXYZ>());searchPointCloud->push_back(searchPoint);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> searchPointColor(searchPointCloud, 255, 0, 0); // 红色viewer->addPointCloud<pcl::PointXYZ>(searchPointCloud, searchPointColor, "search point");viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "search point");// 添加K近邻点pcl::PointCloud<pcl::PointXYZ>::Ptr kNearestPoints(new pcl::PointCloud<pcl::PointXYZ>());for (size_t i = 0; i < pointIdxNKNSearch.size(); ++i){kNearestPoints->push_back(cloud->points[pointIdxNKNSearch[i]]);}pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> kNearestColor(kNearestPoints, 0, 255, 0); // 绿色viewer->addPointCloud<pcl::PointXYZ>(kNearestPoints, kNearestColor, "k nearest points");viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "k nearest points");// 启动可视化viewer->addCoordinateSystem(1.0);viewer->initCameraParameters();while (!viewer->wasStopped()){viewer->spinOnce(100);std::this_thread::sleep_for(std::chrono::milliseconds(100));}return 0;
}

可视化K近邻搜索的效果,如下图所示:

白色的是随机生成的原始点云,红色是查询点,绿色是找到的10个最近点。

K近邻搜索的思路流程:

  • 初始化
    • 从根节点开始,根据查询点的坐标,决定向左子树还是右子树移动。
  • 递归搜索
    • 递归地向下遍历树,直至达到叶节点。
    • 在叶节点处,计算该叶节点数据点与查询点之间的距离,将其加入优先级队列(最大堆),用于存储当前最近的K个点。
  • 回溯
    • 回溯到父节点,检查当前节点的数据点与查询点之间的距离,并更新优先级队列。
    • 判断是否需要跨越分割超平面搜索另一子树:如果查询点到分割超平面的距离小于优先级队列中最远点的距离,则跨越分割超平面,进入另一子树进行搜索。
  • 重复搜索和回溯
    • 重复上述搜索和回溯过程,直至回溯到根节点,最终优先级队列中存储的就是查询点的K个最近邻点。
         构建KDTree/    \/      \/        \节点      节点/  \      /  \/    \    /    \节点    节点  节点  节点

五、KDTree案例——近似最近邻搜索搜索

近似最近邻搜索的目标是找到查询点的近似K个最近邻点,允许一定的误差以提高搜索速度。

常见的做法是通过多次随机采样、设置较大的搜索半径或者在其他库中使用误差参数来实现近似搜索。

特点K近邻搜索近似最近邻搜索
精度中等
性能速度较慢,计算量大速度快,计算量小
应用场景需要精确结果的场景,如分类、回归等允许一定误差的快速检索,如大规模数据处理、实时应用等
优点结果精确,找到的是最邻近的K个点搜索速度快,适用于大规模数据集
缺点在高维数据中性能急剧下降,计算量大结果不够精确,存在一定误差

示例代码:

#include <pcl/point_cloud.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>
#include <chrono>
#include <thread>int main (int argc, char** argv)
{srand(time(NULL));// 创建一个PointCloud<pcl::PointXYZ>对象pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);cloud->width = 1000;cloud->height = 1;cloud->points.resize(cloud->width * cloud->height);for (size_t i = 0; i < cloud->points.size(); ++i){cloud->points[i].x = 1024.0f * rand() / (RAND_MAX + 1.0f);cloud->points[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f);cloud->points[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f);}// 创建KdTreeFLANN对象,并把创建的点云设置为输入pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;kdtree.setInputCloud(cloud);// 设置查询点并赋随机值pcl::PointXYZ searchPoint;searchPoint.x = 1024.0f * rand() / (RAND_MAX + 1.0f);searchPoint.y = 1024.0f * rand() / (RAND_MAX + 1.0f);searchPoint.z = 1024.0f * rand() / (RAND_MAX + 1.0f);// 近似最近邻搜索int K = 10;int trials = 5; // 设置尝试次数,通过增加随机性来实现近似搜索std::vector<int> pointIdxNKNSearch(K);std::vector<float> pointNKNSquaredDistance(K);std::vector<int> all_neighbors;std::vector<float> all_distances;// 多次随机采样for (int t = 0; t < trials; ++t){pcl::PointXYZ randomSearchPoint = searchPoint;randomSearchPoint.x += static_cast<float>(rand()) / RAND_MAX * 2.0 - 1.0;randomSearchPoint.y += static_cast<float>(rand()) / RAND_MAX * 2.0 - 1.0;randomSearchPoint.z += static_cast<float>(rand()) / RAND_MAX * 2.0 - 1.0;if (kdtree.nearestKSearch(randomSearchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0){all_neighbors.insert(all_neighbors.end(), pointIdxNKNSearch.begin(), pointIdxNKNSearch.end());all_distances.insert(all_distances.end(), pointNKNSquaredDistance.begin(), pointNKNSquaredDistance.end());}}// 排序并去重std::vector<std::pair<float, int>> distance_index_pairs;for (size_t i = 0; i < all_neighbors.size(); ++i){distance_index_pairs.emplace_back(all_distances[i], all_neighbors[i]);}std::sort(distance_index_pairs.begin(), distance_index_pairs.end());distance_index_pairs.erase(std::unique(distance_index_pairs.begin(), distance_index_pairs.end()), distance_index_pairs.end());// 选择前K个近似最近邻std::vector<int> final_neighbors;for (size_t i = 0; i < std::min(size_t(K), distance_index_pairs.size()); ++i){final_neighbors.push_back(distance_index_pairs[i].second);}// 创建PCLVisualizer对象pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Vis"));viewer->setBackgroundColor(0, 0, 0); // 设置背景色为黑色// 添加原始点云pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> originalColor(cloud, 255, 255, 255); // 白色viewer->addPointCloud<pcl::PointXYZ>(cloud, originalColor, "original cloud");// 添加查询点pcl::PointCloud<pcl::PointXYZ>::Ptr searchPointCloud(new pcl::PointCloud<pcl::PointXYZ>());searchPointCloud->push_back(searchPoint);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> searchPointColor(searchPointCloud, 255, 0, 0); // 红色viewer->addPointCloud<pcl::PointXYZ>(searchPointCloud, searchPointColor, "search point");viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "search point");// 添加近似最近邻点pcl::PointCloud<pcl::PointXYZ>::Ptr approxNearestPoints(new pcl::PointCloud<pcl::PointXYZ>());for (size_t i = 0; i < final_neighbors.size(); ++i){approxNearestPoints->push_back(cloud->points[final_neighbors[i]]);}pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> approxNearestColor(approxNearestPoints, 0, 255, 0); // 绿色viewer->addPointCloud<pcl::PointXYZ>(approxNearestPoints, approxNearestColor, "approx nearest points");viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "approx nearest points");// 启动可视化viewer->addCoordinateSystem(1.0);viewer->initCameraParameters();while (!viewer->wasStopped()){viewer->spinOnce(100);std::this_thread::sleep_for(std::chrono::milliseconds(100));}return 0;
}

结果可视化:

结果分析:

  • 白色的是随机生成的原始点云,红色是查询点,绿色是找到的2个最近点(本文需要找到10个点的)。
  • 允许一定误差,以提高搜索速度。
  • 在示例代码中,通过增加随机性和多次采样来实现近似搜索,最终合并和去重结果。

六、KDTree案例——半径内近邻搜索

径内近邻搜索 (Radius Search),找到指定半径内的所有点。

思路流程:

  1. 构建 KDTree:首先,构建包含所有数据点的KDTree。这一步骤将数据点按空间位置递归地分割成子区域。
  2. 查询节点搜索:从根节点开始,检查当前节点是否在查询点的半径内。如果是,则将其加入结果集中。
  3. 递归搜索:递归地检查当前节点的子节点:
    • 如果查询球体与子节点对应的空间区域相交,则继续搜索该子节点。
    • 如果查询球体与子节点对应的空间区域不相交,则跳过该子节点。
  4. 合并结果:合并所有符合条件的节点,得到最终的近邻点集合。

看一个示例深入理解,在这个示例中:

  1. 随机生成一个包含1000个点的点云。
  2. 随机选择一个查询点。
  3. 使用 kdtree.radiusSearch 进行半径内近邻搜索,半径为116。
  4. 使用 pcl::visualization::PCLVisualizer 可视化原始点云、查询点和近似最近邻点。

代码示例:

#include <pcl/point_cloud.h>        // 点类型定义头文件
#include <pcl/kdtree/kdtree_flann.h> // kdtree类定义头文件
#include <pcl/visualization/pcl_visualizer.h> // PCL可视化类定义头文件#include <iostream>
#include <vector>
#include <ctime>
#include <chrono>
#include <thread>/*
函数功能:
半径内近邻搜索 (Radius Search):找到指定半径内的所有点。
*/
int main (int argc, char** argv)
{srand(time(NULL)); // 用系统时间初始化随机种子// 创建一个PointCloud<pcl::PointXYZ>对象pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);// 随机点云生成cloud->width = 1000;  // 点云数量cloud->height = 1;    // 表示点云为无序点云cloud->points.resize(cloud->width * cloud->height);for (size_t i = 0; i < cloud->points.size(); ++i) // 循环填充点云数据{cloud->points[i].x = 1024.0f * rand() / (RAND_MAX + 1.0f); // 产生数值为0-1024的浮点数cloud->points[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f);cloud->points[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f);}// 创建KdTreeFLANN对象,并把创建的点云设置为输入pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;kdtree.setInputCloud(cloud);// 设置查询点并赋随机值pcl::PointXYZ searchPoint;searchPoint.x = 1024.0f * rand() / (RAND_MAX + 1.0f);searchPoint.y = 1024.0f * rand() / (RAND_MAX + 1.0f);searchPoint.z = 1024.0f * rand() / (RAND_MAX + 1.0f);// 半径内近邻搜索方法std::vector<int> pointIdxRadiusSearch;           // 存储近邻索引std::vector<float> pointRadiusSquaredDistance;   // 存储近邻对应距离的平方float radius = 256.0f * rand() / (RAND_MAX + 1.0f); // 随机生成某一半径// 打印输出std::cout << "半径内近邻搜索,查询点为 (" << searchPoint.x << " " << searchPoint.y << " " << searchPoint.z<< "),半径=" << radius << std::endl;// 执行半径内近邻搜索方法if (kdtree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0){// 打印所有近邻坐标for (size_t i = 0; i < pointIdxRadiusSearch.size(); ++i)std::cout << "    " << cloud->points[pointIdxRadiusSearch[i]].x << " " << cloud->points[pointIdxRadiusSearch[i]].y << " " << cloud->points[pointIdxRadiusSearch[i]].z << " (距离平方: " << pointRadiusSquaredDistance[i] << ")" << std::endl;}// 创建PCLVisualizer对象pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("radiusSearch"));viewer->setBackgroundColor(0, 0, 0); // 设置背景色为黑色// 添加原始点云pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> originalColor(cloud, 255, 255, 255); // 白色viewer->addPointCloud<pcl::PointXYZ>(cloud, originalColor, "original cloud");// 添加查询点pcl::PointCloud<pcl::PointXYZ>::Ptr searchPointCloud(new pcl::PointCloud<pcl::PointXYZ>());searchPointCloud->push_back(searchPoint);pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> searchPointColor(searchPointCloud, 255, 0, 0); // 红色viewer->addPointCloud<pcl::PointXYZ>(searchPointCloud, searchPointColor, "search point");viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "search point");// 添加半径内近邻点pcl::PointCloud<pcl::PointXYZ>::Ptr radiusNearestPoints(new pcl::PointCloud<pcl::PointXYZ>());for (size_t i = 0; i < pointIdxRadiusSearch.size(); ++i){radiusNearestPoints->push_back(cloud->points[pointIdxRadiusSearch[i]]);}pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> radiusNearestColor(radiusNearestPoints, 0, 255, 0); // 绿色viewer->addPointCloud<pcl::PointXYZ>(radiusNearestPoints, radiusNearestColor, "radius nearest points");viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 5, "radius nearest points");// 启动可视化viewer->addCoordinateSystem(1.0);viewer->initCameraParameters();while (!viewer->wasStopped()){viewer->spinOnce(100);std::this_thread::sleep_for(std::chrono::milliseconds(100));}return 0;
}

可视化半径内近邻搜索的效果,如下图所示:

白色的是随机生成的原始点云,红色是查询点,绿色是找到的3个最近点(半径范围内)。

半径内近邻搜索,查询点为 (200.242 73.3622 785.961),半径=116.108
    166.217 33.6048 783.911 (距离平方: 2742.57)
    164.154 125.101 776.535 (距离平方: 4068.13)
    239.646 7.50222 856.443 (距离平方: 10857.9)

分享完成~

相关文章:

PCL从理解到应用【03】KDTree 原理分析 | 案例分析 | 代码实现

前言 本文分析KDTree的原理&#xff0c;集合案例深入理解&#xff0c;同时提供源代码。 三个案例&#xff1a;K近邻搜索、半径内近邻搜索、近似最近邻搜索。方法对比&#xff0c;如下表所示&#xff1a; 特性K近邻搜索半径内近邻搜索近似最近邻搜索描述查找K个最近邻点查找指…...

Windows 11内置一键系统备份与还原 轻松替代Ghost

面对系统崩溃、恶意软件侵袭或其他不可预见因素导致的启动失败&#xff0c;Windows 7~Windows 11内置的系统映像功能能够迅速将您的系统恢复至健康状态&#xff0c;确保工作的连续性和数据的完整性。 Windows内置3种备份策略 U盘备份&#xff1a;便携且安全 打开“创建一个恢…...

leetCode-hot100-动态规划专题

动态规划 动态规划定义动态规划的核心思想动态规划的基本特征动态规划的基本思路例题322.零钱兑换53.最大子数组和72.编辑距离139.单词拆分62.不同路径63.不同路径Ⅱ64.最小路径和70.爬楼梯121.买卖股票的最佳时机152.乘积最大子数组 动态规划定义 动态规划&#xff08;Dynami…...

【算法笔记自学】入门篇(2)——算法初步

4.1排序 自己写的题解 #include <stdio.h> #include <stdlib.h>void selectSort(int A[], int n) {for(int i 0; i < n - 1; i) { // 修正索引范围int k i;for(int j i 1; j < n; j) { // 修正索引范围if(A[j] < A[k]) {k j;}}if (k ! i) { // 仅在…...

Redis基础教程(六):redis 哈希(Hash)

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…...

鸿蒙开发设备管理:【@ohos.account.appAccount (应用帐号管理)】

应用帐号管理 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 导入模…...

java项目自定义打印日志,打印请求方式,参数用时等

1.相关依赖 <!-- 私人工具包 --><dependency><groupId>cn.changeforyou</groupId><artifactId>location</artifactId><version>1.13-SNAPSHOT</version></dependency><!-- hutool工具依赖 --><dependency>…...

03:EDA的进阶使用

使用EDA设计一个38译码器电路和245放大电路 1、38译码器1.1、查看74HC138芯片数据1.2、电路设计 2、245放大电路2.1、查看数据手册2.2、设计电路 3、绘制PCB3.1、导入3.2、放置3.3、飞线3.4、特殊方式连接GND3.5、泪滴3.6、配置丝印和划分区域3.7、添加typc接口供电 1、38译码器…...

Linux/Unix系统指令:(tar压缩和解压)

tar 是一个在Linux和Unix系统中用于创建和处理归档文件的命令。 下面是tar命令的详细用法&#xff0c;包括它的所有常用选项和一些示例。 基本语法 tar [选项] [归档文件] [文件或目录]常用选项 基本操作 -c&#xff1a;创建一个新的归档文件&#xff08;create&#xff09…...

MySQL 日期和时间函数知识点总结

引言 在数据库管理和开发中&#xff0c;日期查询是一项基础且频繁使用的功能。MySQL提供了丰富的日期和时间处理函数&#xff0c;使得我们能够灵活地进行日期查询和数据处理。本文将详细介绍MySQL中关于日期查询的几个重要知识点&#xff0c;并附上具体的案例。 1. MySQL的日…...

鸿蒙登录页面及页面跳转的设计

目录 任务目标任务分析任务实施1.新建工程项目HMLogin2.设计登录页面Index.visual3.设计第二个页面SecondPage4.修改Index.ets代码5.修改SecondPage.ets代码6.运行工程 任务目标 设计一个简单的登录页面&#xff0c;要求可以将第一页的登录信息&#xff0c;传递到第二个页面&a…...

【居家养老实训室】:看中医保健在养老中的应用

本文以居家养老实训室为视角&#xff0c;深入探讨了中医保健在养老中的应用。通过对中医保健理念、常用方法以及在居家养老中的具体实践进行分析&#xff0c;阐述了其在改善老年人健康状况、提高生活质量方面的重要作用。同时&#xff0c;也指出了目前应用中存在的问题&#xf…...

【区块链+基础设施】区块链服务网络 BSN | FISCO BCOS应用案例

BSN&#xff08;Blockchain-based Service Network&#xff0c;区块链服务网络&#xff09;是一个跨云服务、跨门户、跨底层框架&#xff0c;用于部 署和运行各类区块链应用的全球性基础设施网络&#xff0c;旨在为开发者提供低成本和技术互通的区块链一站式服务。 2019 年 12…...

六、快速启动框架:SpringBoot3实战-个人版

六、快速启动框架&#xff1a;SpringBoot3实战 文章目录 六、快速启动框架&#xff1a;SpringBoot3实战一、SpringBoot3介绍1.1 SpringBoot3简介1.2 系统要求1.3 快速入门1.4 入门总结回顾复习 二、SpringBoot3配置文件2.1 统一配置管理概述2.2 属性配置文件使用2.3 YAML配置文…...

SA 注册流程

目录 1. UE开机后按照3GPP TS 38.104定义的Synchronization Raster搜索特定频点 2.UE尝试检测PSS/SSS&#xff0c;取得下行时钟同步&#xff0c;并获取小区的PCI&#xff1b;如果失败则转步骤1搜索下一个频点&#xff1b;否则继续后续步骤&#xff1b; 3.解析Mib&#xff0c;…...

图像的灰度直方图

先来认识一下灰度直方图&#xff0c;灰度直方图是图像灰度级的函数&#xff0c;用来描述每个灰度级在图像矩阵中的像素个数或者占有率。接下来使用程序实现直方图&#xff1a; 首先导入所需的程序包&#xff1a; In [ ]: import cv2 import numpy as np import matplotlib…...

软件测试面试题:Redis的五种数据结构,以及使用的场景是什么?

字符串&#xff08;Strings&#xff09;&#xff1a;简单直接&#xff0c;就像记事本一样&#xff0c;用来存储和快速访问简单的数据&#xff0c;比如缓存网页或者保存用户会话信息。 列表&#xff08;Lists&#xff09;&#xff1a;有序的数据集合&#xff0c;适合用来存储按…...

Java后端每日面试题(day1)

目录 JavaWeb三大组件依赖注入的方式Autowire和Resurce有什么区别&#xff1f;Spring Boot的优点Spring IoC是什么&#xff1f;说说Spring Aop的优点Component和Bean的区别自定义注解时使用的RetentionPolicy枚举类有哪些值&#xff1f;如何理解Spring的SPI机制&#xff1f;Spr…...

AI与测试相辅相成

AI助力软件测试 1.AI赋能软件测试 使用AI工具来帮助测试人员提高测试效率&#xff0c;提供缺陷分析和缺陷预测。 语法格式 设定角色 具体指示 上下文格式 例: 角色&#xff1a;你是一个测试人员 内容&#xff1a;请帮我生成登录案例的测试用例 ​ 1.只有输入正确账号和密码才…...

搜索+动态规划

刷题刷题刷题刷题 ​​​​​​​​​​​​​​Forgery - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路&#xff1a; 需要两个数组&#xff0c;一个数组全部初始化为".",另一个数组输入数据&#xff0c;每碰到一个“.”就进行染色操作&#xff0c;将其周围的…...

strcpy,srtcmp,strlen函数漏洞利用

strcpy,srtcmp,strlen函数漏洞利用 strcpy strcpy函数用于将字符串复制到另一个指针指向的空间中&#xff0c;遇到空字符 **b’x\00’**时停止&#xff0c;&#xff1a; 所以可以利用 strcpy不检查缓冲区 的漏洞&#xff08;构造的字符串要以\0结尾&#xff09;&#xff0c;…...

SketchUp + Enscape+ HTC Focus3 VR

1. 硬件: 设备连接 2. 软件: 安装steam steamVR Vive Business streaming 3. 操作: 双方登录steam 账号,然后带上头盔,用手柄在HTC Focus3 安装 串流软件,选择串流软件,在Enscape中选择 VR 模式即可 4.最终效果: SketchUp Enscape HTC Focus 3 VR 实时预览_哔哩哔哩_bi…...

推荐3款Windows系统的神级软件,免费、轻量、绝对好用!

DiskView DiskView是一款用于管理和查看磁盘空间的工具&#xff0c;它集成了于微软的Windows操作系统资源管理器中&#xff0c;以显示直观的磁盘空间使用情况。该软件通过生成图形化地图&#xff0c;帮助用户组织和管理大量文件和文件夹&#xff0c;从而高效地管理磁盘空间。用…...

-bash: /snap/bin/docker: 没有那个文件或目录

-bash: /snap/bin/docker: 没有那个文件或目录 解决办法 export PATH$PATH:/usr/bin/docker然后&#xff0c;重新加载配置文件 source ~/.bashrc...

[深度学习]卷积理解

单通道卷积 看这个的可视化就很好理解了 https://github.com/vdumoulin/conv_arithmetic/blob/master/README.md 多通道卷积 当输入有多个通道时,卷积核需要拥有相同的通道数. 假设输入有c个通道,那么卷积核的每个通道分别于相应的输入数据通道进行卷积,然后将得到的特征图对…...

基于aardio web.view2库和python playwright包的内嵌浏览器自动化操作

通过cdp协议可以实现playwright操控webview。 新建Python窗口工程 修改pip.aardio 修改pip.aardio&#xff0c;并执行&#xff0c;安装playwright。 //安装模块 import process.python.pip; //process.python.path "python.exe";/* 安装模块。 参数可以用一个字…...

《数据仓库与数据挖掘》 总复习

试卷组成 第一章图 第二章图 第三章图 第四章图 第五章图 第六章图 第九章图 第一章 DW与DM概述 &#xff08;特点、特性&#xff09; DB到DW 主要特征 &#xff08;1&#xff09;数据太多&#xff0c;信息贫乏&#xff08;Data Rich&#xff0c; Information Poor)。 &a…...

EtherCAT主站IGH-- 8 -- IGH之domain.h/c文件解析

EtherCAT主站IGH-- 8 -- IGH之domain.h/c文件解析 0 预览一 该文件功能`domain.c` 文件功能函数预览二 函数功能介绍1. `ec_domain_init`2. `ec_domain_clear`3. `ec_domain_add_fmmu_config`4. `ec_domain_add_datagram_pair`5. `ec_domain_finish`6. `ecrt_domain_reg_pdo_en…...

《昇思25天学习打卡营第10天|使用静态图加速》

文章目录 今日所学&#xff1a;一、背景介绍1. 动态图模式2. 静态图模式 三、静态图模式的使用场景四、静态图模式开启方式1. 基于装饰器的开启方式2. 基于context的开启方式 总结&#xff1a; 今日所学&#xff1a; 在上一集中&#xff0c;我学习了保存与加载的方法&#xff…...

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(二十二)

课程地址&#xff1a; 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程&#xff0c;一套精通鸿蒙应用开发 &#xff08;本篇笔记对应课程第 32 节&#xff09; P32《31.通知-基础通知》 基础文本类型通知&#xff1a;briefText 没有用&#xff0c;写了也白写。 长文本类型…...