PFH特征描述符、对应关系可视化以及ICP配准

news2024/11/29 10:45:09

一、PFH特征描述符可视化

C++

#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/search/kdtree.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d_omp.h>//使用OMP需要添加的头文件
#include <boost/thread/thread.hpp>
#include <pcl/features/3dsc.h>
#include <pcl/visualization/pcl_plotter.h>// 直方图的可视化 
#include <pcl/visualization/histogram_visualizer.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/pfh.h>
using namespace std;
int main()
{
	//------------------加载点云数据-----------------
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("pcd/pig_view1.pcd", *cloud) == -1)//需使用绝对路径
	{
		PCL_ERROR("Could not read file\n");
	}

	//--------------------计算法线------------------
	pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n;//OMP加速
	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
	//建立kdtree来进行近邻点集搜索
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
	n.setNumberOfThreads(8);//设置openMP的线程数
	n.setInputCloud(cloud);
	n.setSearchMethod(tree);
	n.setKSearch(20);
	n.compute(*normals);//开始进行法向计算

	// ------------------3DSC图像计算------------------
	pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh;
	pfh.setInputCloud(cloud);
	pfh.setInputNormals(normals);
	pfh.setSearchMethod(tree);
	pcl::PointCloud<pcl::PFHSignature125>::Ptr pfh_images(new pcl::PointCloud<pcl::PFHSignature125>());
	pfh.setRadiusSearch(15);
	pfh.compute(*pfh_images);
	cout << "PFH图像计算计算完成" << endl;

	// 显示和检索第一点的自旋图像描述符向量。
	pcl::PFHSignature125 first_descriptor = pfh_images->points[0];
	cout << first_descriptor << endl;


	pcl::visualization::PCLPlotter plotter;
	plotter.addFeatureHistogram(*pfh_images, 200); //设置的横坐标长度,该值越大,则显示的越细致
	plotter.setWindowName("3DSC Image");
	plotter.plot();

	return 0;
}

关键代码解析:

	pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh;
	pfh.setInputCloud(cloud);
	pfh.setInputNormals(normals);
	pfh.setSearchMethod(tree);
	pcl::PointCloud<pcl::PFHSignature125>::Ptr pfh_images(new pcl::PointCloud<pcl::PFHSignature125>());
	pfh.setRadiusSearch(15);
	pfh.compute(*pfh_images);
  1. pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh;

    • 这一行定义了一个PFH特征估计器对象pfh,并指定了输入点云类型为pcl::PointXYZ,输入法向量类型为pcl::Normal,以及输出特征类型为pcl::PFHSignature125
  2. pfh.setInputCloud(cloud);

    • 将点云数据设置为PFH估计器的输入。cloud是一个指向pcl::PointCloud<pcl::PointXYZ>类型的指针,表示原始点云数据。
  3. pfh.setInputNormals(normals);

    • 将法向量数据设置为PFH估计器的输入。normals是一个指向pcl::PointCloud<pcl::Normal>类型的指针,表示点云中每个点的法向量数据。
  4. pfh.setSearchMethod(tree);

    • 设置搜索方法。tree是一个用于加速邻域搜索的数据结构,例如kd-tree或octree。这个参数可以根据点云的大小和分布来调整,以获得更好的性能。
  5. pcl::PointCloud<pcl::PFHSignature125>::Ptr pfh_images(new pcl::PointCloud<pcl::PFHSignature125>());

    • 创建一个指向pcl::PointCloud<pcl::PFHSignature125>类型的智能指针pfh_images,用于存储计算得到的PFH特征。
  6. pfh.setRadiusSearch(15);

    • 设置用于计算PFH特征的邻域搜索半径。较小的半径会考虑较近的邻居点,而较大的半径会考虑更远的邻居点。这个参数需要根据点云的密度和特征的分布来调整。
  7. pfh.compute(*pfh_images);

    • 运行PFH特征的计算过程。该方法会根据输入的点云和法向量数据以及设置的搜索参数来计算每个点的PFH特征,并将结果存储在pfh_images中。
  8. cout << "PFH图像计算计算完成" << endl;

    • 打印消息,指示PFH特征计算完成。
  9. pcl::PFHSignature125 first_descriptor = pfh_images->points[0];

    • 提取第一个点的PFH特征描述符。这里假设点云中至少有一个点。
  10. cout << first_descriptor << endl;

    • 打印第一个点的PFH特征描述符。
  11. pcl::visualization::PCLPlotter plotter;

    • 创建一个PCL绘图器对象,用于可视化PFH特征。
  12. plotter.addFeatureHistogram(*pfh_images, 200);

    • 向绘图器中添加PFH特征的直方图。第二个参数指定了横坐标的长度,该值越大,显示的越细致。
  13. plotter.setWindowName("3DSC Image");

    • 设置绘图窗口的名称。
  14. plotter.plot();

    • 显示绘图器中的图像。

