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

从零开始学习Slam|ICP原理与应用

ICP全称Iterative Closest Point,翻译过来就是迭代最近点。ICP在点云配准(registration)领域应用的非常广泛.

ICP算法流程

  1. 首先对于一幅点云中的每个点,在另一幅点云中计算匹配点(最近点)

  2. 极小化匹配点间的匹配误差,计算位姿

  3. 然后将计算的位姿作用于点云

  4. 再重新计算匹配点

  5. 如此迭代,直到迭代次数达到阈值,或者极小化的能量函数变化量小于设定阈值

求解ICP的三个步骤

  1. 计算两组点的质心位置 (平均位置)p,p’,然后计算每个点的去质心坐标: q i = p i − p ; q i ′ = p i ′ − p ′ q_i= p_i - p; q_i' = p_i'-p' qi=pip;qi=pip
  2. 根据以下优化问题计算旋转矩阵:
    这一步的目标是找到一个旋转矩阵 R ∗ 这一步的目标是找到一个旋转矩阵R^* 这一步的目标是找到一个旋转矩阵R ,使得 旋转后的点集 R q i ′ 与点集 q i 之间的距离最小。 旋转后的点集{Rq_i'}与点集 {q_i }之间的距离最小。 旋转后的点集Rqi与点集qi之间的距离最小。这里的距离是通过计算每个点对之间的欧氏距离的平方和来衡量的:
    R ∗ = a r g m i n R 1 2 ∑ i = 1 n ∥ q i − R q i ′ ∥ 2 R^* = argmin_R \frac{1}{2}\sum_{i=1}^{n}\left\| q_i - Rq_i' \right\|^2 R=argminR21i=1nqiRqi2,n是点的数量。
  3. 根据第二步的 R,计算 t:
    一旦找到了最优的旋转矩阵 R* ,就可以计算平移向量 t* 。这个向量表示在旋转和平移之后,两个点集的质心之间的相对位置。
    平移向量 t* 的计算公式是: t ∗ = p − R ∗ p ′ t^*= p−R^* p' t=pRp 。这里,p 和 p’ 是原始点集的质心,R* 是找到的最优旋转矩阵。

缺陷

上面介绍是最简单的点和点匹配的ICP算法,实际情况中由于噪声,我们仍需其他方法去使算法更加鲁棒。例如,极小化的误差项包括对应点的点到点的欧式距离,和对应点的点到平面距离,以及极小化对应点的颜色值误差等。2003年的时候,pottman 和Hofer两位大牛的论文中证明了当两幅点云比较接近时,极小化对应点的点到平面距离比点到点距离更接近两个平面之间的真实距离,也就是说计算点到平面的距离更靠谱!
在这里插入图片描述

题目

1.

在这里插入图片描述
证明:

  1. 展开等式左边, q i T R q i ′ q_i^T Rq_i' qiTRqi是一个标量(向量乘以矩阵再乘以向量的结果是标量)
  2. 展开等式右边 :
    由于 R q i ′ q i T Rq_i'q_i^T RqiqiT是一个矩阵,其第i个对角线元素可以表示为: ∑ j = 1 n R i j ( q i ′ q i T ) j i \sum_{j=1}^{n}R_{ij}(q_{i}'q_{i}^T)_{ji} j=1nRij(qiqiT)ji
    由于 q i ′ q i T q_i'q_i^T qiqiT是一个外积,其元素 ( q i ′ q i T ) j i (q_i'q_i^T)_{ji} (qiqiT)ji
    可以表示为:
    ( q i ′ q i T ) j i = q i ′ j q i , j (q_i'q_i^T)_{ji}=q_{i'j}q_{i,j} (qiqiT)ji=qijqi,j
    因此我们可以将 ( R q i ′ q i T ) i i (Rq_i'q_i^T)_{ii} (RqiqiT)ii重写为 ( R q i ′ q i T ) i i = ∑ j = 1 n R i j q i ′ , j q i , j (Rq_i'q_i^T)_{ii} = \sum_{j=1}^n R_{ij} q_{i',j} q_{i,j} (RqiqiT)ii=j=1nRijqi,jqi,j将这个表达式代入迹的计算中,我们得到:
    tr ( R q i ′ q i T ) = ∑ i = 1 n ∑ j = 1 n R i j q i ′ j q i , j \text{tr}(R q_i' q_i^T) = \sum_{i=1}^n \sum_{j=1}^n R_{ij} q_{i'j}q_{i,j} tr(RqiqiT)=i=1nj=1nRijqijqi,j这实际上是 q i T R q i ′ q_i^TRq_i' qiTRqi的展开形式,因为:
    q i T R q i ′ = ∑ i = 1 n ∑ j = 1 n q i , i R i j q i ′ j q_i^T R q_i' = \sum_{i=1}^n \sum_{j=1}^n q_{i,i} R_{ij} q_{i'j} qiTRqi=i=1nj=1nqi,iRijqij
    由于矩阵乘法的交换律,我们可以将 q i ′ i 和 q i ′ j q _{i'i}和 q_{i'j } qiiqij的顺序交换,得到:
    q i T R q i ′ = ∑ i = 1 n ∑ j = 1 n R i j q i ′ j q i , j q_i^T R q_i' = \sum_{i=1}^n \sum_{j=1}^n R_{ij} q_{i'j} q_{i,j} qiTRqi=i=1nj=1nRijqijqi,j

