点云处理中阶 Octree模块

news2024/11/20 9:41:09

一、什么是Octree

      八叉树(Octree)是一种用于描述三维空间的树状数据结构。八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点,这八个子节点所表示的体积元素加在一起就等于父节点的体积。一般中心点作为节点的分叉中心。且每个节点可以继续分割,直到满足某个条件(如达到最大深度或最小点数)。这种结构特别适合于稀疏点云数据的处理,能够高效地进行空间查询和操作。

实现八叉树的原理 

  (1). 设定最大递归深度。

  (2). 找出场景的最大尺寸,并以此尺寸建立第一个立方体。

  (3). 依序将单位元元素丢入能被包含且没有子节点的立方体。

  (4). 若没达到最大递归深度,就进行细分八等份,再将该立方体所装的单位元元素全部分担给八个子立方体。

  (5). 若发现子立方体所分配到的单位元元素数量不为零且跟父立方体是一样的,则该子立方体停止细分,因为跟据空间分割理论,细分的空间所得到的分配必定较少,若是一样数目,则再怎么切数目还是一样,会造成无穷切割的情形。

  (6). 重复3,直到达到最大递归深度。

二、八叉树应用

1、点云压缩

      点云由巨大的数据集组成,这些数据集描述了三维点,并与诸如距离、颜色、法线等附加信息相关联。此外,它们可以以很高的速率创建,因此占用大量的内存资源。一旦点云必须在速率有限的通信信道上存储或传输,压缩这类数据的方法就变得非常有趣了。

      点云库提供点云压缩功能。它允许编码所有类型的点云,包括无序的点云,其特征是不存在的点引用,不同的点大小,分辨率,密度和/或点顺序。

      此外,底层八叉树数据结构能够有效地合并来自多个来源的点云数据。

      以下示例演示如何有效地压缩单点云以及点云流。

压缩单点云

  1. 几何压缩

    • Octree编码:将空间分割成八个子区域,递归进行,直到每个节点包含的点数少于某个阈值。使用八叉树结构可以有效减少存储需求。
    • KD树编码:通过平衡树结构将点云分割,并按层次顺序存储,可以较好地压缩数据。
  2. 基于变换的压缩

    • 主成分分析 (PCA):对点云数据进行主成分分析,将点云数据投影到主成分上,减少维度,从而达到压缩的目的。
    • 离散余弦变换 (DCT)小波变换:将点云数据转变到频域,利用能量集中在低频部分的特性,舍弃高频部分,实现压缩。
  3. 点位置编码

    • 量化:将点的坐标值进行量化,可以在一定程度上减少数据量。
    • 预测编码:使用点的邻域信息预测当前点的位置,仅存储预测误差,从而减少存储量。

压缩点云流

  1. 时间冗余压缩

    • 帧间差分编码:仅存储相邻帧之间的差异,而不是每一帧的完整数据。可以大大减少数据量。
    • 运动估计和补偿:通过估计点云流中的运动矢量,只存储运动矢量和补偿信息。
  2. 基于模型的压缩

    • 动态几何模型:利用物体的运动模型(如刚体运动模型、骨架动画等)来预测点的位置,只存储模型参数。
    • 稀疏表示:使用稀疏矩阵或张量表示点云流,存储非零元素及其索引。
  3. 空间和时间联合压缩

    • 四维(3D空间+时间)Octree编码:将时间维度加入Octree结构,实现空间和时间的联合压缩。
    • 时空小波变换:对点云流进行时空小波变换,利用点云流在时空域的稀疏性进行压缩。
  4. 机器学习方法

    • 自编码器:使用神经网络的自编码器结构学习点云数据的低维表示,从而实现压缩。
    • 生成对抗网络(GANs):利用GAN生成逼真的点云数据,可以仅存储生成器的模型参数,而不是所有点数据。

示例一(进行压缩和解压缩)

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/octree_pointcloud_compression.h>

