06 单目初始化器 Initializer

06 单目初始化器 Initializer

单目 SLAM 初始化相关,双目和 RGBD 不会使用这个类

单目相机运动得到两帧图像,调用该类,当满足一定条件时认为初始化成功,否则重新初始化。

6.1 成员变量/函数

在这里插入图片描述

用 reference frame 来初始化,这个 reference frame 就是 SLAM 正式开始的第一帧;用 current frame,也就是用 SLAM 逻辑上的第二帧来初始化整个 SLAM,得到最开始两帧之间的 R \boldsymbol{R} R t \boldsymbol{t} t,以及点云。

成员函数/变量访问控制意义
Initializer(...)public构造函数,用 reference frame 来初始化
bool Initialize(...)public用 current frame,得到最开始两帧之间的 R \boldsymbol{R} R t \boldsymbol{t} t,以及点云
vector<cv::KeyPoint> mvKeys1private存储 reference frame 中的特征点
vector<cv::KeyPoint> mvKeys2private存储 current frame 中的特征点
vector<Match> mvMatches12private记录 Reference 到 Current 匹配上的特征点对
vector<bool> mvbMatched1private记录 Reference Frame 的每个特征点在 Current Frame 是否有匹配的特征点
cv::Mat mKprivate相机内参
float mSigma, mSigma2private测量误差
int mMaxIterationsprivateRANSAC 迭代次数
vector<vector<size_t> > mvSetsprivate二维容器 N × 8 N\times8 N×8
每一层保存 RANSAC 计算 H 和 F 矩阵所需的八对点
得分大于0.4
得分小于0.4
Initialize
提取特征点
FindHomography
FindFundamental
ComputeH21:计算单应矩阵 H
CheckHomography: 根据H矩阵计算重投影误差,误差求和即得分
ComputeF21: 计算基础矩阵F
CheckFundamental:计算投影误差,累积求和即得分
根据得分比例,选择用单应矩阵H或基础矩阵F
ReconstructH
ReconstructF
分解H,得到四种解
CheckRT,按照预定条件,确定最优解
分解F,得到四种解
CheckRT,按照预定条件,确定最优解
确定最优解
若满足要求则初始化成功

6.2 初始化函数 Initialize()

主函数 Initialize() 根据两帧间的匹配关系恢复帧间运动并计算地图点位姿。

在这里插入图片描述

6.3 计算基础矩阵 F \boldsymbol{F} F 和单应矩阵 H \boldsymbol{H} H

6.3.1 RANSAC 算法

RANSAC 算法的核心是减少每次迭代所需的采样点数。从原理上来说,计算 F F F 矩阵最少只需要 7 对匹配点,计算 H H H 矩阵最少只需要 4 对匹配点。ORB-SLAM2 中为了编程方便,每次迭代使用 8 对匹配点计算 F F F H H H

6.3.2 八点法计算 F \boldsymbol{F} F 矩阵: ComputeF21()

在这里插入图片描述

对极约束

p 2 T F p 1 = 0 \boldsymbol{p}_2^T \boldsymbol{F} \boldsymbol{p}_1=0 p2TFp1=0

其中 p 1 、 p 2 \boldsymbol{p}_1、\boldsymbol{p}_2 p1p2 为对应特征点。

( u 2 , v 2 , 1 ) ( f 11 f 12 f 13 f 21 f 22 f 23 f 31 f 32 f 33 ) ( u 1 v 1 1 ) = 0 \left(u_2, v_2, 1\right)\left(\begin{array}{lll} \mathrm{f}_{11} & \mathrm{f}_{12} & \mathrm{f}_{13} \\ \mathrm{f}_{21} & \mathrm{f}_{22} & \mathrm{f}_{23} \\ \mathrm{f}_{31} & \mathrm{f}_{32} & \mathrm{f}_{33} \end{array}\right)\left(\begin{array}{c} \mathrm{u}_1 \\ \mathrm{v}_1 \\ 1 \end{array}\right)=0 (u2,v2,1) f11f21f31f12f22f32f13f23f33 u1v11 =0

为方便计算先展开前两项,并记为 a 、 b 、 c a、b、c abc

