SLAM ORB-SLAM2(21)基础矩阵的计算和评分

SLAM ORB-SLAM2(21)基础矩阵的计算和评分

  • 1. 前言
  • 2. 基础矩阵
    • 2.1. 对级约束
    • 2.2. 推导
    • 2.3. 计算原理
  • 3. ComputeF21
  • 4. CheckFundamental


1. 前言

在 《SLAM ORB-SLAM2(20)查找基础矩阵》 中了解到 查找基础矩阵主要过程:

  1. 特征点坐标归一化 Normalize

函数 Normalize 参考 《SLAM ORB-SLAM2(14)特征点坐标归一化》

  1. 选择归一化之后的特征点
  2. 八点法计算基础矩阵 ComputeF21
  3. 评分并评优 CheckFundamental

现在来看看基础矩阵如何计算和评分


2. 基础矩阵


2.1. 对级约束

不过先来了解一下什么是对级约束
在这里插入图片描述拿着相机分别在点 O 1 O_1 O1 O 2 O_2 O2 观测空间中一点 P P P
该点在两个视图平面上分别被投影到了点 p 1 p_1 p1 p 2 p_2 p2

由于两次测量都是对同一个点 P P P 的观测
所以 O 1 p 1 O_1p_1 O1p1 O 2 p 2 O_2p_2 O2p2的延长线相交与点 P P P
即点 P , O 1 , O 2 , p 1 , p 2 P,O_1,O_2,p_1,p_2 P,O1,O2,p1,p2 都在一个平面上,这个平面被称为 极面 (epipolar plane)
连线 O 1 O 2 O_1O_2 O1O2 被称为 基线 (baseline)
基线分别与两个像平面相交与点 e 1 , e 2 e_1,e_2 e1,e2 ,这两个点被称为 极点 (epipole)
极点与成像点 p 1 , p 2 p_1,p_2 p1,p2 的连线 p 1 e 1 , p 2 e 2 p_1e_1,p_2e_2 p1e1,p2e2 所在的直线 l 1 , l 2 l_1,l_2 l1,l2 被称为 极线 (epipolar line)

对级约束就是,在两个不同的位置上观测空间中同一个点,其成像一定在极线上


2.2. 推导

假设某个特征点 P P P
相对于参考帧相机坐标系的坐标为 X 1 = [ x 1 y 1 z 1 ] T \boldsymbol{X_1} = \begin{bmatrix} x_1 & y_1 & z_1 \end{bmatrix}^T X1=[x1y1z1]T

成像点的齐次坐标为 x 1 = [ u 1 v 1 1 ] T \boldsymbol{x_1} = \begin{bmatrix} u_1 & v_1 & 1\end{bmatrix}^T x1=[u1v11]T

根据针孔相机模型:
x 1 = 1 z K X 1 ⟺ [ u 1 v 1 1 ] = 1 z [ f x 0 c x 0 f y c y 0 0 1 ] [ x 1 y 1 z 1 ] \boldsymbol{x_1} = \cfrac{1}{z} \boldsymbol{KX_1} \Longleftrightarrow \begin{bmatrix} u_1 \\ v_1 \\ 1 \end{bmatrix} = \cfrac{1}{z} \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_1 \\ y_1 \\ z_1 \end{bmatrix} x1=z1KX1u1v11=z1fx000fy0cxcy1x1y1z1 矩阵 K K K 为相机的内参矩阵,记录了相机的 x y x\ y x y 轴上的焦距 f x , f y f_x, f_y fx,fy 和 光心坐标 c x , c y c_x,c_y cx,cy