2.

2、 精心设计的ICP编程实践

给定一个轨迹1,数据格式:timestamp tx ty tz qx qy qz qw, 自定义一个任意的旋转矩阵和平移向量(可以尝试不同的值,甚至加一些噪声看看结果有什么变化),对轨迹1进行变换,得到一个新的轨迹2, 使用ICP算法(提示:取平移作为三维空间点)估计轨迹1,2之间的位姿,然后将该位姿作用在轨迹2。

验证:ICP算法估计的旋转矩阵和平移向量是否准确;轨迹1,2是否重合。

如下是我加了一个旋转平移量后的两个轨迹,经过ICP计算好位姿后再反作用在变换后的轨迹,最终两个轨迹是重合滴!

/***************************** 题目:给定一个轨迹1,数据格式:timestamp tx ty tz qx qy qz qw* 自定义一个任意的旋转矩阵和平移向量(可以尝试不同的值看看结果有什么变化),对轨迹1进行变换,得到一个新的轨迹2* 使用ICP算法(提示:取平移作为三维空间点)估计轨迹1,2之间的位姿,然后将该位姿作用在轨迹2* 验证:ICP算法估计的旋转矩阵和平移向量是否准确;轨迹1,2是否重合* 
* 本程序学习目标:* 熟悉ICP算法的原理及应用。** 公众号:计算机视觉life。发布于公众号旗下知识星球:从零开始学习SLAM,参考答案请到星球内查看。* 时间:2019.05* 作者:小六
****************************/
#include <iostream>
#include "sophus/se3.h"
#include <fstream>
#include <pangolin/pangolin.h>
#include <opencv2/core/core.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <Eigen/SVD>using namespace std;
using namespace cv;void DrawTrajectory(vector<Sophus::SE3, Eigen::aligned_allocator<Sophus::SE3>> pose1,vector<Sophus::SE3, Eigen::aligned_allocator<Sophus::SE3>> pose2);int main()
{// path to trajectory filestring trajectory_file = "../trajectory.txt";vector<Sophus::SE3, Eigen::aligned_allocator<Sophus::SE3>> pose_groundtruth;vector<Sophus::SE3, Eigen::aligned_allocator<Sophus::SE3>> pose_new;vector<Sophus::SE3, Eigen::aligned_allocator<Sophus::SE3>> pose_estimate;vector<Point3f> pts_new, pts_groundtruth;Eigen::Quaterniond q;Eigen::Vector3d t;Sophus::SE3 T;string timestamp;ifstream textFile;// 自定义一个变换矩阵/********************** 开始你的代码,参考星球里作业5代码 ****************************/// 旋转向量(轴角):沿Z轴旋转45°Eigen::Vector3d rotation_vector(0, 0, M_PI / 4); // 沿Z轴旋转45°// 平移向量,可以自己自定义,我这里是 x=3, y=-1, z=0.8,可以多尝试其他值Eigen::Vector3d translation_vector(3, -1, 0.8); // 平移向量/********************** 结束你的代码 ****************************/Sophus::SE3 myTransform(rotate,tranlation);cout<<"rotation matrix =\n"<<rotation_vector.matrix() <<endl;cout<<"translation vector =\n"<<tranlation <<endl;cout<<"myTransform =\n"<<myTransform.matrix() <<endl;textFile.open(trajectory_file.c_str());// 读取轨迹数据/********************** 开始你的代码,参考星球里作业8代码 ****************************/// 提示:取平移作为三维空间点,平移向量 t 直接表示了刚体变换后的坐标系原点在世界坐标系中的位置。因此,它可以被看作是一个三维空间中的点的坐标。while (textFile >> timestamp >> t.x() >> t.y() >> t.z() >> q.x() >> q.y() >> q.z() >> q.w()) {Sophus::SE3 pose(q, t);pose_groundtruth.push_back(pose);                                     // pose 位姿 包含位置和方向pts_groundtruth.push_back(Point3f(t.x(), t.y(), t.z()));             //pts是points的缩写,表示三维空间的一个点// 应用变换生成新的轨迹Eigen::Vector3d new_t = myTransform * t;// 表示将三维向量 t 通过刚体变换 myTransform 进行变换,得到新的三维向量 new_t// myTransform.so3() 是 Sophus::SE3 类的一个方法,它提取出旋转部分,并将其表示为 Sophus::SO3 类型。// Sophus::SO3 是一个专门用于表示三维旋转的类,可以使用旋转矩阵或四元数来表示旋转。// unit_quaternion() 是 Sophus::SO3 类的一个方法,它将旋转表示为单位四元数。Eigen::Quaterniond new_q = q * myTransform.so3().unit_quaternion();//表示将原始旋转 q 与 myTransform 的旋转部分进行复合,生成新的旋转四元数 new_qpose_new.push_back(Sophus::SE3(new_q, new_t));pts_new.push_back(Point3f(new_t.x(), new_t.y(), new_t.z()));}/********************** 结束你的代码 ****************************/textFile.close();// 使用ICP算法估计轨迹1,2之间的位姿,然后将该位姿作用在轨迹2/********************** 开始你的代码,参考十四讲中第7章ICP代码 ****************************/Mat pts1, pts2;pts1 = Mat(pts_groundtruth).reshape(0, pts_groundtruth.size());pts2 = Mat(pts_new).reshape(0, pts_new.size());Mat R, t;Mat outliers;             // outliers 是指那些在匹配过程中未能正确配对的点int method = cv::SOLVEPNP_ITERATIVE;double reprojThreshold = 3.0;bool useExtrinsicGuess = false;// 使用solvePnP估计位姿solvePnP(pts1, pts2, Mat::eye(3, 3, CV_64F), Mat::zeros(4, 1, CV_64F), R, t, useExtrinsicGuess, method, noArray(), &outliers);// 将旋转矩阵从Rodrigues形式转换为3x3矩阵Rodrigues(R, R);// 输出估计的位姿cout << "Estimated rotation matrix:\n" << R << endl;cout << "Estimated translation vector:\n" << t.t() << endl;// 将估计的位姿作用于轨迹2for (size_t i = 0; i < pose_new.size(); i++) {Eigen::Vector3d new_t = R * pose_new[i].translation() + t.t();Eigen::Quaterniond new_q = pose_new[i].so3().unit_quaternion() * Eigen::Quaterniond(R);pose_estimate.push_back(Sophus::SE3(new_q, new_t));}/********************** 结束你的代码 ****************************///    DrawTrajectory(pose_groundtruth, pose_new);  // 变换前的两个轨迹DrawTrajectory(pose_groundtruth, pose_estimate);  // 轨迹应该是重合的return 0;
}void DrawTrajectory(vector<Sophus::SE3, Eigen::aligned_allocator<Sophus::SE3>> pose1,vector<Sophus::SE3, Eigen::aligned_allocator<Sophus::SE3>> pose2) {if (pose1.empty()||pose2.empty()) {cerr << "Trajectory is empty!" << endl;return;}// create pangolin window and plot the trajectorypangolin::CreateWindowAndBind("Trajectory Viewer", 1024, 768);glEnable(GL_DEPTH_TEST);glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);pangolin::OpenGlRenderState s_cam(pangolin::ProjectionMatrix(1024, 768, 500, 500, 512, 389, 0.1, 1000),pangolin::ModelViewLookAt(0, -0.1, -1.8, 0, 0, 0, 0.0, -1.0, 0.0));pangolin::View &d_cam = pangolin::CreateDisplay().SetBounds(0.0, 1.0, pangolin::Attach::Pix(175), 1.0, -1024.0f / 768.0f).SetHandler(new pangolin::Handler3D(s_cam));while (pangolin::ShouldQuit() == false) {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);d_cam.Activate(s_cam);glClearColor(1.0f, 1.0f, 1.0f, 1.0f);glLineWidth(2);for (size_t i = 0; i < pose1.size() - 1; i++) {glColor3f(1 - (float) i / pose1.size(), 0.0f, (float) i / pose1.size());glBegin(GL_LINES);auto p1 = pose1[i], p2 = pose1[i + 1];glVertex3d(p1.translation()[0], p1.translation()[1], p1.translation()[2]);glVertex3d(p2.translation()[0], p2.translation()[1], p2.translation()[2]);glEnd();}for (size_t i = 0; i < pose2.size() - 1; i++) {glColor3f(1 - (float) i / pose2.size(), 0.0f, (float) i / pose2.size());glBegin(GL_LINES);auto p1 = pose2[i], p2 = pose2[i + 1];glVertex3d(p1.translation()[0], p1.translation()[1], p1.translation()[2]);glVertex3d(p2.translation()[0], p2.translation()[1], p2.translation()[2]);glEnd();}pangolin::FinishFrame();usleep(5000);   // sleep 5 ms}
}