a = f 11 ∗ u 2 + f 21 ∗ v 2 + f 31 b = f 12 ∗ u 2 + f 22 ∗ v 2 + f 32 c = f 13 ∗ u 2 + f 23 ∗ v 2 + f 33 \begin{aligned} & a=f_{11} * u_2+f_{21} * v_2+f_{31} \\ & b=f_{12} * u_2+f_{22} * v_2+f_{32} \\ & c=f_{13} * u_2+f_{23} * v_2+f_{33} \end{aligned} a=f11u2+f21v2+f31b=f12u2+f22v2+f32c=f13u2+f23v2+f33

则上面的矩阵可记为

[ a b c ] [ u 1 v 1 1 ] = 0 \left[\begin{array}{lll} a & b & c \end{array}\right]\left[\begin{array}{c} u_1 \\ v_1 \\ 1 \end{array}\right]=0 [abc] u1v11 =0
展开

a ∗ u 1 + b ∗ v 1 + c = 0 a * u_1+b * v_1+c=0 au1+bv1+c=0

代入 a 、 b 、 c a、b、c abc

u 1 u 2 f 11 + u 1 v 2 f 21 + u 1 f 31 + v 1 u 2 f 12 + v 1 v 2 f 22 + v 1 f 32 + u 2 f 13 + v 2 f 23 + f 33 = 0 \mathrm{u}_1 \mathrm{u}_2 \mathrm{f}_{11}+\mathrm{u}_1 \mathrm{v}_2 \mathrm{f}_{21}+\mathrm{u}_1 \mathrm{f}_{31}+\mathrm{v}_1 \mathrm{u}_2 \mathrm{f}_{12}+\mathrm{v}_1 \mathrm{v}_2 \mathrm{f}_{22}+\mathrm{v}_1 \mathrm{f}_{32}+\mathrm{u}_2 \mathrm{f}_{13}+\mathrm{v}_2 \mathrm{f}_{23}+\mathrm{f}_{33}=0 u1u2f11+u1v2f21+u1f31+v1u2f12+v1v2f22+v1f32+u2f13+v2f23+f33=0

由于尺度不变性(可同时除 f 33 f_{33} f33),只有八个未知数,至少需要八对点

( u 1 1 u 2 1 u 1 1 v 2 1 u 1 1 v 1 1 u 2 1 v 1 1 v 2 1 v 1 1 u 2 1 v 2 1 1 u 1 2 u 2 2 u 1 2 v 2 2 u 1 2 v 1 2 u 2 2 v 1 2 v 2 2 v 1 2 u 2 2 v 2 2 1 ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ u 1 8 u 2 8 u 1 8 v 2 8 u 1 8 v 1 8 u 2 8 v 1 8 v 2 8 v 1 8 u 2 8 v 2 8 1 ) ( f 11 f 12 f 13 f 21 f 22 f 23 f 31 f 32 f 33 ) = 0 \left(\begin{array}{ccccccccc} \mathrm{u}_1^1 \mathrm{u}_2^1 & \mathrm{u}_1^1 \mathrm{v}_2^1 & \mathrm{u}_1^1 & \mathrm{v}_1^1 \mathrm{u}_2^1 & \mathrm{v}_1^1 \mathrm{v}_2^1 & \mathrm{v}_1^1 & \mathrm{u}_2^1 & \mathrm{v}_2^1 & 1 \\ \mathrm{u}_1^2 \mathrm{u}_2^2 & \mathrm{u}_1^2 \mathrm{v}_2^2 & \mathrm{u}_1^2 & \mathrm{v}_1^2 \mathrm{u}_2^2 & \mathrm{v}_1^2 \mathrm{v}_2^2 & \mathrm{v}_1^2 & \mathrm{u}_2^2 & \mathrm{v}_2^2 & 1 \\ \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots \\ \mathrm{u}_1^8 \mathrm{u}_2^8 & \mathrm{u}_1^8 \mathrm{v}_2^8 & \mathrm{u}_1^8 & \mathrm{v}_1^8 \mathrm{u}_2^8 & \mathrm{v}_1^8 \mathrm{v}_2^8 & \mathrm{v}_1^8 & \mathrm{u}_2^8 & \mathrm{v}_2^8 & 1 \end{array}\right)\left(\begin{array}{c} \mathrm{f}_{11} \\ \mathrm{f}_{12} \\ \mathrm{f}_{13} \\ \mathrm{f}_{21} \\ \mathrm{f}_{22} \\ \mathrm{f}_{23} \\ \mathrm{f}_{31} \\ \mathrm{f}_{32} \\ \mathrm{f}_{33} \end{array}\right)=0 u11u21u12u22u18u28u11v21u12v22u18v28u11u12u18v11u21v12u22v18u28v11v21v12v22v18v28v11v12v18u21u22u28v21v22v28111 f11f12f13f21f22f23f31f32f33 =0