此时,考虑相机的内参,将 X 1 , X 2 X_1,X_2 X1,X2投影到成像平面上有:
{ x 1 = 1 z 1 K X 1 x 2 = 1 z 2 K X 2 ⇒ { X 1 = z 1 K − 1 x 1 X 2 = z 2 K − 1 x 2 \begin{cases} \boldsymbol{x_1} = \cfrac{1}{z_1} \boldsymbol{K} \boldsymbol{X_1} \\ \boldsymbol{x_2} = \cfrac{1}{z_2} \boldsymbol{K} \boldsymbol{X_2} \end{cases} \Rightarrow \begin{cases} \boldsymbol{X_1} = z_1\boldsymbol{K}^{-1} \boldsymbol{x_1} \\ \boldsymbol{X_2} = z_2\boldsymbol{K}^{-1} \boldsymbol{x_2} \end{cases} x1=z11KX1x2=z21KX2{X1=z1K1x1X2=z2K1x2
相机经过位姿变换 ⟨ R , t ⟩ ⟨R,t⟩ R,t后,观测到 P P P 点坐标为,上式导入运动关系:
X 2 = R X 1 + t ⇒ z 2 K − 1 x 2 = z 1 R K − 1 x 1 + t \boldsymbol{X_2} = \boldsymbol{RX_1} + \boldsymbol{t} \ \ \ \ \ \Rightarrow \ \ \ z_2 \boldsymbol{K}^{-1} \boldsymbol{x_2} = z_1 \boldsymbol{R}\boldsymbol{K}^{-1}\boldsymbol{x_1} + \boldsymbol{t}\\ X2=RX1+t        z2K1x2=z1RK1x1+t
两边叉乘 t t t
z 2 t × K − 1 x 2 = z 1 t × R K − 1 x 1 z_2 \boldsymbol{t}_{\times}\boldsymbol{K}^{-1}\boldsymbol{x_2} = z_1 \boldsymbol{t}{\times}\boldsymbol{R}\boldsymbol{K}^{-1}\boldsymbol{x_1} z2t×K1x2=z1t×RK1x1

叉乘(外积): A X B = |A| |B| s i n θ sin\theta sinθ, 向量形成的平行四边形的面积,也是法向量

t = [ a 1 a 2 a 3 ] ⇒ t ∧ = [ 0 − a 3 a 2 a 3 0 − a 1 − a 2 a 1 0 ] t=\left[\begin{array}{l}a_{1} \\ a_{2} \\ a_{3}\end{array}\right] \Rightarrow \ t^{\wedge}=\left[\begin{array}{ccc}0 & -a_{3} & a_{2} \\ a_{3} & 0 & -a_{1} \\ -a_{2} & a_{1} & 0\end{array}\right] t=a1a2a3 t=0a3a2a30a1a2a10

反对称矩阵,它的主对角线上的元素全为0,而位于主对角线两侧对称的元素反号

A X B = [ 0 − z a y a z a 0 − x a − y a x a 0 ] \begin{bmatrix}0 & -z_a & y_a \\z_a &0 & -x_a \\-y_a & x_a & 0 \end{bmatrix} 0zayaza0xayaxa0 [ x b y b z b ] \begin{bmatrix}x_b \\y_b \\z_b \end{bmatrix} xbybzb= [ y a z b − y b z a x b z a − x a z b x a y b − x b y a ] \begin{bmatrix}y_az_b-y_bz_a \\x_bz_a-x_az_b \\x_ay_b-x_by_a \end{bmatrix} yazbybzaxbzaxazbxaybxbya

那么两个平行的向量叉乘为0

两边点乘 ( K − 1 x 2 ) T \left(\boldsymbol{K}^{-1}\boldsymbol{x_2}\right)^T (K1x2)T
z 2 ( K − 1 x 2 ) T t × K − 1 x 2 = z 1 ( K − 1 x 2 ) T t × R K − 1 x 1 z_2 \left(\boldsymbol{K}^{-1}\boldsymbol{x_2}\right)^T\boldsymbol{t}{\times}\boldsymbol{K}^{-1}\boldsymbol{x_2} = z_1 \left(\boldsymbol{K}^{-1}\boldsymbol{x_2}\right)^T\boldsymbol{t}{\times}\boldsymbol{R}\boldsymbol{K}^{-1}\boldsymbol{x_1} z2(K1x2)Tt×K1x2=z1(K1x2)Tt×RK1x1
关注式子的左侧的左边, t × K − 1 x 2 \boldsymbol{t}_{\times}\boldsymbol{K}^{-1}\boldsymbol{x_2} t×K1x2的含义就是向量 t t t K − 1 x 2 \boldsymbol{K}^{-1}\boldsymbol{x_2} K1x2 的叉乘
将得到一个同时与这两个向量垂直的向量,该向量与 K − 1 x 2 \boldsymbol{K}^{-1}\boldsymbol{x_2} K1x2 的点积为零
所以上式可以写成如下的形式:
z 1 ( K − 1 x 2 ) T t × R K − 1 x 1 = 0 z_1 \left(\boldsymbol{K}^{-1}\boldsymbol{x_2}\right)^T\boldsymbol{t}{\times}\boldsymbol{R}\boldsymbol{K}^{-1}\boldsymbol{x_1}=0 z1(K1x2)Tt×RK1x1=0

上式就是一个等式为零的约束,所以其中 z z z的取值实际上没有什么作用,只要非零就行,那么
x 2 T K − T t × R K − 1 x 1 = 0 \boldsymbol{x_2}^T\boldsymbol{K}^{-T}\boldsymbol{t}{\times}\boldsymbol{R}\boldsymbol{K}^{-1}\boldsymbol{x_1}=0 x2TKTt×RK1x1=0

把矩阵 K − T t × R K − 1 \boldsymbol{K}^{-T}\boldsymbol{t}_{\times}\boldsymbol{R}\boldsymbol{K}^{-1} KTt×RK1 称为 基础矩阵,用符号 F \boldsymbol{F} F 表示,那么得到映射关系:
x 2 T F x = 0 \boldsymbol{x_2}^T \boldsymbol{Fx} = 0 x2TFx=0


2.3. 计算原理

根据两帧图像之间的映射关系: x 2 T F x = 0 \boldsymbol{x_2}^T \boldsymbol{Fx} = 0 x2TFx=0
代入求解:
[ 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 ⇒ u 2 u 1 f 11 + u 2 v 1 f 12 + u 2 f 13 + v 2 u 1 f 21 + v 2 v 1 f 22 + v 2 f 23 + u 1 f 31 + v 1 f 32 + f 33 = 0 \begin{bmatrix} u_2 & v_2 & 1 \end{bmatrix} \begin{bmatrix} f_{11} & f_{12} & f_{13} \\ f_{21} & f_{22} & f_{23} \\ f_{31} & f_{32} & f_{33} \end{bmatrix} \begin{bmatrix} u_1 \\ v_1 \\ 1 \end{bmatrix} = 0 \ \ \ \ \ \Rightarrow \\ \ \\ u_2u_1f_{11} + u_2v_1f_{12} + u_2f_{13} + v_2u_1f_{21} + v_2v_1f_{22} + v_2f_{23} + u_1f_{31} + v_1f_{32} + f_{33} = 0 [u2v21]f11f21f31f12f22f32f13f23f33u1v11=0      u2u1f11+u2v1f12+u2f13+v2u1f21+v2v1f22+v2f23+u1f31+v1f32+f33=0

f = [ f 11 f 12 f 13 f 21 f 22 f 23 f 31 f 32 f 33 ] T \boldsymbol{f} = \begin{bmatrix} f_{11} & f_{12} & f_{13} & f_{21} & f_{22} & f_{23} & f_{31} & f_{32} & f_{33} \end{bmatrix}^T f=[f11f12f13f21f22f23f31f32f33]T ,上式可以写成向量点乘的形式:
[ u 2 u 1 u 2 v 1 u 2 v 2 u 1 v 2 v 1 v 2 u 1 v 1 1 ] f = 0 \begin{bmatrix} u_2u_1 & u_2v_1 & u_2 & v_2u_1 & v_2v_1 & v_2 & u_1 & v_1 & 1 \end{bmatrix} \boldsymbol{f} = 0 [u2u1u2v1u2v2u1v2v1v2u1v11]f=0

假有 m m m 对匹配点,根据上式可以写出 m m m 个约束,可以写成 A f = 0 \boldsymbol{Af}=\boldsymbol{0} Af=0 的矩阵形式,如下:
A f = [ u 1 , 2 u 1 , 1 u 1 , 2 v 1 , 1 u 1 , 2 v 1 , 2 u 1 , 1 v 1 , 2 v 1 , 1 v 1 , 2 u 1 , 1 v 1 , 1 1 ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ u m , 2 u m , 1 u m , 2 v m , 1 u m , 2 v m , 2 u m , 1 v m , 2 v m , 1 v m , 2 u m , 1 v m , 1 1 ] f = 0 \boldsymbol{Af} = \begin{bmatrix} u_{1,2}u_{1,1} & u_{1,2}v_{1,1} & u_{1,2} & v_{1,2}u_{1,1} & v_{1,2}v_{1,1} & v_{1,2} & u_{1,1} & v_{1,1} & 1 \\ \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \\ u_{m,2}u_{m,1} & u_{m,2}v_{m,1} & u_{m,2} & v_{m,2}u_{m,1} & v_{m,2}v_{m,1} & v_{m,2} & u_{m,1} & v_{m,1} & 1 \\ \end{bmatrix} \boldsymbol{f} = \boldsymbol{0} Af=u1,2u1,1um,2um,1u1,2v1,1um,2vm,1u1,2um,2v1,2u1,1vm,2um,1v1,2v1,1vm,2vm,1v1,2vm,2u1,1um,1v1,1vm,111f=0
对矩阵 A A A 进行奇异值分解,得到的 右奇异矩阵的最后一列 就是 f \boldsymbol{f} f最优解
能够最小化 ∥ A f ∥ / ∥ f ∥ \boldsymbol{∥Af∥/∥f∥} Af/f的解,使 A f \boldsymbol{Af} Af 尽可能的接近 0

为何右奇异矩阵的最后一列为单应矩阵的最优解 参考 《SLAM ORB-SLAM2(16)奇异值分解》 的 求解超定方程

至少需要8个点才能求得基础矩阵,这也就是所谓的八点法


3. ComputeF21

直接线性法 DLT 方法求解 基础矩阵 F F F

按上述公式填充数据于系数矩阵 A A A

/*** @brief 基础矩阵计算求解函数* @param vP1  参考帧归一化坐标* @param vP2  当前帧归一化坐标* @return cv::Mat 计算的基础矩阵F*/
cv::Mat Initializer::ComputeF21(const vector<cv::Point2f> &vP1, const vector<cv::Point2f> &vP2)
{/* 获取坐标数量 */const int N = vP1.size();/* 定义系数矩阵A */cv::Mat A(N, 9, CV_32F);/* 配置系数 */for (int i = 0; i < N; i++){/* 获取特征点对的像素坐标 */const float u1 = vP1[i].x;const float v1 = vP1[i].y;const float u2 = vP2[i].x;const float v2 = vP2[i].y;/* 配置当前特征点对应的约束 */A.at<float>(i, 0) = u2 * u1;A.at<float>(i, 1) = u2 * v1;A.at<float>(i, 2) = u2;A.at<float>(i, 3) = v2 * u1;A.at<float>(i, 4) = v2 * v1;A.at<float>(i, 5) = v2;A.at<float>(i, 6) = u1;A.at<float>(i, 7) = v1;A.at<float>(i, 8) = 1;}/* 定义输出变量,u是左边的正交矩阵U, w为奇异矩阵,vt为右正交矩阵V的转置T */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);/* 对初步得来的基础矩阵进行第2次奇异值分解 */cv::SVDecomp(Fpre, w, u, vt, cv::SVD::MODIFY_A | cv::SVD::FULL_UV);/* 基础矩阵的秩为2,强制将第3个奇异值设置为0 */w.at<float>(2) = 0;/* 返回重组满足秩约束的基础矩阵 */return u * cv::Mat::diag(w) * vt;
}

通过OpenCV的接口对矩阵 A A A 进行 SVD分解,取最小的奇异值在 V T V^T VT空间中对应的行向量构建基础矩阵
但是基础矩阵的秩只有2,也就是它应当有一个为0的奇异值
对矩阵 A A A 进行 SVD分解 时并不能保证这一点
所以构建矩阵 Fpre 再次进行 SVD分解,令最小的奇异值为 0,再重组基础矩阵

:矩阵 A A A非零特征值个数
奇异值分解 参考 《SLAM ORB-SLAM2(16)奇异值分解》


4. CheckFundamental

经过计算,得到基础矩阵,那么根据基础矩阵计算重投影误差

这里返回的单应矩阵是归一化之后的,还不能直接使用, 需要恢复归一化之前的矩阵才行
在 《SLAM ORB-SLAM2(20)查找基础矩阵》 的 5. 八点法计算基础矩阵 中已经恢复了:

cv::Mat Fn = ComputeF21(vPn1i, vPn2i); /* 八点法计算基础矩阵 */
F21i = T2t * Fn * T1;                  /* 根据归一化的矩阵恢复 基础矩阵 F21 */

在第一步已经进行特征点归一化:vPn1 = T1 * mvKeys1, vPn2 = T2 * mvKeys2

又因为 x x x2T F F F21 x x x1=0
根据基础矩阵约束得到:(T2 * mvKeys2)T * Fn * T1 * mvKeys1 = 0
进一步得到 : mvKeys2T * T2t * Fn * T1 * mvKeys1 = 0

/*** @brief 基础矩阵评分函数* @param F21  参考帧到当前帧的基础矩阵* @param vbMatchesInliers  特征点对的Inlier标记* @param sigma  标准差* @return score 得分*/
float Initializer::CheckFundamental(const cv::Mat &F21, vector<bool> &vbMatchesInliers, float sigma)
{/* 获取匹配点对数量 */const int N = mvMatches12.size();/* 获取从参考帧到当前帧的基础矩阵的各个元素 */const float f11 = F21.at<float>(0, 0);const float f12 = F21.at<float>(0, 1);const float f13 = F21.at<float>(0, 2);const float f21 = F21.at<float>(1, 0);const float f22 = F21.at<float>(1, 1);const float f23 = F21.at<float>(1, 2);const float f31 = F21.at<float>(2, 0);const float f32 = F21.at<float>(2, 1);const float f33 = F21.at<float>(2, 2);

获取从参考帧到当前帧的基础矩阵中的各个元素

    /* 预分配特征点对Inliers标记的空间 */vbMatchesInliers.resize(N);/* 初始化单应矩阵得分 */float score = 0;/* 基于卡方检验计算出的阈值(假设测量有一个像素的偏差)自由度为1的卡方分布在显著性水平为0.05时对应的临界阈值为3.841自由度为2的卡方分布在显著性水平为0.05时对应的临界阈值为5.991 */const float th = 3.841;const float thScore = 5.991;/* 方差平方的倒数,作为信息矩阵 协方差的逆 */const float invSigmaSquare = 1.0 / (sigma * sigma);

根据传入的sigma值计算协方差矩阵

    /* 通过F矩阵,进行参考帧和当前帧之间的双向投影,并计算出加权重投影误差 */for (int i = 0; i < N; i++){/* 开始都默认为Inlier */bool bIn = true;/* 提取参考帧和当前帧之间的特征匹配点对 */const cv::KeyPoint &kp1 = mvKeys1[mvMatches12[i].first];const cv::KeyPoint &kp2 = mvKeys2[mvMatches12[i].second];/* 提取出特征点的坐标 */const float u1 = kp1.pt.x;const float v1 = kp1.pt.y;const float u2 = kp2.pt.x;const float v2 = kp2.pt.y;// Reprojection error in second image// l2=F21x1=(a2,b2,c2)/* 计算 参考帧 上的点在 当前帧 上投影得到的极线 l2 = F21 * p1 = (a2, b2, c2) */const float a2 = f11 * u1 + f12 * v1 + f13;const float b2 = f21 * u1 + f22 * v1 + f23;const float c2 = f31 * u1 + f32 * v1 + f33;/* 计算 当前帧的特征点 到 投影得到的极线 l2 的距离平方 d^2 = ((ax+by+c) / sqrt(a^2 + b^2))^2 */const float num2 = a2 * u2 + b2 * v2 + c2;const float squareDist1 = num2 * num2 / (a2 * a2 + b2 * b2);/* 转换参考帧投影至当前帧的误差 */const float chiSquare1 = squareDist1 * invSigmaSquare;/* 阀值用th,而累加得分用thScore,确保与单应基础评分标准一致 *//* 用阈值标记离群点,内点的话累加得分 */if (chiSquare1 > th)bIn = false;else/* 累计得分。误差越大,得分越低 */score += thScore - chiSquare1;// Reprojection error in second image// l1 =x2tF21=(a1,b1,c1)/* 计算 当前帧 上的点在 参考帧 上投影得到的极线 l1 = p2 * F21 = (a1, b1, c1) */const float a1 = f11 * u2 + f21 * v2 + f31;const float b1 = f12 * u2 + f22 * v2 + f32;const float c1 = f13 * u2 + f23 * v2 + f33;/* 计算 参考帧的特征点 到 投影得到的极线 l1 的距离平方 d^2 = ((ax+by+c) / sqrt(a^2 + b^2))^2 */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;else/* 累计得分。误差越大,得分越低 */score += thScore - chiSquare2;/* 双向重投影误差均满足要求,则说明当前点为内点 */if (bIn)vbMatchesInliers[i] = true;elsevbMatchesInliers[i] = false;}/* 返回得分 */return score;
}

根据对极约束的几何意义,它能够将一幅图像中的某个点投影到另一幅图像的极线上

在这里插入图片描述
对每个匹配的特征点,计算双向投影误差(特征点 到 投影得到的极线 的距离 d = d = d= a x + b y + c a 2 + b 2 ax+by+c \over \sqrt{a^2 + b^2} a2+b2 ax+by+c 的 平方),并获取对应得分和更新内点标记,具体如下:

  1. 获取匹配点的像素坐标
  2. 计算参考帧上的点 x 1 x_1 x1 在当前帧上投影得到的极线 l 2 l_2 l2,再计算参考帧到当前帧的带权重的重投影误差,同时累积当前得分并进行内点判断
  3. 计算当前帧上的点 x 2 x_2 x2 在参考帧上投影得到的极线 l 1 l_1 l1,再计算当前帧到参考帧的带权重的重投影误差,同时累积当前得分并进行内点判断
  4. 记录当前匹配点的内点标记

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

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

相关文章

基于springboot+vue的美食推荐商城

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

SLAM基础知识-卡尔曼滤波

前言&#xff1a; 在SLAM系统中&#xff0c;后端优化部分有两大流派。一派是基于马尔科夫性假设的滤波器方法&#xff0c;认为当前时刻的状态只与上一时刻的状态有关。另一派是非线性优化方法&#xff0c;认为当前时刻状态应该结合之前所有时刻的状态一起考虑。 卡尔曼滤波是…

【Transformer】笔记

主要参考 https://zhuanlan.zhihu.com/p/366592542 https://mp.weixin.qq.com/s/b-_M8GPK7FD7nbPlN703HQ 其他参考 原理 https://zhuanlan.zhihu.com/p/627448301 多头注意力机制 https://zhuanlan.zhihu.com/p/611684065 https://blog.csdn.net/shizheng_Li/article/details/1…

Launch学习

参考博客&#xff1a; (1) 史上最全的launch的解析来啦&#xff0c;木有之一欧 1 ROS工作空间简介 2 元功能包 src目录下可以包含多个功能包&#xff0c;假设需要使用机器人导航模块&#xff0c;但是这个模块中包含着地图、定位、路径规划等不同的功能包&#xff0c;它们的逻…

【二】【SQL】去重表数据及分组聚合查询

去重表数据 表的准备工作 去除表中重复的数据&#xff0c;重复的数据只留一份。 mysql> create table duplicate_table (-> id int,-> name varchar(20)-> ); Query OK, 0 rows affected (0.03 sec)mysql> insert into duplicate_table values-> (100,aaa)…

Doris——纵腾集团流批一体数仓架构

目录 前言 一、早期架构 二、架构选型 三、新数据架构 3.1 数据中台 3.2 数仓建模 3.3 数据导入 四、实践经验 4.1 准备阶段 4.2 验证阶段 4.3 压测阶段 4.4 上线阶段 4.5 宣导阶段 4.6 运行阶段 4.6.1 Tablet规范问题 4.6.2 集群读写优化 五、总结收益 六…

深度学习PyTorch 之 RNN-中文多分类

关于RNN的理论部分我们已经在前面介绍过&#xff0c;所以这里直接上代码 1、 数据部分 1.1 读取数据 # 加载数据 data_path ./data/news.csv data pd.read_csv(data_path)# 预览数据的前几行 data.head()数据是csv格式&#xff0c;只有两列&#xff0c;第一列是标签&#…

【解决方案】ArcGIS Engine二次开发时,运行后出现“正尝试在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain...”

我们在做ArcGIS Engine二次开发时&#xff0c;特别是新手&#xff0c;安装好了开发环境&#xff0c;满怀信心的准备将按照教程搭建好的框架在Visual Studio中进行运行。点击运行后&#xff0c;却出现了“正尝试在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化…

ABAP - SALV教程06 - 列的设置(隐藏、修改、优化列宽)

SAVL要想像Function ALV或OO ALV那样设置Fieldcat&#xff0c;也是有方法的。通过取得全体列的类引用 CL_SALV_COLUMNS来进行修改 METHOD set_columns.* 取得全部列的对象DATA(lo_cols) co_alv->get_columns( ).* 设置自动优化列宽度lo_cols->set_optimize( X ).T…

实例驱动计算机网络

文章目录 计算机网络的层次结构应用层DNSHTTP协议HTTP请求响应过程 运输层TCP协议TCP协议面向连接实现TCP的三次握手连接TCP的四次挥手断开连接 TCP协议可靠性实现TCP的流量控制TCP的拥塞控制TCP的重传机制 UDP协议 网际层IP协议&#xff08;主机与主机&#xff09;IP地址的分类…

计算机视觉基础知识(十六)--图像识别

图像识别 信息时代的一门重要技术;目的是让计算机代替人类处理大量的物理信息;随着计算机技术的发展,人类对图像识别技术的认识越来越深刻;图像识别技术利用计算机对图像进行处理\分析\理解,识别不同模式的目标和对象;过程分为信息的获取\预处理\特征抽取和选择\分类器设计\分…

在Golang中简化日志记录:提升性能和调试效率

最大化效率和有效故障排除&#xff1a;在Golang中简化日志记录 日志记录是软件开发的一个基本方面&#xff0c;有助于调试、监控和理解应用程序的流程。在Golang中&#xff0c;有效的日志记录实践可以显著提高性能并简化调试过程。本文探讨了优化Golang日志记录的技术&#xf…

[HackMyVM]靶场 VivifyTech

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (Unk…

基于Java的超市商品管理系统(Vue.js+SpringBoot)

目录 一、摘要1.1 简介1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 超市区域模块2.3 超市货架模块2.4 商品类型模块2.5 商品档案模块 三、系统设计3.1 用例图3.2 时序图3.3 类图3.4 E-R图 四、系统实现4.1 登录4.2 注册4.3 主页4.4 超市区域管理4.5 超市货架管理4.6 商品类型…

浅谈 Linux fork 函数

文章目录 前言fork 基本概念代码演示示例1&#xff1a;体会 fork 函数返回值的作用示例2&#xff1a;创建多进程&#xff0c;加深对 fork 函数的理解 前言 本篇介绍 fork 函数。 fork 基本概念 pid_t fork(void) fork 的英文含义是"分叉"&#xff0c;在这里就是 …

Java知识点整理(一)

反射 反射是在运行状态中&#xff0c;动态获取类信息&#xff0c;以及动态调用对象的方法的功能叫做反射机制。在JDBC&#xff0c;Servlet&#xff0c;SpringIOC中 优点&#xff1a;能够灵活的创建代码&#xff0c;动态执行方法访问属性。 缺点&#xff1a;破坏了封装性&…

Mysql学习之MVCC解决读写问题

多版本并发控制 什么是MVCC MVCC &#xff08;Multiversion Concurrency Control&#xff09;多版本并发控制。顾名思义&#xff0c;MVCC是通过数据行的多个版本管理来实现数据库的并发控制。这项技术使得在InnoDB的事务隔离级别下执行一致性读操作有了保证。换言之&#xff0…

从零自制docker-1-【环境配置 docker go介绍与安装】

文章目录 docker简介举例docker安装go语言go安装go 配置 docker简介 Docker可以看作是一种极其轻巧的“虚拟机”&#xff0c;它允许你将一个或多个程序及其运行环境打包在一起&#xff0c;形成一个标准化的单元&#xff0c;这个单元可以在任何支持Docker的系统上运行&#xff…

神经网络之万能定理python-pytorch实现,可以拟合任意曲线

神经网络之万能定理python-pytorch实现&#xff0c;可以拟合任意曲线 博主&#xff0c;这几天一直在做这个曲线拟合的实验&#xff0c;讲道理&#xff0c;网上可能也有很多这方面的资料&#xff0c;但是博主其实试了很多&#xff0c;效果只能对一般的曲线还行&#xff0c;稍微…

114.龙芯2k1000-pmon(13)- 串口如何用

本文是讲原理图的部分&#xff0c;跟pmon的关系不大&#xff01;&#xff01; 参考手册&#xff1a;《龙芯2K1000处理器用户手册.pdf》 刚刚看数据手册&#xff0c;让我是有点惊讶&#xff0c;但是也让我迷惑。&#xff08;一个串口复用为4个是啥意思&#xff1f;&#xff09;…