总的来说,这段代码的作用是计算并可视化点云的PFH特征。参数的设置会直接影响特征的计算和可视化效果,因此需要根据具体的数据和需求进行调整。

结果:

二、PFH对应关系可视化

C++

#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/registration/correspondence_estimation.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/registration/transformation_estimation_svd.h> 
#include <pcl/keypoints/sift_keypoint.h>
#include <pcl/features/pfh.h>

using namespace std;

namespace pcl
{
    template<>
    struct SIFTKeypointFieldSelector<PointXYZ>
    {
        inline float
            operator () (const PointXYZ& p) const
        {
            return p.z;
        }

    };
}

typedef pcl::PointCloud<pcl::PointXYZ> pointcloud;
typedef pcl::PointCloud<pcl::Normal> pointnormal;
typedef pcl::PointCloud<pcl::PFHSignature125> pfhFeature;

pfhFeature::Ptr compute_pfh_feature(pointcloud::Ptr input_cloud, pcl::search::KdTree<pcl::PointXYZ>::Ptr tree)
{

    pointnormal::Ptr normals(new pointnormal);
    pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n;
    n.setInputCloud(input_cloud);
    n.setNumberOfThreads(5);
    n.setSearchMethod(tree);
    n.setKSearch(10);
    n.compute(*normals);


    pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh;
    pfh.setInputCloud(input_cloud);
    pfh.setInputNormals(normals);
    pfh.setSearchMethod(tree);
    pcl::PointCloud<pcl::PFHSignature125>::Ptr pfh_fe_ptr(new pcl::PointCloud<pcl::PFHSignature125>());
    pfh.setRadiusSearch(10);
    pfh.compute(*pfh_fe_ptr); 

    return pfh_fe_ptr;



}

void extract_keypoint(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& keypoint)
{


    pcl::PointCloud<pcl::PointWithScale> result;


    const float min_scale = 5.f;                 
    const int n_octaves = 3;                            
    const int n_scales_per_octave = 15;       
    const float min_contrast = 0.01f;       
    pcl::SIFTKeypoint<pcl::PointXYZ, pcl::PointWithScale> sift;

    sift.setInputCloud(cloud);            
    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    sift.setSearchMethod(tree);               
    sift.setScales(min_scale, n_octaves, n_scales_per_octave);
    sift.setMinimumContrast(min_contrast);    
    sift.compute(result);                     
    cout << "Extracted " << result.size() << " keypoints" << endl;
    copyPointCloud(result, *keypoint);

}