使用 SVD 分解求出最小二乘解。

cv::Mat u,w,vt;cv::SVDecomp(A,w,u,vt,cv::SVD::MODIFY_A | cv::SVD::FULL_UV);cv::Mat Fpre = vt.row(8).reshape(0, 3); // v的最后一列cv::SVDecomp(Fpre,w,u,vt,cv::SVD::MODIFY_A | cv::SVD::FULL_UV);w.at<float>(2)=0; // 秩2约束,将第3个奇异值设为0return  u*cv::Mat::diag(w)*vt;
6.3.3 计算基础矩阵 F \boldsymbol{F} F 及其得分:FindFundamental()

此函数主要流程为:

  • 特征点归一化:Normalize()

  • 调用函数 ComputeF21() 计算基础矩阵,采用 RANSAC 算法,找到评分(卡方检验)最高的解:ComputeH21()CheckHomography()

在这里插入图片描述

6.3.4 计算 H \boldsymbol{H} H 矩阵: ComputeH21()

若场景中的特征点都落在同一平面(墙、地面),则可以用单应矩阵进行运动估计。

在这里插入图片描述

p 2 = H p 1 \boldsymbol{p}_2=\boldsymbol{H} \boldsymbol{p}_1 p2=Hp1

p 1 、 p 2 \boldsymbol{p}_1、\boldsymbol{p}_2 p1p2 为对应特征点。

一般来说,4 对点即可求解

( u 1 1 v 1 1 1 0 0 0 − u 1 1 u 2 1 − v 1 1 u 2 1 0 0 0 u 1 1 v 1 1 1 − u 1 1 v 2 1 − v 1 1 v 2 1 u 1 2 v 1 2 1 0 0 0 − u 1 2 u 2 2 − v 1 2 u 2 2 0 0 0 u 1 2 v 1 2 1 − u 1 2 v 2 2 − v 1 2 v 2 2 u 1 3 v 1 3 1 0 0 0 − u 1 3 u 2 3 − v 1 3 u 2 3 0 0 0 u 1 3 v 1 3 1 − u 1 3 v 2 3 − v 1 3 v 2 3 u 1 4 v 1 4 1 0 0 0 − u 1 4 u 2 4 − v 1 4 u 2 4 0 0 0 u 1 4 v 1 4 1 − u 1 4 v 2 4 − v 1 4 v 2 4 ) ( h 1 h 2 h 3 h 4 h 5 h 6 h 7 h 8 ) = ( u 2 1 v 2 1 u 2 2 v 2 2 u 2 3 v 2 3 u 2 4 v 2 4 ) . \left(\begin{array}{cccccccc} u_1^1 & v_1^1 & 1 & 0 & 0 & 0 & -u_1^1 u_2^1 & -v_1^1 u_2^1 \\ 0 & 0 & 0 & u_1^1 & v_1^1 & 1 & -u_1^1 v_2^1 & -v_1^1 v_2^1 \\ u_1^2 & v_1^2 & 1 & 0 & 0 & 0 & -u_1^2 u_2^2 & -v_1^2 u_2^2 \\ 0 & 0 & 0 & u_1^2 & v_1^2 & 1 & -u_1^2 v_2^2 & -v_1^2 v_2^2 \\ u_1^3 & v_1^3 & 1 & 0 & 0 & 0 & -u_1^3 u_2^3 & -v_1^3 u_2^3 \\ 0 & 0 & 0 & u_1^3 & v_1^3 & 1 & -u_1^3 v_2^3 & -v_1^3 v_2^3 \\ u_1^4 & v_1^4 & 1 & 0 & 0 & 0 & -u_1^4 u_2^4 & -v_1^4 u_2^4 \\ 0 & 0 & 0 & u_1^4 & v_1^4 & 1 & -u_1^4 v_2^4 & -v_1^4 v_2^4 \end{array}\right)\left(\begin{array}{c} h_1 \\ h_2 \\ h_3 \\ h_4 \\ h_5 \\ h_6 \\ h_7 \\ h_8 \end{array}\right)=\left(\begin{array}{c} u_2^1 \\ v_2^1 \\ u_2^2 \\ v_2^2 \\ u_2^3 \\ v_2^3 \\ u_2^4 \\ v_2^4 \end{array}\right) . u110u120u130u140v110v120v130v140101010100u110u120u130u140v110v120v130v1401010101u11u21u11v21u12u22u12v22u13u23u13v23u14u24u14v24v11u21v11v21v12u22v12v22v13u23v13v23v14u24v14v24 h1h2h3h4h5h6h7h8 = u21v21u22v22u23v23u24v24 .