int main(int argc, char** argv) {
    // 创建一个点云对象
    pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGBA>());
    pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloudOut(new pcl::PointCloud<pcl::PointXYZRGBA>());

    // 生成一些示例点云数据
    cloud->width = 100;
    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 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud->points[i].r = rand() % 256;
        cloud->points[i].g = rand() % 256;
        cloud->points[i].b = rand() % 256;
        cloud->points[i].a = 255;
    }

    // 初始化点云压缩和解压缩对象
    pcl::io::compression_Profiles_e compressionProfile = pcl::io::HIGH_RES_ONLINE_COMPRESSION_WITHOUT_COLOR;
    bool showStatistics = true;
    pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> PointCloudEncoder(compressionProfile, showStatistics);
    pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> PointCloudDecoder;

    // 压缩点云
    std::stringstream compressedData;
    PointCloudEncoder.encodePointCloud(cloud, compressedData);

    // 解压缩点云
    PointCloudDecoder.decodePointCloud(compressedData, cloudOut);

    // 打印压缩和解压缩后的点云数据
    std::cout << "Original Point Cloud: " << std::endl;
    for (size_t i = 0; i < cloud->points.size(); ++i) {
        std::cout << "    " << cloud->points[i] << std::endl;
    }

    std::cout << "Decompressed Point Cloud: " << std::endl;
    for (size_t i = 0; i < cloudOut->points.size(); ++i) {
        std::cout << "    " << cloudOut->points[i] << std::endl;
    }

    return 0;
}

示例二(OpenNI兼容设备)

下面的代码为OpenNI兼容设备实例化一个新的采样器,并且启动循环回调接口,每从设备获取一帧数据就回调函数一次,,这里的回调函数就是实现数据压缩和可视化解压缩结果。

出处:PCL学习八叉树 - Being_young - 博客园 (cnblogs.com)

#include <pcl/point_cloud.h>                         // 点云类型
#include <pcl/point_types.h>                          //点数据类型
#include <pcl/io/openni_grabber.h>                    //点云获取接口类
#include <pcl/visualization/cloud_viewer.h>            //点云可视化类

#include <pcl/compression/octree_pointcloud_compression.h>   //点云压缩类

#include <stdio.h>
#include <sstream>
#include <stdlib.h>

#ifdef WIN32
# define sleep(x) Sleep((x)*1000)
#endif

class SimpleOpenNIViewer
{
public:
  SimpleOpenNIViewer () :
    viewer (" Point Cloud Compression Example")
  {
  }
/************************************************************************************************
  在OpenNIGrabber采集循环执行的回调函数cloud_cb_中,首先把获取的点云压缩到stringstream缓冲区,下一步就是解压缩,
  它对压缩了的二进制数据进行解码,存储在新的点云中解码了点云被发送到点云可视化对象中进行实时可视化
*************************************************************************************************/
  