int main(int argc, char** argv)
{
    pointcloud::Ptr source_cloud(new pointcloud);
    pointcloud::Ptr target_cloud(new pointcloud);
    pcl::io::loadPCDFile<pcl::PointXYZ>("pcd/pig_view1.pcd", *source_cloud);
    pcl::io::loadPCDFile<pcl::PointXYZ>("pcd/pig_view2.pcd", *target_cloud);

    pcl::PointCloud<pcl::PointXYZ>::Ptr s_k(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr t_k(new pcl::PointCloud<pcl::PointXYZ>);
    extract_keypoint(source_cloud, s_k);
    extract_keypoint(target_cloud, t_k);


    pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
    pfhFeature::Ptr source_pfh = compute_pfh_feature(s_k, tree);
    pfhFeature::Ptr target_pfh = compute_pfh_feature(t_k, tree);
    pcl::registration::CorrespondenceEstimation<pcl::PFHSignature125, pcl::PFHSignature125> crude_cor_est;
    boost::shared_ptr<pcl::Correspondences> cru_correspondences(new pcl::Correspondences);
    crude_cor_est.setInputSource(source_pfh);
    crude_cor_est.setInputTarget(target_pfh);
    crude_cor_est.determineCorrespondences(*cru_correspondences);
    Eigen::Matrix4f Transform = Eigen::Matrix4f::Identity();
    pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ, float>::Ptr trans(new pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ, float>);

    trans->estimateRigidTransformation(*source_cloud, *target_cloud, *cru_correspondences, Transform);



    boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer(new pcl::visualization::PCLVisualizer("v1"));
    viewer->setBackgroundColor(0, 0, 0);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>target_color(target_cloud, 255, 0, 0);
    viewer->addPointCloud<pcl::PointXYZ>(target_cloud, target_color, "target cloud");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "target cloud");
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>input_color(source_cloud, 0, 255, 0);
    viewer->addPointCloud<pcl::PointXYZ>(source_cloud, input_color, "input cloud");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "input cloud");
    viewer->addCorrespondences<pcl::PointXYZ>(s_k, t_k, *cru_correspondences, "correspondence");
    //viewer->initCameraParameters();
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(1000));
    }


    return 0;
}

关键代码解析:

我之前在SIFT 3D关键点检测以及SAC-IA粗配准-CSDN博客

和Spin Image自旋图像描述符可视化以及ICP配准-CSDN博客以及本章第一部分已经解释了大部分函数,这里就不赘述了

结果:

三、PFH结合ICP配准 

C++

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/registration/icp.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/registration/ia_ransac.h>
#include <pcl/visualization/pcl_plotter.h>
#include <pcl/features/pfh.h>
#include <pcl/keypoints/sift_keypoint.h>
typedef pcl::PointXYZ PointT;
typedef pcl::PointCloud<PointT> PointCloud;
typedef pcl::PFHSignature125 PFHT;
typedef pcl::PointCloud<PFHT> PointCloudPFH;
typedef pcl::search::KdTree<PointT> Tree;

namespace pcl
{
    template<>
    struct SIFTKeypointFieldSelector<PointXYZ>
    {
        inline float
            operator () (const PointXYZ& p) const
        {
            return p.z;
        }

    };
}
// 关键点提取
void extract_keypoint(PointCloud::Ptr& cloud, PointCloud::Ptr& keypoint, Tree::Ptr& tree)
{
    pcl::PointCloud<pcl::PointWithScale> result;
    const float min_scale = 5.f;                 
    const int n_octaves = 3;                        
    const int n_scales_per_octave = 15;    
    const float min_contrast = 0.01f;           
    pcl::SIFTKeypoint<pcl::PointXYZ, pcl::PointWithScale> sift;
    sift.setInputCloud(cloud);            
    sift.setSearchMethod(tree);               
    sift.setScales(min_scale, n_octaves, n_scales_per_octave);
    sift.setMinimumContrast(min_contrast);    
    sift.compute(result);                    
    copyPointCloud(result, *keypoint);
}
// 法线计算和 计算特征点的Spinimage描述子
void computeKeyPointsPFH(PointCloud::Ptr& cloud_in, PointCloud::Ptr& key_cloud, PointCloudPFH::Ptr& dsc, Tree::Ptr& tree)
{
    pcl::NormalEstimationOMP<PointT, pcl::Normal> n;//OMP加速
    pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
    n.setNumberOfThreads(6);//设置openMP的线程数
    n.setInputCloud(key_cloud);
    n.setSearchSurface(cloud_in);
    n.setSearchMethod(tree);
    //n.setKSearch(10);
    n.setRadiusSearch(0.3);
    n.compute(*normals);

    pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh;
    pfh.setInputCloud(key_cloud);
    pfh.setInputNormals(normals);
    pfh.setSearchMethod(tree);
    pcl::PointCloud<pcl::PFHSignature125>::Ptr pfh_fe_ptr(new pcl::PointCloud<pcl::PFHSignature125>());
    pfh.setRadiusSearch(10);
    pfh.compute(*dsc);

}