这里为了和 ComputeH21() 一致,也采用八点法。通过 SVD 分解求出 H \boldsymbol{H} H 矩阵。

6.3.5 计算单应矩阵 H \boldsymbol{H} H 及其得分 FindHomography()

过程类似 FindFundamental()

在这里插入图片描述

6.3.6 卡方检验计算置信度得分: CheckFundamental()、CheckHomography()

卡方检验通过构造检验统计量 χ \chi χ 来比较期望结果和实际结果之间的差别,从而得出观察频数极值的发生概率。

χ 2 = Σ ( O − E ) 2 E \chi^2=\Sigma \frac{(\mathrm{O}-\mathrm{E})^2}{\mathrm{E}} χ2=ΣE(OE)2

(1)CheckHomography()

计算重投影误差,也就是计算投影点与对应匹配点的像素距离的平方(计算值与真实值),作为卡方值。

有前面

p 2 = H p 1 \boldsymbol{p}_2=\boldsymbol{H} \boldsymbol{p}_1 p2=Hp1

将帧 1 特征点左乘单应矩阵,得到帧 2 中对应特征点的计算值。反之,则为 p 1 = H − 1 p 2 \boldsymbol{p}_1=\boldsymbol{H}^{-1} \boldsymbol{p}_2 p1=H1p2

// Reprojection error in second image
// x1in2 = H21*x1
// 将图像1中的特征点单应到图像2中
// |u1|   |h11 h12 h13||u2|
// |v1| = |h21 h22 h23||v2|
// |1 |   |h31 h32 h33||1 |
const float w1in2inv = 1.0/(h31*u1+h32*v1+h33);  
const float u1in2 = (h11*u1+h12*v1+h13)*w1in2inv;
const float v1in2 = (h21*u1+h22*v1+h23)*w1in2inv;const float squareDist2 = (u2-u1in2)*(u2-u1in2)+(v2-v1in2)*(v2-v1in2);  // 计算平方误差const float chiSquare2 = squareDist2*invSigmaSquare;  // 卡方if(chiSquare2>th)bIn = false;
elsescore += th - chiSquare2;   // 得分if(bIn)vbMatchesInliers[i]=true;
elsevbMatchesInliers[i]=false;    // 大于阈值,则为外点,置为 false

(2)CheckFundamental()

对于函数 CheckFundamental():理想情况下,有 p 2 T F p 1 = 0 \boldsymbol{p}_2^T \boldsymbol{F} \boldsymbol{p}_1=0 p2TFp1=0,但由于误差存在,左式并不会恒等于零,于是,我们将它的值作为误差。

// Reprojection error in second image
//                        |f11 f12 f13|
// |a1 b1 c1| = |u2 v2 1| |f21 f22 f23|
//                        |f31 f32 f33|const float a1 = f11*u2+f21*v2+f31;     // 先展开前两项
const float b1 = f12*u2+f22*v2+f32;
const float c1 = f13*u2+f23*v2+f33;//          |v1|
//|a1 b1 c1||u1|=0?            // 由于误差存在,并不为零,将其作为误差值
//          |1 |
const float num1 = a1*u1+b1*v1+c1;const float squareDist2 = num1*num1/(a1*a1+b1*b1);  // 平方误差const float chiSquare2 = squareDist2*invSigmaSquare;if(chiSquare2>th)bIn = false;
elsescore += thScore - chiSquare2;if(bIn)vbMatchesInliers[i]=true;
elsevbMatchesInliers[i]=false;
6.3.7 归一化:Normalize()

用均值和一阶距绝对值将关键点归一化,归一化可以使特征点分布均匀,增强计算稳定性。