 void  cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
  {
    if (!viewer.wasStopped ())
    {
      // 存储压缩点云的字节流对象
      std::stringstream compressedData;
      // 存储输出点云
      pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloudOut (new pcl::PointCloud<pcl::PointXYZRGBA> ());

      // 压缩点云
      PointCloudEncoder->encodePointCloud (cloud, compressedData);

      // 解压缩点云
      PointCloudDecoder->decodePointCloud (compressedData, cloudOut);


      // 可视化解压缩的点云
      viewer.showCloud (cloudOut);
    }
  }
/**************************************************************************************************************
 在函数中创建PointCloudCompression类的对象来编码和解码,这些对象把压缩配置文件作为配置压缩算法的参数所提供的压缩配置文件为OpenNI兼容设备采集到的点云预先确定的通用参数集,本例中使用MED_RES_ONLINE_COMPRESSION_WITH_COLOR配置参数集,用于快速在线的压缩,压缩配置方法可以在文件/io/include/pcl/compression/compression_profiles.h中找到,
 在PointCloudCompression构造函数中使用MANUAL——CONFIGURATION属性就可以手动的配置压缩算法的全部参数
******************************************************************************************************************/
  void run ()
  {

    bool showStatistics = true;  //设置在标准设备上输出打印出压缩结果信息

    // 压缩选项详情在: /io/include/pcl/compression/compression_profiles.h
    pcl::io::compression_Profiles_e compressionProfile = pcl::io::MED_RES_ONLINE_COMPRESSION_WITH_COLOR;

    // 初始化压缩和解压缩对象  其中压缩对象需要设定压缩参数选项,解压缩按照数据源自行判断
    PointCloudEncoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> (compressionProfile, showStatistics);
    PointCloudDecoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> ();
    /***********************************************************************************************************
    下面的代码为OpenNI兼容设备实例化一个新的采样器,并且启动循环回调接口,每从设备获取一帧数据就回调函数一次,,这里的回调函数就是实现数据压缩和可视化解压缩结果。
   ************************************************************************************************************/
    //创建从OpenNI获取点云的抓取对象
    pcl::Grabber* interface = new pcl::OpenNIGrabber ();

    // 建立回调函数
    boost::function<void
    (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f = boost::bind (&SimpleOpenNIViewer::cloud_cb_, this, _1);

    //建立回调函数和回调信息的绑定
    boost::signals2::connection c = interface->registerCallback (f);
    // 开始接受点云的数据流
    interface->start ();

    while (!viewer.wasStopped ())
    {
      sleep (1);
    }

    interface->stop ();

    // 删除压缩与解压缩的实例
    delete (PointCloudEncoder);
    delete (PointCloudDecoder);

  }

  pcl::visualization::CloudViewer viewer;
  pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA>* PointCloudEncoder;
  pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA>* PointCloudDecoder;

};

int
main (int argc, char **argv)
{
  SimpleOpenNIViewer v;  //创建一个新的SimpleOpenNIViewer  实例并调用他的run方法
  v.run ();
  return (0);
}

示例三(官方demo)

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/visualization/cloud_viewer.h>

#include <pcl/compression/octree_pointcloud_compression.h>

#include <stdio.h>
#include <sstream>
#include <stdlib.h>

#ifdef WIN32
# define sleep(x) Sleep((x)*1000)
#endif

class SimpleOpenNIViewer
{
public:
  SimpleOpenNIViewer () :
    viewer (" Point Cloud Compression Example")
  {
  }

  void
  cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
  {
    if (!viewer.wasStopped ())
    {
      // stringstream to store compressed point cloud
      std::stringstream compressedData;
      // output pointcloud
      pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloudOut (new pcl::PointCloud<pcl::PointXYZRGBA> ());

      // compress point cloud
      PointCloudEncoder->encodePointCloud (cloud, compressedData);

      // decompress point cloud
      PointCloudDecoder->decodePointCloud (compressedData, cloudOut);


      // show decompressed point cloud
      viewer.showCloud (cloudOut);
    }
  }

  void
  run ()
  {

    bool showStatistics = true;

    // for a full list of profiles see: /io/include/pcl/compression/compression_profiles.h
    pcl::io::compression_Profiles_e compressionProfile = pcl::io::MED_RES_ONLINE_COMPRESSION_WITH_COLOR;

    // instantiate point cloud compression for encoding and decoding
    PointCloudEncoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> (compressionProfile, showStatistics);
    PointCloudDecoder = new pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA> ();

    // create a new grabber for OpenNI devices
    pcl::Grabber* interface = new pcl::OpenNIGrabber ();

    // make callback function from member function
    std::function<void(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
      [this] (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr& cloud) { cloud_cb_ (cloud); };

    // connect callback function for desired signal. In this case its a point cloud with color values
    boost::signals2::connection c = interface->registerCallback (f);

    // start receiving point clouds
    interface->start ();

    while (!viewer.wasStopped ())
    {
      sleep (1);
    }

    interface->stop ();

    // delete point cloud compression instances
    delete (PointCloudEncoder);
    delete (PointCloudDecoder);

  }

  pcl::visualization::CloudViewer viewer;

  pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA>* PointCloudEncoder;
  pcl::io::OctreePointCloudCompression<pcl::PointXYZRGBA>* PointCloudDecoder;

};

int
main ()
{
  SimpleOpenNIViewer v;
  v.run ();

  return (0);
}

2、空间分区与点云检索