// 点云可视化
void visualize_pcd(PointCloud::Ptr icp_result, PointCloud::Ptr cloud_target)
{
    //创建初始化目标
    pcl::visualization::PCLVisualizer viewer("registration Viewer");
    pcl::visualization::PointCloudColorHandlerCustom<PointT> final_h(icp_result, 0, 255, 0);
    pcl::visualization::PointCloudColorHandlerCustom<PointT> tgt_h(cloud_target, 255, 0, 0);
    viewer.setBackgroundColor(0, 0, 0);
    viewer.addPointCloud(cloud_target, tgt_h, "tgt cloud");
    viewer.addPointCloud(icp_result, final_h, "final cloud");

    while (!viewer.wasStopped())
    {
        viewer.spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }
}


int main()
{
    // 加载源点云和目标点云
    PointCloud::Ptr cloud(new PointCloud);
    PointCloud::Ptr cloud_target(new PointCloud);
    if (pcl::io::loadPCDFile<pcl::PointXYZ>("pcd/pig_view1.pcd", *cloud) == -1)
    {
        PCL_ERROR("加载点云失败\n");
    }
    if (pcl::io::loadPCDFile<pcl::PointXYZ>("pcd/pig_view2.pcd", *cloud_target) == -1)
    {
        PCL_ERROR("加载点云失败\n");
    }
    visualize_pcd(cloud, cloud_target);
    //关键点
    pcl::PointCloud<PointT>::Ptr keypoints1(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<PointT>::Ptr keypoints2(new pcl::PointCloud<pcl::PointXYZ>);
    Tree::Ptr tree(new Tree);

    extract_keypoint(cloud, keypoints1, tree);
    extract_keypoint(cloud_target, keypoints2, tree);
    cout << "SIFT 3D完成!" << endl;
    cout << "cloud的关键点的个数:" << keypoints1->size() << endl;
    cout << "cloud_target的关键点的个数:" << keypoints2->size() << endl;



    // 使用SpinImage描述符计算特征
    PointCloudPFH::Ptr source_features(new PointCloudPFH);
    PointCloudPFH::Ptr target_features(new PointCloudPFH);
    computeKeyPointsPFH(cloud, keypoints1, source_features, tree);
    computeKeyPointsPFH(cloud_target, keypoints2, target_features, tree);
    cout << "PFH完成!" << endl;


    //SAC配准
    pcl::SampleConsensusInitialAlignment<PointT, PointT, PFHT> scia;
    scia.setInputSource(keypoints1);
    scia.setInputTarget(keypoints2);
    scia.setSourceFeatures(source_features);
    scia.setTargetFeatures(target_features);
    scia.setMinSampleDistance(7);     // 设置样本之间的最小距离
    scia.setNumberOfSamples(100);       // 设置每次迭代计算中使用的样本数量(可省),可节省时间
    scia.setCorrespondenceRandomness(6);// 在选择随机特征对应时,设置要使用的邻居的数量;
    PointCloud::Ptr sac_result(new PointCloud);
    scia.align(*sac_result);
    Eigen::Matrix4f sac_trans;
    sac_trans = scia.getFinalTransformation();
    cout << "SAC配准完成!" << endl;

    //icp配准
    PointCloud::Ptr icp_result(new PointCloud);
    pcl::IterativeClosestPoint<PointT, PointT> icp;
    icp.setInputSource(keypoints1);
    icp.setInputTarget(keypoints2);
    icp.setMaxCorrespondenceDistance(20);
    icp.setMaximumIterations(35);        // 最大迭代次数
    icp.setTransformationEpsilon(1e-10); // 两次变化矩阵之间的差值
    icp.setEuclideanFitnessEpsilon(0.01);// 均方误差
    icp.align(*icp_result, sac_trans);
    cout << "ICP配准完成!" << endl;

    // 输出配准结果
    std::cout << "ICP converged: " << icp.hasConverged() << std::endl;
    std::cout << "Transformation matrix:\n" << icp.getFinalTransformation() << std::endl;
    Eigen::Matrix4f icp_trans;
    icp_trans = icp.getFinalTransformation();
    cout << icp_trans << endl;
    使用创建的变换对未过滤的输入点云进行变换
    pcl::transformPointCloud(*cloud, *icp_result, icp_trans);

    visualize_pcd(icp_result, cloud_target);

    return 0;
}

关键代码解析:

我之前在SIFT 3D关键点检测以及SAC-IA粗配准-CSDN博客

和Spin Image自旋图像描述符可视化以及ICP配准-CSDN博客以及本章第一部分已经解释了大部分函数,这里就不赘述了

结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1455758.html

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

相关文章

PyCharm - Project Interpreter (项目解释器)

PyCharm - Project Interpreter [项目解释器] References File -> Settings… -> Project: -> Project Interpreter References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

深入探讨Lambda表达式转换为委托类型的编译过程

了解了&#xff0c;如果要深入探讨Lambda表达式转换为委托类型的编译过程&#xff0c;我们需要关注C#编译器如何处理这个转换。这个过程涉及到编译时的类型推断、匿名方法的创建&#xff0c;以及生成对应的委托实例。我们来更详细地分析这个过程&#xff1a; 编译阶段 1. 解…

21. Merge Two Sorted Lists(合并两个有序链表)

问题描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 问题分析 我们只需要使用两个指针分别从两个链表的头部向后遍历整个链表&#xff0c;每一个次都让量个元素比较大小&#xff0c;小的元素并入的新的链表&#xf…

MySQL(1/3)

基本命令行操作 命令行连接 mysql -uroot -p 回车&#xff0c;然后在下一行输入密码&#xff0c;或者直接在p后写密码 修改密码 updata mysql.user set authentication_stringpassword(原密码) where userroot and Host localhost; 刷新权限 flush privileges; 查看所有数据库…

数据库索引面试的相关问题

查看索引的执行计划 索引失效的情况 1、索引列上做了计算&#xff0c;函数&#xff0c;类型转换等操作。索引失效是因为查询过程需要扫描整个索引并回表。代价高于直接全表扫描。 Like匹配使用了前缀匹配符“%abc” 字符串不加引号导致类型转换。 原因&#xff1a; 常见索…

03 SS之返回JSON+UserDetail接口+基于数据库实现RBAC

1. 返回JSON 为什么要返回JSON 前后端分离成为企业应用开发中的主流&#xff0c;前后端分离通过json进行交互&#xff0c;登录成功和失败后不用页面跳转&#xff0c;而是给前端返回一段JSON提示, 前端根据JSON提示构建页面. 需求: 对于登录的各种状态 , 给前端返回JSON数据 …

面向对象编程(三)

目录 1. 关键字&#xff1a;static 1.1 类属性、类方法的设计思想 1.2 static关键字 1.3 静态变量 1.3.1 语法格式 1.3.2 静态变量的特点 1.3.3 举例 1.3.4 内存解析 1.4 静态方法 1.4.1 语法格式 1.4.2 静态方法的特点 1.4.3 举例 2. 单例(Singleton)设计模式 2…

HarmonyOS router页面跳转

默认启动页面index.ets import router from ohos.router import {BusinessError} from ohos.baseEntry Component struct Index {State message: string Hello World;build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)//添加按钮&am…

简约火箭发射静态404错误页面源码

简约火箭发射静态404错误页面源码&#xff0c;源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 蓝奏云下载&#xff1a;https://wfr.lanzout.com/iK…

烦人的鼠标唤醒电脑功能彻底禁用

1.常规操作禁用鼠标唤醒 搜索设备 电源管理取消勾选 这样操作后, 系统更新等各种原因, 又会失效, 需要反复操作, 很烦 2.关闭计算机管理的计划任务 禁用 3.查询唤醒原因 powercfg /waketimers powercfg /lastwake

多模态学习综述(MultiModal Learning)

最早开始关注到多模态机器学习是看到Jeff Dean在2019年年底NeurIPS大会上的一个采访报道&#xff0c;讲到了2020年机器学习趋势&#xff1a;多任务和多模态学习将成为突破口。 Jeff Dean 谈2020年机器学习趋势&#xff1a;多任务和多模式学习将成为突破口 站在2022年&#xff…

华为模拟器防火墙配置实验(四)

实验拓扑图 需求&#xff1a; 1&#xff0c;办公区设备可以通过电信链路和移动链路正常上网&#xff08;多对多的NAT&#xff0c;并且需要保存一个公网IP不能用来转换&#xff09; 2&#xff0c;分公司的设备可以通过总公司的移动链路和电信链路访问DMZ区域的http服务器 3&…

VSCODE上使用python_Django

接上篇 https://blog.csdn.net/weixin_44741835/article/details/136135996?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22136135996%22%2C%22source%22%3A%22weixin_44741835%22%7D VSCODE官网&#xff1a; Editing Python …

python+django咖啡网上商城网站

全网站共设计首页、咖啡文化、咖啡商城、个人信息、联系我们5个栏目以及登录、注册界面&#xff0c;让用户能够全面的了解中国咖啡咖啡文化宣传网站以及一些咖啡知识、文化。 栏目一首页&#xff0c;主要放置咖啡的起源及发展进程的图文介绍&#xff1b;栏目二咖啡文化&#xf…

FPGA 高速接口(LVDS)

差分信号环路测试 1 概述 LVDS&#xff08;Low Voltage Differential Signalin&#xff09;是一种低振幅差分信号技术。它使用幅度非常低的信号&#xff08;约350mV&#xff09;通过一对差分PCB走线或平衡电缆传输数据。大部分高速数据传输中&#xff0c;都会用到LVDS传输。 …

多维时序 | Matlab实现基于VMD-DBO-LSTM、VMD-LSTM、LSTM的多变量时间序列预测

多维时序 | Matlab实现基于VMD-DBO-LSTM、VMD-LSTM、LSTM的多变量时间序列预测 目录 多维时序 | Matlab实现基于VMD-DBO-LSTM、VMD-LSTM、LSTM的多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现基于VMD-DBO-LSTM、VMD-LSTM、LSTM的多变量时间…

06 分频器设计

分频器简介 实现分频一般有两种方法&#xff0c;一种方法是直接使用 PLL 进行分频&#xff0c;比如在 FPGA 或者 ASIC 设计中&#xff0c;都可以直接使用 PLL 进行分频。但是这种分频有时候受限于 PLL 本身的特性&#xff0c;无法得到频率很低的时钟信号&#xff0c;比如输入 …

LeetCode 热题 100 Day01

哈希模块 哈希结构&#xff1a; 哈希结构&#xff0c;即hash table&#xff0c;哈希表|散列表结构。 图摘自《代码随想录》 哈希表本质上表示的元素和索引的一种映射关系。 若查找某个数组中第n个元素&#xff0c;有两种方法&#xff1a; 1.从头遍历&#xff0c;复杂度&#xf…

【Node-RED】安全登陆时,账号密码设置

【Node-RED】安全登陆时&#xff0c;账号密码设置 前言实现步骤密码生成setting.js 文件修改 安全权限 前言 Node-RED 在初始下载完成时&#xff0c;登录是无账号密码的。基于安全性考虑&#xff0c;本期博文介绍在安全登陆时&#xff0c;如何进行账号密码设置。当然&#xff…

spring boot自动装配及自动装配条件判断

第一步需要在pom.xml文件指定需要导入的坐标 要是没有自动提示需要检查maven有没有 实现代码 /*springboot第三方自动配置实现方法 * 什么是自动配置 自动配置就是springboot启动自动加载的类不需要在手动的控制反转自动的加入bean中 * * *//*第一种方案包扫描 不推荐因为繁琐…