均值

u ˉ = ( ∑ i = 1 N u i ) / N \bar{u}=(\sum^N_{i=1}u_i)/N uˉ=(i=1Nui)/N
一阶距绝对值

∣ u ˉ ∣ = ∑ i = 0 N ∣ u i − u ˉ ∣ / N |\bar{u}|=\sum_{i=0}^N\left|u_i-\bar{u}\right| / N uˉ=i=0Nuiuˉ/N

归一化坐标

u i ′ = u i − u ˉ ∣ u ˉ ∣ u^{\prime}_i=\frac{u_i-\bar{u}}{|\bar{u}|} ui=uˉuiuˉ

s X = 1 ∣ u ˉ x ∣ sX=\frac{1}{|\bar{u}_x|} sX=uˉx1 s Y = 1 ∣ u ˉ y ∣ sY=\frac{1}{|\bar{u}_y|} sY=uˉy1,那么变换到归一化坐标的变换矩阵为

[ x ′ y ′ 1 ] = [ s X 0 − mean  X ∗ s X 0 s Y − mean  Y ∗ s Y 0 0 1 ] [ x y 1 ] \left[\begin{array}{c} x^{\prime} \\ y^{\prime} \\ 1 \end{array}\right]=\left[\begin{array}{ccc} s X & 0 & - \text { mean } X * s X \\ 0 & s Y & - \text { mean } Y * s Y \\ 0 & 0 & 1 \end{array}\right]\left[\begin{array}{l} x \\ y \\ 1 \end{array}\right] xy1 = sX000sY0 mean XsX mean YsY1 xy1

代码

/** @param vKeys             特征点在图像上的坐标* @param vNormalizedPoints 特征点归一化后的坐标* @param T                 将特征点归一化的矩阵*/
void Initializer::Normalize(const vector<cv::KeyPoint> &vKeys, vector<cv::Point2f> &vNormalizedPoints, cv::Mat &T)
{float meanX = 0;float meanY = 0;const int N = vKeys.size();vNormalizedPoints.resize(N);for(int i=0; i<N; i++){meanX += vKeys[i].pt.x;meanY += vKeys[i].pt.y;}meanX = meanX/N;meanY = meanY/N;    // 均值float meanDevX = 0;float meanDevY = 0;// 将所有vKeys点减去中心坐标,使x坐标和y坐标均值分别为0for(int i=0; i<N; i++){vNormalizedPoints[i].x = vKeys[i].pt.x - meanX;vNormalizedPoints[i].y = vKeys[i].pt.y - meanY;meanDevX += fabs(vNormalizedPoints[i].x);meanDevY += fabs(vNormalizedPoints[i].y);}meanDevX = meanDevX/N;meanDevY = meanDevY/N;  // 一阶距绝对值float sX = 1.0/meanDevX;float sY = 1.0/meanDevY;// 将x坐标和y坐标分别进行尺度缩放,使得x坐标和y坐标的一阶绝对矩分别为1for(int i=0; i<N; i++)   // 得到归一化坐标{vNormalizedPoints[i].x = vNormalizedPoints[i].x * sX;vNormalizedPoints[i].y = vNormalizedPoints[i].y * sY;}    // 得到归一化坐标的变换矩阵// |sX  0  -meanx*sX|// |0   sY -meany*sY|// |0   0      1    |T = cv::Mat::eye(3,3,CV_32F);T.at<float>(0,0) = sX;T.at<float>(1,1) = sY;T.at<float>(0,2) = -meanX*sX;T.at<float>(1,2) = -meanY*sY;
}
6.3.8 检验 F \boldsymbol{F} F H \boldsymbol{H} H 分解结果 :CheckRT()

使用基础矩阵 F \boldsymbol{F} F 分解 R \boldsymbol{R} R t \boldsymbol{t} t,数学上会得到四个可能的解,因此分解后调用函数 Initializer::CheckRT() 检验分解结果,取相机前方成功三角化数目最多的一组解。

在这里插入图片描述

显然只有在第一种解中,点 P \boldsymbol{P} P 在两个相机中均有正深度。

同样地,单应矩阵也需要检验,从而得出符合条件的 R , t \boldsymbol{R,t} Rt