      下篇文章单独讲检索

3、点云数据空间变换检测

官网demo:Spatial change detection on unorganized point cloud data — Point Cloud Library 0.0 documentationicon-default.png?t=N7T8https://pcl.readthedocs.io/projects/tutorials/en/latest/octree_change.html#octree-change-detection

八叉树是一种基于树的数据结构,用于组织稀疏的三维数据。在本demo中,我们将学习如何使用八叉树实现来检测多个无组织点云之间的空间变化,这些变化可能在大小,分辨率,密度和点顺序上有所不同。变换检测主要用于检测点云数据中不同时间点之间的变化。这种变化检测在很多实际应用场景中非常有用,特别是需要监控环境变化或检测动态物体的领域,即识别到场景中物体的变换。

通过递归比较八叉树的树结构,可以识别由体素配置差异所代表的空间变化。

此外,我们解释了如何使用pcl八叉树“双缓冲”技术,使我们能够随着时间的推移有效地处理多个点云。

3.1 示例

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/octree/octree_pointcloud_changedetector.h>
#include <iostream>

int main() {
    // 定义点云类型
    typedef pcl::PointXYZ PointT;

    // 创建两个点云
    pcl::PointCloud<PointT>::Ptr cloudA(new pcl::PointCloud<PointT>);
    pcl::PointCloud<PointT>::Ptr cloudB(new pcl::PointCloud<PointT>);

    // 添加点到第一个点云 (cloudA)
    cloudA->push_back(PointT(1.0, 1.0, 1.0));
    cloudA->push_back(PointT(1.0, 2.0, 1.0));
    cloudA->push_back(PointT(1.0, 3.0, 1.0));

    // 添加点到第二个点云 (cloudB)
    cloudB->push_back(PointT(1.0, 1.0, 1.0));
    cloudB->push_back(PointT(1.0, 2.0, 1.0));
    cloudB->push_back(PointT(1.0, 3.0, 1.0));
    cloudB->push_back(PointT(1.0, 4.0, 1.0)); // 新增点

    // 创建八叉树变化检测器,设置分辨率
    float resolution = 0.5f;
    pcl::octree::OctreePointCloudChangeDetector<PointT> octree(resolution);

    // 将第一个点云 (cloudA) 添加到八叉树中
    octree.setInputCloud(cloudA);
    octree.addPointsFromInputCloud();

    // 切换到第二个点云 (cloudB)
    octree.switchBuffers();
    octree.setInputCloud(cloudB);
    octree.addPointsFromInputCloud();

    // 获取变化检测结果
    std::vector<int> newPointIdxVector;
    octree.getPointIndicesFromNewVoxels(newPointIdxVector);

    // 输出变化点的索引和坐标
    std::cout << "Points added in cloudB:" << std::endl;
    for (std::size_t i = 0; i < newPointIdxVector.size(); ++i) {
        std::cout << "Index: " << newPointIdxVector[i]
                  << ", Point: " << cloudB->points[newPointIdxVector[i]].x << " "
                  << cloudB->points[newPointIdxVector[i]].y << " "
                  << cloudB->points[newPointIdxVector[i]].z << std::endl;
    }

    return 0;
}

3.2 解释 

  • 定义点云类型:使用 pcl::PointXYZ 作为点云的点类型
  • 创建点云:创建两个点云 cloudAcloudB 并向其中添加点
  • 创建八叉树变化检测器:使用 pcl::octree::OctreePointCloudChangeDetector 创建八叉树变化检测器,并设置分辨率。分辨率决定了八叉树的叶子节点大小,即检测变化的精度
  • 添加第一个点云到八叉树中:将第一个点云(cloudA)添加到八叉树中
  • 切换缓冲区:调用 switchBuffers 方法,这样八叉树会保存之前点云的状态,并准备接收新的点云数据。