相关文章:

从零开始学习Slam|ICP原理与应用

ICP全称Iterative Closest Point&#xff0c;翻译过来就是迭代最近点。ICP在点云配准&#xff08;registration&#xff09;领域应用的非常广泛. ICP算法流程 首先对于一幅点云中的每个点&#xff0c;在另一幅点云中计算匹配点&#xff08;最近点&#xff09; 极小化匹配点间…...

算法与数据结构面试题

算法与数据结构面试题 加油&#xff01; 考查数据结构本身 什么是数据结构 简单地说&#xff0c;数据结构是以某种特定的布局方式存储数据的容器。这种“布局方式”决定了数据结构对于某些操作是高效的&#xff0c;而对于其他操作则是低效的。首先我们需要理解各种数据结构&a…...

尚硅谷shell脚本学习

视频&#xff1a;【尚硅谷】Shell脚本从入门到实战_哔哩哔哩_bilibili 学一点shell脚本能帮助进行自动化操作。苹果电脑默认环境是/bin/bash/ 通过echo $SHELL 可以查看苹果本机的内核&#xff0c;我的属于/bin/zsh/.注意zsh和bash没有什么区别。 一、Shell脚本入门 1&#…...

设计模式分类与定义(高软55)

系列文章目录 设计模式 文章目录 系列文章目录前言一、设计模式分类二、设计模式定义三、真题总结 前言 本节讲明常用设计模式的定义、关键点知识&#xff0c;很有意义哦。 一、设计模式分类 二、设计模式定义 三、真题 总结 就是高软笔记&#xff0c;大佬请略过&#xff01;...

