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

news2024/10/5 13:50:37

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;
        else
            vbMatchesInliers[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.coloradmin.cn/o/1482611.html

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

相关文章

nginx 配置浏览器不缓存文件 每次都会从服务器 请求新的文件

目录 解决问题方法说明 测试html环境js环境第一步然后修改内容 打开带有js缓存的页面强制刷新 配置nginx 每次打开页面都会重新请求index.js 文件重启nginx再次修改index.js 总结设置为全局 解决问题 适用于实时更新数据的&#xff0c;网页 可以让用户每次都是重新请求&#x…

《从0开始搭建实现apollo9.0》系列三 CANBUS模块解读

二、CANBUS代码 1、canbus模块的软件架构如下&#xff1a; 主要输入输出 输入&#xff1a;apollo::control::ControlCommand | 控制指令 输出&#xff1a; /apollo/chassis | apollo::canbus::Chassis | 车辆底盘信息接口数据&#xff0c;包括车辆速度、方向盘转角、档位、底盘…

Vue Html中插入本地视频(Video 标签)

在 Vue 中插入本地视频可以通过使用标签来实现。你可以将视频文件放在你的项目中的合适位置&#xff08;比如assets文件夹&#xff09;&#xff0c;然后在 Vue 组件中引用这个视频文件。html同理 首先&#xff0c;在你的 Vue 项目中的assets文件夹下放入你的视频文件&#xff…

兼容性比较好的浏览器推荐(2023手机浏览器排名)

浏览器在我们日常工作生活占据着重要的位置。浏览器是电脑的必备软件&#xff0c;也是手机端不可缺少的软件之一。如果你想要下载浏览器&#xff0c;却不知道哪个浏览器最好用&#xff0c;那么就看看本篇文章。下文给大家推荐2023年最热门、好用的手机浏览器&#xff0c;排行不…

计算机网络【网络安全】

计算机网络——网络安全 一、网络安全问题概述 网络安全威胁 网络安全面临两大类威胁&#xff0c;被动攻击和主动攻击 被动攻击 指攻击者从网络上窃听他人的通信内容&#xff0c;通常把这类攻击称为截获。 主动攻击 篡改 攻击者故意篡改网络上传送的报文 恶意程序 拒绝服…

java实现图片转pdf,并通过流的方式进行下载(前后端分离)

首先需要导入相关依赖&#xff0c;由于具体依赖本人也不是记得很清楚了&#xff0c;所以简短的说一下。 iText&#xff1a;PDF 操作库&#xff0c;用于创建和操作 PDF 文件。可通过 Maven 或 Gradle 引入 iText 依赖。 MultipartFile&#xff1a;Spring 框架中处理文件上传的类…

day08_分类品牌管理商品规格管理商品管理

文章目录 1 分类品牌管理1.1 菜单添加1.2 表结构介绍1.3 页面制作1.4 品牌列表加载1.4.1 后端接口BrandControllerBrandServiceBrandMapperBrandMapper.xml 1.4.2 前端对接brand.jscategoryBrand.vue 1.5 分类数据加载1.6 列表查询1.6.1 需求说明1.6.2 后端接口需求分析Categor…

软考基础知识2

1.DMA控制方式&#xff1a;直接内存存取。数据在内存与I/O设备间直接成块传送&#xff0c;不需要CPU的任何干涉&#xff0c;由DMA硬件直接执行完成。 例题&#xff1a; 2.程序计数器总是存下一个指令的地址。 例题&#xff1a; 3.可靠度的计算&#xff1a; 例题&#xff1a…

低碳策略全都有!EI论文:计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度程序代码!

适用平台&#xff1a;MatlabYalmipCplex 参考文献&#xff1a;《计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度》-电网技术 程序建立了碳交易市场下的计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度模型&#xff0c;鉴于该模型具有高维非线性特点&#xff0c;求…

蓝桥杯算法题汇总

一.线性表&#xff1a;链式 例题&#xff1a;旋转链表 二.栈&#xff1a; 例题&#xff1a;行星碰撞问题 三.队列 三.数组和矩阵 例题&#xff1a;

亿道信息轻工业三防EM-T195,零售、制造、仓储一网打尽

厚度仅10.5mm&#xff0c;重量仅0.65千克的EM-T195&#xff0c;其紧凑而纤薄的设计为以往加固型平板带来了全新的轻薄概念。尽管设计时尚、轻薄&#xff0c;但经过军用认证的强固性仍然能够承受所有具有挑战性的环境条件。随身携带无负担的轻便性加上抗震功能使其成为餐厅、酒店…

Spring Initializer环境问题

1.基于jdk8与本地 环境准备 1)下载jdk8并安装 2&#xff09;下载maven 3.6.3并解压放入D盘maven目录下&#xff0c;去掉外层 设置阿里源 打开settings.xml,在mirrors标签之内增加&#xff0c;注意粘贴后</id>中的/有可能被删掉&#xff0c;要自己补上 <mirror>&l…