       OctreePointCloudChangeDetector类继承自Octree2BufBase类,后者能够同时在内存中保持和管理两个八树。此外,它实现了一个内存池,可以重用已经分配的节点对象,从而在生成多点云的八叉树时减少昂贵的内存分配和释放操作。通过调用" octree. switchbuffers() ",重置了八叉树类,同时在内存中保留了之前的八叉树结构。

  • 添加第二个点云到八叉树中:将第二个点云(cloudB)添加到八叉树中。
  • 获取变化检测结果:调用 getPointIndicesFromNewVoxels 方法,获取在第二个点云中新增的点的索引。

      为了检索存储在当前八叉树结构(基于cloudB)体素上的点,这些点在之前的八叉树结构(基于cloudA)中不存在,我们可以调用“getPointIndicesFromNewVoxels”方法,该方法返回结果点索引的向量。

  • 输出变化点:遍历新点的索引,并输出它们的坐标。

三、接口文档学习

pcl_octree库提供了从点云数据创建分层树数据结构的有效方法。这允许对点数据集进行空间分区、下采样和搜索操作。每个八叉树节点要么有八个子节点,要么没有子节点。根节点描述了一个立方体边界框,它封装了所有的点。在每个树级别,该空间被细分为2倍,从而提高体素分辨率。

pcl_octree实现提供了高效的最近邻搜索例程,如“体素内邻居搜索”、“K近邻搜索”和“半径内邻居搜索”。它会根据点数据集自动调整其尺寸。一组叶节点类提供了额外的功能,例如空间“占用”和“每体素点密度”检查。序列化和反序列化函数能够有效地将八叉树结构编码为二进制格式。此外,在需要高速创建八叉树的场景中,内存池实现减少了昂贵的内存分配和释放操作。

1、Octree模块主要类

  1. pcl::octree::OctreePointCloud<T>

    • 功能:这是 Octree 模块的基类,提供了基本的八叉树结构和功能,包括树的构建、插入、删除等操作。
    • 主要子类
      • pcl::octree::OctreePointCloudSinglePoint<T>
      • pcl::octree::OctreePointCloudPointVector<T>
      • pcl::octree::OctreePointCloudVoxelCentroid<T>
  2. pcl::octree::OctreePointCloudSinglePoint<T>

    • 功能:此类继承自 OctreePointCloud<T>,用于每个八叉树节点存储单个点。
  3. pcl::octree::OctreePointCloudPointVector<T>

    • 功能:此类继承自 OctreePointCloud<T>,用于每个八叉树节点存储一个点向量(多个点)。
  4. pcl::octree::OctreePointCloudVoxelCentroid<T>

    • 功能:此类继承自 OctreePointCloud<T>,用于每个八叉树节点存储体素(Voxel)质心。
  5. pcl::octree::OctreePointCloudSearch<T>

    • 功能:提供搜索功能,包括邻域搜索、半径搜索和 K 近邻搜索等。继承自 OctreePointCloudPointVector<T>
  6. pcl::octree::OctreePointCloudCompression<T>

    • 功能:用于点云数据的压缩和解压缩,利用八叉树结构来减少数据存储需求。

2、类之间的关系

OctreePointCloud<T> 是 Octree 模块的基类,其他类通过继承自它来实现不同的功能。具体关系如下:

  • pcl::octree::OctreePointCloud<T>:基类,定义了基本的八叉树操作。
    • pcl::octree::OctreePointCloudSinglePoint<T>:继承自 OctreePointCloud<T>,每个节点存储一个点。
    • pcl::octree::OctreePointCloudPointVector<T>:继承自 OctreePointCloud<T>,每个节点存储一个点向量。
    • pcl::octree::OctreePointCloudVoxelCentroid<T>:继承自 OctreePointCloud<T>,每个节点存储一个体素质心。
    • pcl::octree::OctreePointCloudSearch<T>:继承自 OctreePointCloudPointVector<T>,提供搜索功能。
    • pcl::io::OctreePointCloudCompression<T>:独立实现,但依赖 Octree 结构进行压缩和解压缩。

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

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

相关文章

Java进阶学习笔记6——继承的介绍

继承的学习目标&#xff1a; 认识继承&#xff1b; 继承的好处、应用场景 什么是继承&#xff1f; Java中提供了一个关键字extends&#xff0c;用这个关键字&#xff0c;可以让一个类和另外一个类建立父子关系。 继承的特点: 子类能继承父类的非私有成员&#xff08;成员变…

【JavaEE】加法计算器与用户登录实战演练

目录 综合练习加法计算器1. 准备工作2. 约定前后端交互接口3. 服务器代码 用户登录1. 准备工作2. 约定前后端交互接口3. 服务器代码4. 调整前端页面代码 综合练习 理解前后端交互过程接⼝传参, 数据返回, 以及⻚⾯展⽰ 加法计算器 需求: 输⼊两个整数, 点击"点击相加&q…

windows 7 10 11快捷键到启动页面

1.快速打开用户启动文件夹 shell:startup 方式2&#xff1a;快速打开系统启动文件夹 shell:Common Startup shell:Common Startup

dubbo复习:(7)使用sentinel对dubbo服务进行限流

一、下载sentinel-dashboard 并启动 java -Dserver.port8080 -Dcsp.sentinel.dashboard.serverlocalhost:8080 -Dproject.namesentinel-dashboard -jar sentinel-dashboard.jar二、在spring boot应用中增加sentinel相关依赖 <dependency><groupId>com.alibaba.csp…

Hadoop数据压缩和压缩案例实操

文章目录 数据压缩概述MR支持的压缩编码格式和各自优缺点压缩实操案例1.Map输出端采用压缩2.Reduce输出端采用压缩 数据压缩概述 Hadoop数据压缩是一种通过特定的算法来减小计算机文件大小的机制。这种机制在Hadoop中尤其重要&#xff0c;因为它可以有效减少底层存储系统&…

Docker 模块在宝塔中怎么使用

么是 Docker&#xff1f; Docker 是一个用于开发、发布和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分离&#xff0c;以便您可以快速交付软件。使用 Docker&#xff0c;您可以像管理应用程序一样管理基础设施。通过利用 Docker 快速交付、测试和部署代码的方…

【产品经理】输出

引言&#xff1a;        在最近频繁的产品管理职位面试中&#xff0c;我深刻体会到了作为产品经理需要的不仅仅是对市场和技术的敏锐洞察&#xff0c;更多的是在复杂多变的环境中&#xff0c;如何运用沟通、领导力和决策能力来引导产品从概念走向市场。这一系列博客将分享…

hot100 -- 回溯(上)

目录 &#x1f35e;科普 &#x1f33c;全排列 AC DFS &#x1f6a9;子集 AC DFS &#x1f382;电话号码的字母组合 AC DFS &#x1f33c;组合总和 AC DFS &#x1f35e;科普 忘记 dfs 的&#xff0c;先看看这个&#x1f447; DFS&#xff08;深度优先搜索&#xf…

使用 Flask 和 Celery 构建异步任务处理应用

文章目录 什么是 Flask&#xff1f;什么是 Celery&#xff1f;如何在 Flask 中使用 Celery&#xff1f;步骤 1&#xff1a;安装 Flask 和 Celery步骤 2&#xff1a;创建 Flask 应用程序步骤 3&#xff1a;运行 Celery Worker步骤 4&#xff1a;启动 Flask 应用程序 结论 在构建…

SQLiteOpenHelper数据库帮助器

SQLiteOpenHelper数据库帮助器是Android提供的数据库辅助工具。 1、继承SQLiteOpenHelper类&#xff0c;需要重写onCreate和onUpgrade两个方法 案例&#xff1a;实现增删改查 package com.example.databases_text;import android.app.PictureInPictureParams; import androi…

maven打包报错:MalformedInputException: Input length = 1

maven 打包时报错&#xff1a; [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.3.1:resources (default-resources) on project ec-work-mes: filtering /Users/ecmaster/svn/ecmaster/ynmk/ynmk-mes/ec-work/ec-work-mes/src/main/resou…

【问题处理】maven一直提示artemis-http-client-1.1.8.jar报错(2024-05-25)

项目使用了视频监控&#xff0c;里面涉及到海康威视的视频监控。 问题&#xff1a; pom在导入maven时&#xff0c;报错“Could not find artifact com.artemis:http-client:jar:1.1.8 ” 原因&#xff1a; 根据平台提供的maven地址&#xff0c;填写进pom文件中&#xff0c;编…

从0开始linux(3)——如何读写文件

欢迎来到博主的专栏——从0开始linux 博主ID&#xff1a;代码小豪 文章目录 创建普通文件用文本编辑器nano写入文件如何读取文件cat命令less命令head和tail 我们前面已经了解和如何操作文件&#xff0c;但是目前认识的文件类型分为两类&#xff0c;一类是目录文件、另一类是普通…

PDF 生成在左侧目录栏目录信息的目录 点击跳转

pdf 导出的内容 是itextpdf 写的 目录信息 得用 pdfbox 里的 PDDocumentOutline <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.4.3</version></dependency><dependency&g…

[手游] 正义对决3

《正义对决3联机版》是一款多人联机的竞技射击游戏&#xff0c;玩家将扮演警方和强盗两个不同的势力&#xff0c;展开一场在庞大都市中的正义之战。强盗一方将在城市内抢劫各处并藏匿&#xff0c;而警方则必须将所有罪犯绳之以法。游戏中&#xff0c;玩家可自由购买众多武器装备…

OpenCASCADE Draw模块TKDraw项目问题修改

1.问题 在调试Draw模块代码时&#xff0c;出现一个小问题&#xff0c;导致无法正常运行 如下&#xff1a; 2.代码跟踪 通过代码跟踪发现时一个数组越界问题&#xff0c;在此处添加了判断处理&#xff0c;程序可以正常调试

批量复制文件智能删除已复制,轻松管理文件新体验!让您的文件整理更高效无忧

在信息爆炸的时代&#xff0c;文件管理无疑成为我们日常生活和工作中不可或缺的一部分。面对堆积如山的文件&#xff0c;我们时常陷入无尽的复制、粘贴、删除循环中&#xff0c;不仅耗时耗力&#xff0c;还容易出错。但今天&#xff0c;我要向您推荐一款颠覆传统的文件管理工具…

手撕算法|斯坦福大学教授用60页PPT搞定了八大神经网络

人工智能领域深度学习的八大神经网络常见的是以下几种 1.卷积神经网络&#xff08;CNN&#xff09;&#xff1a; 卷积神经网络是用于图像和空间数据处理的神经网络&#xff0c;通过卷积层和池化层来捕捉图像的局部特征&#xff0c;广泛应用于图像分类、物体检测等领域。 2.循…

Convolutional Occupancy Networks【ECCV】

论文&#xff1a;https://arxiv.org/pdf/2003.04618 代码&#xff1a;GitHub - autonomousvision/convolutional_occupancy_networks: [ECCV20] Convolutional Occupancy Networks 图 1&#xff1a;卷积占据网络。传统的隐式模型 (a) 由于其全连接网络结构&#xff0c;表现能力…

真拿AI赚到钱的人,不在朋友圈里

1 最近有张两大AI巨头对比的梗图给我看乐了&#xff0c;玩儿AI的还在做产品&#xff0c;玩儿焦虑的已经在数钱了。 这也是在做AI&#xff0c;只不过是唉声叹气的ai。 要我说&#xff0c;现在缺的根本不是AI&#xff0c;而是【有用的AI】。 恩格斯老师说过一句话&#xff1a…