天梯赛 L2-025 分而治之

这个题的主要考点还是邻接表建图&#xff0c;很简单的一道题&#xff0c;每次只需要判断没有被摧毁的城市邻居是不是都被摧毁了。 #include<bits/stdc.h> using namespace std; int main(){int n,m;cin>>n>>m;vector<vector<int>> g(n1);for(in…...

MySQL的进阶语法7(索引-B+Tree 、Hash、聚集索引 、二级索引(回表查询)、索引的使用及设计原则

目录 一、索引概述 1.1 基本介绍 1.2 基本演示 1.3 特点及优势 二、索引结构 2.1 概述 2.2 二叉树 2.3 B-Tree 2.4 BTree 2.5 Hash 2.5.1 结构 2.5.2 特点 2.5.3 存储引擎支持 三、索引的分类 3.1 索引分类 3.2 聚集索引和二级索引 3.2.1 聚集索引和二级…...

芯片射频前端电路架构

2.4GHz射频前端电路的设计需要平衡多方面性能需求&#xff0c;是无线通信系统的关键技术环节&#xff0c;主要由以下几个关键模块组成&#xff1a; 1. 发射链路 - 数字信号转换 - 调制电路 -本地振荡器 - 功率放大器 - 天线匹配网络 2. 接收链路 - 低噪声放大器(LNA)…...

使用STM32CubeMX和Keil在STM32上创建并运行一个简单的FreeRTOS多任务程序

目标 利用FreeRTOS运行两个任务&#xff0c;分别为点灯和OLED屏的显示。 利用STM32CubeMX生成Keil工程和相关初始化代码 知识回顾 之前已经利用STM32CubeMX生成过Keil工程和相关初始化代码了&#xff0c;可以去回顾一下&#xff0c;详情见&#xff1a;https://blog.csdn.ne…...

Spring AI Alibaba 快速开发生成式 Java AI 应用

Spring AI Alibaba 是一款 Java 语言实现的 AI 应用开发框架&#xff0c;旨在简化 Java AI 应用程序开发&#xff0c;让 Java 开发者像使用 Spring 开发普通应用一样开发 AI 应用。Spring AI Alibaba 基于 Spring AI 开源项目构建&#xff0c;默认提供阿里云基础模型服务、开源…...

记录学习的第十七天

今天对昨天下午的洛谷蓝桥杯模拟赛和今天早上的力扣周赛进行复盘。 昨天的蓝桥杯模拟赛&#xff0c;硬坐了4个小时&#xff0c;只会做前面的三道入门题。&#x1f625;而且第一道填空题竟然还算错了。其他的五道题我都没啥思路了&#xff0c;实在难受啊&#xff01; Q1:这道题硬…...

穿透单链表的神秘屏障,洞察数据结构的真谛

❤个人主页&#xff1a;折枝寄北的博客 ❤专栏位置&#xff1a;数据结构 单链表实现逻辑 0. 前言1. 概念及结构2. 实现逻辑2.1 相关函数的声明2.2 函数代码实现2.2.1 打印2.2.2 创建新节点2.2.3 尾插2.2.4 头插2.2.5 尾删2.2.6 头删2.2.7 查找2.2.8 pos位置前插入2.2.9 pos位置…...

腾讯云智测试开发面经

1、投递时间线 2.20投递简历&#xff0c;3.11第一轮面试&#xff0c;3.30第二轮面试&#xff0c;4.4第三轮面试&#xff0c;4.10第四轮面试&#xff0c;4.11offer意向书 2、第一轮面试 第一轮面试技术面&#xff0c;面试官是导师&#xff0c;面试时长40多分钟 1&#xff09…...

react+antd封装一个可回车自定义option的select并且与某些内容相互禁用

需求背景 一个select框 现在要求可多选 并且原有一个any的选项 其他选项为输入后回车自己增加 若选择了any 则其他选项不可选择反之选择其他选项any不可选择 并且回车新增时也不可直接加入到选中数组只加入到option内 并且不可重复添加新内容 实现过程 <Form.Item …...

笔记1——数据通信网络基础

一、概述 数据通信网络&#xff1a;由路由器、交换机、防火墙、无线设备以终端构成的网络 功能&#xff1a;实现数据互通 二、网络设备 交换机&#xff1a; 特点&#xff1a;距离终端用户最近的设备 作用&#xff1a;终端接入、二层交换机 广播域:交换机连接的终端构成一个广播…...

全国产FMC子卡-16bit 8通道2.4G

国产化FMC DA子卡&#xff0c;16bit 8通道2.4GS/s 全国产FMC子卡是一款高分辨率、高采样率的全国产多通道标准双宽DAC FMC子板。其接口电气和结构设计均依据FMC标准(ANSI/VITA 57.1)&#xff0c;通过两个高密度FMC连接器&#xff08;HPC&#xff09;连接至FPGA载板。它提供8路A…...

ZLMediaKit 源码分析——[4] ZLToolKit 中EventPoller之异步任务处理

系列文章目录 第一篇 基于SRS 的 WebRTC 环境搭建 第二篇 基于SRS 实现RTSP接入与WebRTC播放 第三篇 centos下基于ZLMediaKit 的WebRTC 环境搭建 第四篇 WebRTC学习一&#xff1a;获取音频和视频设备 第五篇 WebRTC学习二&#xff1a;WebRTC音视频数据采集 第六篇 WebRTC学习三…...

基于 DeepSeek 与天地图搭建创新地理信息应用

一、技术背景 DeepSeek 是由国内公司研发的一款具有强大参数规模与性能的大语言模型&#xff0c;它能够处理复杂的自然语言指令&#xff0c;提供丰富的分析与建议。天地图则是国家地理信息公共服务平台&#xff0c;提供权威、丰富的地理信息数据&#xff0c;涵盖卫星影像、矢量…...

python函数装饰器

python函数装饰器 声明&#xff1a;博主并没有系统学习过python语言&#xff0c;在实际项目中遇到关于python不懂的语法&#xff0c;这里仅作为个人学习积累笔记 1.1 python函数相关基础 深入了解python函数装饰器移步&#xff1a;Python 函数装饰器 下面的笔记来源于上述链接…...

AI战略群与星际之门:软银AI投资版图计划深度解析

一、星际之门:万亿美元级 AI 基础设施革命 1.1 项目背景与战略定位 在 AI 技术迅猛发展的今天,算力已成为推动其前进的核心动力。软银联合 OpenAI、甲骨文、英伟达、微软、arm推出的 “星际之门”(Stargate)计划,无疑是 AI 领域的一颗重磅炸弹。作为 AI 领域史上最大单笔…...

Modbus TCP转profibusDP网关接防撞雷达快速配置

Modbus TCP转profibusDP网关接防撞雷达快速配置 在工业自动化领域中&#xff0c;不同的设备可能使用不同的通信协议。当需要将使用 ModbusTCP 协议的防撞雷达连接到ProfibusDP网络时&#xff0c;需要使用协议转换器来实现协议的转换。 本文将详细介绍如何通过ModbusTCP转Profi…...

O(1) 时间复杂度数据设计题

0x00 preface 所谓 O ( 1 ) O(1) O(1) A P I API API 设计&#xff0c;并不是说&#xff0c;时间复杂度必须是**“总是”常数级别的。 对于一个操作来说&#xff0c;如果他偶尔是 O ( N ) O(N) O(N) 的&#xff0c;大部分时间都是 O ( 1 ) O(1) O(1) 的&#xff0c;并且&a…...

基于Spring AI与Ollama构建本地DeepSeek对话机器人

1、安装ollama&#xff1a; 打开Ollama下载官网&#xff0c;根据自己的操作系统下载相应版本的安装文件。 由于Ollama默认安装在C盘&#xff0c;而Ollama和模型文件都非常大&#xff0c;如果安装在C盘非常占用系统空间&#xff0c;可以使用下面的方法将Ollama安装到指定为止 …...

边缘计算赋能淘宝API:分布式节点缓存降低高并发延迟

以下是关于 “边缘计算赋能淘宝 API&#xff1a;分布式节点缓存降低高并发延迟” 的相关内容介绍&#xff1a; 背景 淘宝作为大型电商平台&#xff0c;每天面临海量的用户访问和高并发请求。在传统的集中式计算架构下&#xff0c;处理如此大规模的请求容易导致网络延迟、响应速…...

Keepalived+LVS+nginx高可用架构

注明&#xff1a;所有软件已经下载好&#xff0c;防火墙和SELinux已经全部关闭 一.搭建NFS 1.服务端 1.创建文件 [rootnfs ~]# mkdir -p /nfs/data 2、修改权限 [rootnfs ~]# chmod orw /nfs/data 3、写配置文件 [rootnfs ~]# cat /etc/exports /nfs/data 192.168.111.118(r…...

CMake学习--如何在CMake中编译静态库、动态库并在主程序中调用

目录 一、背景知识二、使用方法&#xff08;一&#xff09;编译静态库&#xff08;二&#xff09;编译动态库&#xff08;三&#xff09;在主程序中调用库 三、总结 一、背景知识 在C/C开发中&#xff0c;库&#xff08;Library&#xff09;是预先编译好的代码集合&#xff0c…...

技术回顾day3

1.获取文件信息、获取视频信息 走的都是同一个方法&#xff1a;baseController里面的getFile。 在getFile方法里面进行判断文件的类型&#xff0c;判断是不是m3u8类型或者ts类型做一些额外的处理。 获取信息底层就是读取文件&#xff0c;然后写入response的OutputStream ou…...

【dp + 裴蜀定理】P8646 [蓝桥杯 2017 省 AB] 包子凑数 题解

P8646 [蓝桥杯 2017 省 AB] 包子凑数 题解 题目传送门 P8646 [蓝桥杯 2017 省 AB] 包子凑数 一、题目描述 小明发现包子铺有N种蒸笼&#xff0c;每种能放A_i个包子&#xff08;无限供应&#xff09;。问有多少个正整数X无法被这些蒸笼数量的组合表示出来。若无限多个则输出…...

在HarmonyOS NEXT 开发中,如何指定一个号码,拉起系统拨号页面

大家好&#xff0c;我是 V 哥。 《鸿蒙 HarmonyOS 开发之路 卷1 ArkTS篇》已经出版上市了哈&#xff0c;有需要的朋友可以关注一下&#xff0c;卷2应用开发篇也马上要出版了&#xff0c;V 哥正在紧锣密鼓的写鸿蒙开发实战卷3的教材&#xff0c;卷3主要以项目实战为主&#xff0…...

网络华为HCIA+HCIP 策略路由,双点双向

目录 路由策略&#xff0c;策略路由 策略路由优势 策略路由分类 接口策略路由 双点双向 双点双向路由引入特点: 联系 路由回灌和环路问题 路由策略&#xff0c;策略路由 路由策略:是对路由条目进行控制&#xff0c;通过控制路由条目影响报文的转发路径&#xff0c;即路…...

探索Doris:日志分析的新宠,是否能取代老牌ES?

在大数据时代&#xff0c;日志存储与分析对于企业的运营和决策起着至关重要的作用。Elasticsearch&#xff08;简称 ES&#xff09;作为一款广泛应用的开源分布式搜索和分析引擎&#xff0c;长期以来在日志管理领域占据着举足轻重的地位。然而&#xff0c;随着技术的不断发展&a…...

常见电源模块设计

目录 1. 5V电源模块 2. 3.3V电源模块 3. 1.9V电源模块 4. 220V转12V电源模块 1. 5V电源模块 参考电路 电路说明&#xff1a; 这个电路采用的是稳压芯片78L05&#xff0c;我是用的12V的电源模块转成为5V,为后续的供电。 2. 3.3V电源模块 参考电路&#xff1a; 电路说明…...

虚幻引擎控制角色跟随移动方向旋转的方法

在UE5中&#xff0c;要控制角色随移动方向旋转&#xff0c;可以使用蓝图和C两种方式来实现。 使用蓝图 1、选中角色移动组件&#xff0c;勾选将旋转朝向运动。 2、选中当前角色类 取消勾选使用控制器旋转的几个选项 3、这时&#xff0c;摄像机会跟着角色一起旋转。如果不希望…...

Oracle 23ai Vector Search 系列之3 集成嵌入生成模型(Embedding Model)到数据库示例,以及常见错误

文章目录 Oracle 23ai Vector Search 系列之3 集成嵌入生成模型&#xff08;Embedding Model&#xff09;到数据库示例&#xff0c;以及常见错误使用安装了Oracle 23ai 的虚拟机&#xff08;Oracle Database 23ai Free VirtualBox Appliance&#xff09;1.下载[Oracle VM Virtu…...

RISC-V debug专栏2 --- Debug Module(DM)

Debug Module&#xff08;DM&#xff09;的核心功能 DM 就像一个翻译官&#xff0c;负责把调试器的抽象指令&#xff08;比如 “暂停处理器”&#xff09;转换成硬件能听懂的具体操作。它必须实现以下基本功能&#xff1a; 必要功能&#xff08;必须实现&#xff09;&#xff…...

LLM 分词器Tokenizer 如何从 0 到 1 训练出来

写在前面 大型语言模型(LLM)处理的是人类的自然语言,但计算机本质上只能理解数字。Tokenizer(分词器) 就是架在自然语言和计算机数字表示之间的一座至关重要的桥梁。它负责将我们输入的文本字符串分解成模型能够理解的最小单元——Token,并将这些 Token 转换成对应的数字…...

蓝桥杯冲刺:一维前缀和

系列文章目录 蓝桥杯系列&#xff1a;一维前缀和 文章目录 系列文章目录前言一、暴力的写法&#xff1a;二、一维前缀和的模板&#xff1a; 具体实现&#xff1a; 三、具体例题&#xff1a;求和 1.题目参考&#xff1a;2.以下是具体代码实现&#xff1a; 总结 前言 上次我介绍…...

光学关键尺寸量测设备市场报告:2024年全球市场销售额达到了14.75亿美元

一、引言 光学关键尺寸量测设备作为半导体制造、精密加工等领域的核心工具&#xff0c;其重要性不言而喻。随着科技的飞速发展&#xff0c;这些设备在提升产品精度、缩短研发周期、降低生产成本等方面发挥着越来越关键的作用。本报告旨在深入分析光学关键尺寸量测设备的技术特…...

链表的操作-反转链表

链表 160相交链表 代码 class Solution { public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* h1headA;ListNode* h2headB;while(h1&&h2){if(h1!h2){h1h1->next;h2h2->next;}else{return h1;}}if(h1nullptr){h1headB;}else{h…...

2025 年浙江危化品经营单位考试攻略分享​

浙江的考试由省应急管理部门主导。理论考试突出危化品在电商、物流等新兴业态下的安全管理知识&#xff0c;这与浙江发达的电商产业紧密相关。对危险化学品的环境危害及防治知识考查细致。实际操作考核模拟杭州、宁波等地危化品仓储物流中心的作业情况。​ 报名材料准备齐全后…...

python使用cookie、session、selenium实现网站登录(爬取信息)

一、使用cookie 这段代码演示了如何使用Python的urllib和http.cookiejar模块来实现网站的模拟登录&#xff0c;并在登录后访问需要认证的页面。 # 导入必要的库 import requests from urllib import request, parse# 1. 导入http.cookiejar模块中的CookieJar类&#xff0c;用…...

STM32开发板上生成PWM正弦波

在STM32开发板上生成正弦波通常需要结合定时器&#xff08;TIM&#xff09;、数模转换器&#xff08;DAC&#xff09;或脉宽调制&#xff08;PWM&#xff09;以及时钟系统的配置。以下是分步指南&#xff1a; 方法1&#xff1a;使用DAC 定时器&#xff08;推荐&#xff09; 步…...

Spring Boot 实现文件秒传功能

前言 在开发Web应用时&#xff0c;文件上传是一个常见需求。然而&#xff0c;当用户需要上传大文件或相同文件多次时&#xff0c;会造成带宽浪费和服务器存储冗余。此时可以使用文件秒传技术通过识别重复文件&#xff0c;实现瞬间完成上传的效果&#xff0c;大大提升了用户体验…...

【Vue2】数据绑定_MVVM模型_数据代理_事件处理

目录 一、 数据绑定 1. Vue中有2种数据绑定的方式&#xff1a; 2. 响应式原理 el 与 data 的两种写法 二、 MVVM模型 三、 数据代理 1.回顾Object defineproperty方法 2. 何为数据代理 3.Vue中的数据代理 四、 事件处理 1.事件的基本使用&#xff1a; 2. Vue中的事…...

Python数据类型-dict

Python数据类型-dict 字典是Python中一种非常强大且常用的数据类型&#xff0c;它使用键-值对(key-value)的形式存储数据。 1. 字典的基本特性 无序集合&#xff1a;字典中的元素没有顺序概念可变(mutable)&#xff1a;可以动态添加、修改和删除元素键必须唯一且不可变&…...

win10之mysql server 8.0.41安装

一 mysql server 下载 官网下载地址页面 https://dev.mysql.com/downloads/mysql/二 免装版使用步骤 1 解压 下载完成后,解压文件夹,如下所示: 2 执行安装命令 D:\soft\mysql\mysql-8.0.41-winx64\mysql-8.0.41-winx64\bin>mysqld --install Service successfully in…...

解决Oracle PL/SQL中“表或视图不存在“错误的完整指南

解决Oracle PL/SQL中"表或视图不存在"错误的完整指南 前言问题概述根本原因分析一、 编译时与运行时验证差异二、权限问题三、 Schema命名问题 实际案例演示案例1&#xff1a;动态分表查询案例2&#xff1a;权限不足的场景 实用排查步骤排查流程图最佳实践建议解决方…...

从实用的角度聊聊Linux下文本编辑器VIM

本文从实用的角度聊聊Vim的常用命令。何为实用&#xff1f;我举个不实用的例子大家就明白了&#xff0c;用vim写代码。;) “vim是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富&#xff0c;在程序员中被广泛使用&#xff0c;和Emacs并列成…...

MySQL的进阶语法8(SQL优化——insert、主键、order by、group by、limit、count和update)

目录 一、插入数据 1.1 insert 1.2 大批量插入数据 二、主键优化 2.1 数据组织方式 2.2 页分裂 2.2.1 主键顺序插入效果 2.2.2 主键乱序插入效果 2.3 页合并 2.4 索引设计原则 三、order by优化 3.1 执行以下两条语句&#xff08;无索引&#xff09; 3.2 创建索引…...

STM32F103C8T6单片机硬核原理篇:讨论GPIO的基本原理篇章1——只讨论我们的GPIO简单输入和输出

目录 前言 输出时的GPIO控制部分 标准库是如何操作寄存器完成GPIO驱动的初始化的&#xff1f; 问题1&#xff1a;如何掌握GPIO的编程细节——跟寄存器如何打交道 问题2&#xff1a;哪些寄存器&#xff0c;去哪里找呢&#xff1f; 问题三&#xff0c;寄存器的含义&#xff…...

FreeRTOS源码下载分享

FreeRTOS源码下载分享 官网下载太慢了&#xff0c;分享下FreeRTOSv202411 FreeRTOSv202411.00.zip 链接: https://pan.baidu.com/s/1P4sVS5WroYEl0WTlPD7GXg 提取码: g6aq...