敏捷开发模型:一种灵活、协作和持续的软件开发方法

敏捷开发模型&#xff1a;一种灵活、协作和持续的软件开发方法 引言 在软件开发领域&#xff0c;随着市场需求的不断变化和技术的迅速发展&#xff0c;传统的瀑布模型逐渐暴露出其局限性。为了应对这些挑战&#xff0c;敏捷开发模型应运而生。敏捷开发模型强调灵活、协作和持…

Java基于springboot的厨艺交流平台的设计与实现代码

摘 要 使用旧方法对厨艺交流信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在厨艺交流信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的厨艺交流平台功…

华为HCIP Datacom H12-821 卷4

1.单选题 下面哪些策略或工具不能够应用于 OSPF: A、access-list B、prefix-list C、route- Policy D、as-path filter 正确答案&#xff1a; D 解析&#xff1a; as-path-filter命令用来创建AS路径过滤器&#xff0c;OSPF属于IGP协议&#xff0c;不涉及到AS号。 2.单选题…

AI时代,我们需要什么能力?

AI 时代&#xff0c;一定会重构很多行业&#xff0c;也会重构人民的生活工作方式&#xff0c;那么 AI 时代&#xff0c;我们需要培养什么能力呢&#xff1f; 我们应该去做那些 AI 做不了的事情&#xff01;让 AI 成为我们的工具&#xff0c;助力我们更高效的解决问题&#xff…

信息系统项目管理师--项目管理概述

开展项⽬是为了通过可交付成果达成⽬标。⽬标是所指向的结果、要取得的战略地位、要达到的⽬的、要获得的成果、要⽣产的产品或者要提供的服务。 可交付成果形成的独特并可验证的产品、成果或服务。可交付成果可能是有形的&#xff0c;也可能是⽆形的。产⽣⼀个或多个可交付成…

openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划

文章目录 openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划 openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划 完成资源负载管理功能配置前&#xff0c;需要先根据业务模型完成租户资源的规划。业…

矩阵爆破逆向之条件断点的妙用

不知道你是否使用过IDA的条件断点呢&#xff1f;在IDA进阶使用中&#xff0c;它的很多功能都有大作用&#xff0c;比如&#xff1a;ida-trace来跟踪调用流程。同时IDA的断点功能也十分强大&#xff0c;配合IDA-python的输出语句能够大杀特杀&#xff01; 那么本文就介绍一下这…

gpt生成器,批量gpt文章生成器

GPT&#xff08;生成式预训练模型&#xff09;生成器软件在当今的数字化时代扮演着越来越重要的角色&#xff0c;它们通过人工智能技术&#xff0c;可以自动生成各种类型的文章内容&#xff0c;为用户提供了无限的创作可能性。本文将介绍6款不同的GPT生成器软件&#xff0c;并介…