步骤:
① 遍历各匹配点对,调用三角化函数恢复三维点坐标
② 三维点坐标各值都必须为有限实数;
③ 深度值必须为正;
④ 三维点和两帧图像光心夹角需满足一定条件,夹角越大,视差越大,误差越小,三角化结果越准确;
⑤ 三维点的重投影误差需小于设定阈值。

将每种情况下满足要求的三维点的数目记录下来,进一步进行比较,得出最优解:
① 最优解成功三角化的数目明显优于次优解的点数目;
② 最优解的视差大于设定点阈值;
③ 最优解成功三角化的点数目大于设定阈值;
④ 最优解成功三角化点数目占所有特征点数目的 90% 以上。

6.4 三角化

三角测量恢复深度,进而求出三维点坐标。

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

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

相关文章

怎么使用cmd命令来进行Vue脚手架的项目搭建

前言 使用vue搭建项目的时候&#xff0c;我们可以通过对应的cmd命令去打开脚手架&#xff0c;然后自己配置对应的功能插件 怎么打开 我们打开对应的cmd命令之后就开始进入对应的网站搭建 vue ui 然后我们就打开对应的项目管理器来进行配置----这里我们打开开始创建新的项目…

【VS Code+Verilog+Vivado使用】(2)基本设置

文章目录 2 基本设置2.1 字体大小2.2 Tab大小2.3 选中高亮2.4 文件编码 2 基本设置 2.1 字体大小 方法1&#xff1a;VS Code左下角 > 管理 > 设置&#xff0c;搜索"font size"&#xff0c;点击左侧"字体"&#xff0c;根据需要设置"editor.fon…

穷游网酒店数据采集与可视化分析与实现

摘 要 穷游网酒店数据采集与可视化分析大屏的背景是为了满足用户对酒店数据的需求以及提供数据洞察和决策支持。随着旅游业的快速发展&#xff0c;人们对酒店信息的需求日益增加&#xff0c;而穷游网作为一家专注于旅游信息的网站&#xff0c;拥有丰富的酒店数据资源。 这个大…

回归预测 | Matlab实现CPO-SVR冠豪猪优化支持向量机的数据多输入单输出回归预测

回归预测 | Matlab实现CPO-SVR冠豪猪优化支持向量机的数据多输入单输出回归预测 目录 回归预测 | Matlab实现CPO-SVR冠豪猪优化支持向量机的数据多输入单输出回归预测预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab实现CPO-SVR冠豪猪优化支持向量机的数据多输入…

Flink实战四_TableAPISQL

接上文&#xff1a;Flink实战三_时间语义 1、Table API和SQL是什么&#xff1f; 接下来理解下Flink的整个客户端API体系&#xff0c;Flink为流式/批量处理应用程序提供了不同级别的抽象&#xff1a; 这四层API是一个依次向上支撑的关系。 Flink API 最底层的抽象就是有状态实…

腾讯mini项目总结-指标监控服务重构

项目概述 本项目的背景是&#xff0c;当前企业内部使用的指标监控服务的方案的成本很高&#xff0c;无法符合用户的需求&#xff0c;于是需要调研并对比测试市面上比较热门的几款开源的监控方案&#xff08;选择了通用的OpenTelemetry协议&#xff1a;Signoz&#xff0c;otel-…

JVM学习

1.Java虚拟机内部有哪些线程共享&#xff0c;那些线程隔离 程序计数器&#xff1a; 通过改变这个计数器的值来选取下一条需要执行的字节码命令 Java虚拟机栈&#xff1a; 栈&#xff0c;每个方法被执行时&#xff0c;Java虚拟机都会同步的创建一个栈帧用于存储局部变量表&…

java 实现微信公众号关键字自动回复

接上一篇内容https://blog.csdn.net/YISHENGYOUNI95/article/details/134383219 因为设置了公众号的服务器配置&#xff0c;导致之前设置的公众号自动回复失效了 需要通过之前配置的接口实现自动回复 参考一下官方文档回复文本消息 | 微信开放文档 根据用户发送的消息&#…

中国的茶文化:历史、传统与生活

中国的茶文化&#xff1a;历史、传统与生活 一、引言 茶&#xff0c;这一神奇而古老的饮品&#xff0c;与中国的历史、文化和生活方式紧密相连。中国的茶文化&#xff0c;源远流长&#xff0c;博大精深&#xff0c;是中华文明的重要组成部分。它不仅是一种饮料&#xff0c;更是…

Jedis连接池究竟是何物?

一、前言 连接池的用途实际上有过开发经验的朋友都已经比较清楚了&#xff0c;当资源对象的创建/销毁比较耗时的场景下&#xff0c;可以通过"池化"技术&#xff0c;达到资源的复用&#xff0c;以此来减少系统的开销、增大系统吞吐量&#xff0c;比如数据库连接池、线…

雍禾植发:“地球生发计划”修复荒漠化土地超百万平方米

日前&#xff0c;雍禾植发宣布“毛发森林•地球生发计划”从正式发起到2023年11月19日秋季造林结束&#xff0c;已经在内蒙古自治区额济纳旗东风镇额很查干嘎查种下60000棵树&#xff0c;修复荒漠化土地超过102.01万平方米。 作为此次公益活动的“落脚地”,额济纳旗地处内蒙古…

Swift Vapor 教程(项目创建)

The future of web development. 在初次接触 Swift Vapor 时&#xff0c;感觉代码比较清爽&#xff0c;用起来逻辑比较清晰。 困难点&#xff1a; Swift Vapor 使用了JWT管理三方库&#xff0c;比较吃网络Swift Vapor 搭建环境比较复杂初次使用Swift Vapor 尽量不要使用MySql。…

Linux内存常用命令指标详解

1. free rootnode02:~# free -m total used free shared buff/cache available Mem: 3919 1194 1738 1 986 2446 Swap: 0 0 0free 输出的是一个表格&#xff0c;其中…

网页版idea、pycharm搭建

官网教程提供了两种方法&#xff1a;1、有给应用版idea或pycharm安装插件来开放网页服务&#xff1b;2、使用docker创建容器开放网页服务。这边推荐并介绍第二种步骤。 基本过程为&#xff1a;拉取相关镜像&#xff1b;开启服务&#xff1b;使用网页版 &#xff08;细节和注意点…

3D数据转换器HOOPS Exchange如何获取模型的几何数据? 干货预警!

一、概述 前面讲解过模型在内存中的结构&#xff0c;现在回顾一下&#xff0c;当模型导入成功后&#xff0c;整个模型数据会以原生结构的 PRC 组装树形式存放到内存中。&#xff08;申请 HOOPS Exchange 试用&#xff09; PRC结构的主要类型包含四种&#xff0c;分别是…

Qt 调用系统键盘

Wow64DisableWow64FsRedirection(&pvoid) 函数用于禁用 32 位 Windows 程序对文件系统重定向的支持。它将禁用文件系统重定向&#xff0c;以便在运行 32 位应用程序时&#xff0c;可以访问 64 位系统目录。pvoid 是一个指向先前启用的文件系统重定向状态的指针。 构建了要…

(2)(2.10) LTM telemetry

文章目录 前言 1 协议概述 2 配置 3 带FPV视频发射器的使用示例 4 使用TCM3105的FSK调制解调器示例 前言 轻量级 TeleMetry 协议 (LTM) 是一种单向通信协议&#xff08;从飞行器下行的数据链路&#xff09;&#xff0c;可让你以低带宽/低波特率&#xff08;通常为 2400 波…

ElasticSearch 应用实践 笔记

概述 介绍 ES 是一个开源的高扩展的分布式全文搜索引擎&#xff0c;是整个Elastic Stack技术栈的核心。它可以近乎实时的存储&#xff0c;检索数据&#xff1b;本身扩展性很好&#xff0c;可以扩展到上百台服务器&#xff0c;处理PB级别的数据。ElasticSearch的底层是开源库Lu…

【Golang】ModbusRTU协议CRC16校验算法

CRC校验码是通过在数据后面附加一个短的校验序列来生成的&#xff0c;用于检测数据在传输过程中是否发生错误。CRC16是一种特定的CRC校验算法&#xff0c;它生成一个16位的校验码。 下面是使用Go语言实现CRC16校验算法的代码&#xff1a; package main import ("encoding…

npm安装下载修改镜像源

问题描述一 npm install 时&#xff0c;报错&#xff1a;npm ERR! network request to https://registry.npmjs.org/postcss-pxtorem failed, reason: connect ETIMEDOU&#xff0c;这是因为默认npm安装会请求国外的镜像源&#xff0c;导致下载缓慢容易断开请求下载失败的 np…