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

计算机视觉之SLAM与6Dof

第一部分:SLAM与6dof简介

1.1 SLAM技术概述

SLAM(Simultaneous Localization and Mapping)即同时定位与地图构建,是一种机器人领域中的关键技术。它允许机器人在未知环境中,通过传感器收集环境信息,同时进行自我定位和地图构建。SLAM技术在自动驾驶、无人机、增强现实等领域具有广泛的应用。

SLAM技术可以分为前端和后端两个部分:

  1. 前端:负责实时处理传感器数据,提取特征点,进行位姿估计,生成初始的局部地图。
  2. 后端:负责优化前端产生的位姿估计和地图,提高定位和地图构建的精度。

1.2 6自由度(6dof)

6自由度(6 degrees of freedom,简称6dof)是指一个物体在三维空间中具有六个独立运动的自由度,包括三个旋转自由度和三个平移自由度。具体如下:

  1. 三个旋转自由度:物体可以围绕三个互相垂直的轴进行旋转,分别是俯仰(Pitch)、横滚(Roll)和偏航(Yaw)。
  2. 三个平移自由度:物体可以沿着三个互相垂直的轴进行平移,分别是前向(X轴)、侧向(Y轴)和垂直(Z轴)。

在SLAM技术中,6自由度用于描述相机或机器人等设备在三维空间中的位姿。通过求解6自由度,我们可以得到设备在三维空间中的精确位置和姿态,从而实现高精度的定位和地图构建。

1.3 SLAM与6dof的关系

SLAM技术与6dof密切相关,因为SLAM需要求解相机或机器人在三维空间中的位姿,而位姿的表示正是通过6自由度来实现的。在SLAM过程中,通过传感器(如摄像头、激光雷达等)收集环境信息,然后使用算法求解6自由度,从而实现实时定位和地图构建。

在本系列的后续部分,我们将详细介绍SLAM技术中的前端和后端算法,并通过实际代码演示如何实现6自由度的求解。接下来,我们将进入第二部分,探讨SLAM技术中的前端算法。

第二部分:SLAM前端算法

2.1 特征提取与匹配

在SLAM的前端处理中,特征提取与匹配是非常关键的一步。这一步骤的目的是为了找到连续帧之间相同或相似的特征点,以便后续进行位姿估计。常用的特征提取算法有SIFT、SURF、ORB等,它们各有优缺点,适用于不同的场景。

2.1.1 ORB特征提取算法

ORB(Oriented FAST and Rotated BRIEF)是一种高效的特征提取算法,它结合了FAST角点检测和BRIEF特征描述子的特点,并加入了尺度和旋转不变性。ORB算法的主要步骤如下:

  1. FAST角点检测:检测图像中的角点,选择具有高梯度变化的点作为候选点。
  2. Harris角点评分:对候选点进行Harris角点评分,筛选出质量较高的角点。
  3. 特征点方向赋值:计算每个特征点的方向,使得特征具有旋转不变性。
  4. 生成特征描述子:使用BRIEF描述子生成特征点的描述向量,同时考虑特征点的尺度和旋转。

2.1.2 特征匹配

特征匹配是将两帧图像中的特征点进行对应的过程。ORB算法使用汉明距离来度量两个特征描述子的相似度,通过设置一个阈值来判断是否为匹配点。匹配过程中还会使用RANSAC算法来滤除误匹配点,提高匹配的准确性。

2.2 位姿估计

位姿估计是根据特征匹配结果计算两帧图像之间的相对变换关系。在SLAM中,常用的位姿估计方法有单应性矩阵(Homography)和基础矩阵(Fundamental Matrix)。

2.2.1 单应性矩阵

单应性矩阵用于描述两个图像之间的变换关系,它适用于场景平面结构比较明显的场合。通过解算单应性矩阵,可以得到两帧图像之间的旋转和平移变换。

2.2.2 基础矩阵

基础矩阵描述了两个图像中匹配点对之间的几何关系,它适用于一般场景下的位姿估计。通过解算基础矩阵,可以得到两帧图像之间的本质矩阵(Essential Matrix),进而分解出旋转和平移变换。

2.3 局部地图构建

在SLAM的前端处理中,除了进行特征提取、匹配和位姿估计外,还需要构建局部地图。局部地图通常由当前帧的特征点及其位置信息组成,用于辅助后续的位姿优化和回环检测。

2.4 代码示例

下面是一个使用Python和OpenCV实现的简化版ORB-SLAM前端处理的代码示例:

import cv2
import numpy as np# 初始化ORB特征提取器
orb = cv2.ORB_create()# 读取两帧图像
img1 = cv2.imread('frame1.jpg', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('frame2.jpg', cv2.IMREAD_GRAYSCALE)# 提取特征点
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)# 特征匹配
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)# 按照距离排序
matches = sorted(matches, key=lambda x: x.distance)# 选择最佳匹配点
good_matches = matches[:int(len(matches) * 0.15)]# 绘制匹配结果
img3 = cv2.drawMatches(img1, kp1, img2, kp2, good_matches, None, flags=2)# 显示匹配结果
cv2.imshow('Matches', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

这段代码演示了如何使用ORB算法提取特征点并进行匹配,最后绘制出匹配结果。在实际的SLAM系统中,还需要结合位姿估计和局部地图构建等步骤,才能实现完整的SLAM前端处理。

在第三部分,我们将详细介绍SLAM技术中的后端算法,以及如何通过优化提高定位和地图构建的精度。

第三部分:SLAM后端算法

3.1 后端优化概述

SLAM后端优化是整个SLAM系统中至关重要的一环,它负责对前端产生的初始位姿估计和地图进行优化,以提高整个系统的精度和鲁棒性。后端优化通常涉及滤波和图优化两种主要方法。

3.1.1 滤波方法

滤波方法,如卡尔曼滤波(Kalman Filter, EKF)和粒子滤波(Particle Filter),主要用于连续数据的在线实时处理。它们通过建立系统的状态转移模型和观测模型,来递推地更新系统的状态估计。

卡尔曼滤波(EKF)

EKF是SLAM中常用的滤波方法,它通过线性化非线性函数,将非线性问题转化为线性问题,然后使用标准的卡尔曼滤波公式进行状态估计。EKF适用于系统模型相对简单的场合。

粒子滤波

粒子滤波适用于系统模型非线性较强、噪声非高斯的场合。它通过一组随机样本(粒子)来表示系统状态的后验概率分布,通过重采样和重要性采样来递推地更新粒子的权重和状态。

3.1.2 图优化方法

图优化方法,如g2o、Ceres和GTSAM,将SLAM问题建模为图优化问题,其中节点表示相机位姿或路标点,边表示位姿之间的约束关系。图优化方法可以离线或在线进行,适用于大规模、复杂场景的SLAM问题。

g2o

g2o(General Graph Optimization)是一个开源的图优化库,它提供了通用的图优化框架,支持多种优化算法和线性方程求解器。g2o可以用于SLAM中的位姿图优化和因子图优化。

Ceres

Ceres Solver是一个用于非线性最小二乘问题的求解器,它可以通过构建残差块(Residual Blocks)来表示优化问题,并提供了多种数值优化算法和线性方程求解器。

GTSAM

GTSAM(Georgia Tech Smoothing and Mapping)是一个基于因子图优化的SLAM库,它提供了丰富的因子和变量类型,支持增量式和批处理式的优化。

3.2 位姿图优化

位姿图优化是图优化方法中的一种,它将SLAM问题中的相机位姿作为图中的节点,将位姿之间的约束关系(如相邻帧的相对位姿)作为图中的边,通过优化这些边的权重来优化相机位姿。

3.2.1 位姿图构建

位姿图的构建包括确定节点和边的类型,以及如何根据SLAM前端提供的信息来构建图。通常,每个相机位姿对应一个节点,每两个相邻位姿之间的变换对应一条边。

3.2.2 位姿图优化

位姿图优化是一个迭代过程,它通过最小化边的权重(即残差)来优化节点的位姿。优化过程中,通常使用非线性优化算法,如Levenberg-Marquardt算法,来求解优化问题。

3.3 因子图优化

因子图优化是另一种图优化方法,它将SLAM问题中的变量(如相机位姿和路标点)和约束(如观测约束和运动约束)表示为因子图中的节点和边。因子图优化可以同时优化相机位姿和路标点的位置。

3.3.1 因子图构建

因子图的构建包括确定变量和因子的类型,以及如何根据SLAM前端提供的信息来构建图。通常,每个相机位姿和每个路标点对应一个变量,每个观测和运动约束对应一个因子。

3.3.2 因子图优化

因子图优化同样是一个迭代过程,它通过最小化因子的残差来优化变量的值。优化过程中,可以使用非线性优化算法,如Levenberg-Marquardt算法,来求解优化问题。

3.4 代码示例与实现

为了更好地理解SLAM后端优化中的图优化方法,我们将通过一个简化的代码示例来展示如何使用g2o库进行位姿图优化。在这个示例中,我们将构建一个简单的位姿图,其中包含几个顶点(代表相机位姿)和边(代表位姿之间的约束关系),并使用g2o进行优化。

3.4.1 位姿图构建

首先,我们需要定义图的顶点和边。在g2o中,顶点通常是VertexSE3类型,代表相机位姿,而边可以是EdgeSE3类型,代表两个位姿之间的变换。

#include <g2o/core/sparse_optimizer.h>
#include <g2o/core/block_solver.h>
#include <g2o/core/optimization_algorithm_levenberg.h>
#include <g2o/solvers/csparse/linear_solver_csparse.h>
#include <g2o/types/slam3d/vertex_se3.h>
#include <g2o/types/slam3d/edge_se3.h>int main() {// 创建优化器g2o::SparseOptimizer optimizer;optimizer.setVerbose(true);// 创建线性求解器g2o::LinearSolverCSparse<g2o::BlockSolver_6_3::PoseMatrixType> *linearSolver = new g2o::LinearSolverCSparse<g2o::BlockSolver_6_3::PoseMatrixType>();// 创建块求解器g2o::BlockSolver_6_3 *blockSolver = new g2o::BlockSolver_6_3(linearSolver);// 创建优化算法g2o::OptimizationAlgorithmLevenberg *solver = new g2o::OptimizationAlgorithmLevenberg(blockSolver);// 设置优化器optimizer.setAlgorithm(solver);// 添加顶点for (int i = 0; i < num_poses; ++i) {g2o::VertexSE3 *v = new g2o::VertexSE3();v->setId(i);v->setEstimate(Eigen::Isometry3d::Identity());optimizer.addVertex(v);}// 添加边for (int i = 0; i < num_edges; ++i) {g2o::EdgeSE3 *e = new g2o::EdgeSE3();e->setId(i);e->setVertex(0, optimizer.vertex(i));e->setVertex(1, optimizer.vertex(i+1));e->setMeasurement(Eigen::Isometry3d::Identity()); // 假设已知变换e->information() = Eigen::Matrix<double, 6, 6>::Identity();optimizer.addEdge(e);}// 执行优化optimizer.initializeOptimization();optimizer.optimize(10);// 清理delete solver;return 0;
}

在这个示例中,我们首先创建了一个SparseOptimizer对象,并为其设置了一个Levenberg-Marquardt算法的求解器。然后,我们添加了一系列的VertexSE3顶点,每个顶点代表一个相机位姿,并添加了EdgeSE3边,每个边代表两个相邻位姿之间的变换关系。最后,我们调用了initializeOptimizationoptimize方法来执行优化。

3.4.2 位姿图优化结果

执行优化后,每个顶点的位姿将会根据边的约束关系进行调整,从而得到更加精确的位姿估计。这些优化后的位姿可以用于后续的SLAM任务,如地图构建或路径规划。

3.5 小结

SLAM后端优化是提高SLAM系统精度和鲁棒性的关键步骤。通过滤波和图优化方法,可以有效地整合前端处理的结果,并提高位姿估计和地图构建的准确性。在实际应用中,选择合适的优化方法取决于具体的场景和需求。在下一部分,我们将探讨SLAM中的回环检测和地图融合技术,以及如何实现大规模、长期运行的SLAM系统。

第四部分:SLAM中的回环检测与地图融合

4.1 回环检测概述

回环检测(Loop Closure Detection)是SLAM中的一项重要技术,它允许机器人识别出之前访问过的场景或位置,从而建立当前帧与历史帧之间的关联。回环检测对于减少累积误差、提高地图的一致性和实现全局优化至关重要。

4.1.1 回环检测的方法

回环检测的方法主要分为基于视觉的和基于几何的方法:

  1. 基于视觉的回环检测:这种方法使用图像特征来识别回环。常用的算法有词袋模型(Bag of Words, BoW)、深度学习等。词袋模型将图像的特征点聚类为视觉单词(Visual Words),然后通过比较不同帧的视觉单词分布来判断是否形成回环。

  2. 基于几何的回环检测:这种方法使用几何信息来检测回环。例如,通过比较当前帧的位姿与历史帧的位姿,如果发现两个位姿非常接近,则可能检测到一个回环。

4.1.2 回环验证

一旦检测到潜在的回环,需要进行回环验证来确认检测的正确性。常用的回环验证方法包括:

  • 本质图(Essential Graph):通过构建本质图,将潜在的回环节点加入到图中,然后使用图优化方法进行优化,如果优化结果一致,则认为回环是正确的。
  • 姿态图(Pose Graph):将潜在的回环节点加入到姿态图中,然后使用姿态图优化来验证回环的正确性。
  • ICP(Iterative Closest Point):通过ICP算法将当前帧的点云与历史帧的点云进行对齐,如果对齐误差较小,则认为回环是正确的。

4.2 地图融合

地图融合(Map Merging)是指将多个局部地图或子地图合并为一个全局一致地图的过程。地图融合对于实现大规模、长期运行的SLAM系统至关重要。

4.2.1 地图融合的方法

地图融合的方法主要分为基于滤波的和基于图优化的方法:

  1. 基于滤波的地图融合:这种方法使用滤波器(如卡尔曼滤波器)来更新全局地图。每个局部地图都有一个对应的滤波器,地图融合的过程就是将这些滤波器合并为一个全局滤波器。

  2. 基于图优化的地图融合:这种方法使用图优化(如g2o、Ceres、GTSAM)来优化全局地图。每个局部地图都有一组顶点和边,地图融合的过程就是将这些顶点和边合并到一个全局图中,然后使用图优化算法进行优化。

4.2.2 地图融合的挑战

地图融合面临以下几个挑战:

  • 数据关联:如何正确地将不同局部地图中的相同特征点或路标点关联起来。
  • 累积误差:随着地图规模的扩大,累积误差会逐渐增大,如何有效地减少累积误差。
  • 计算资源:大规模地图融合需要大量的计算资源,如何提高算法的效率。

4.3 实现回环检测与地图融合

在SLAM系统中,回环检测和地图融合是提高地图全局一致性的关键环节。以下是如何在SLAM中实现这两部分的简要概述和示例。

4.3.1 回环检测实现

回环检测通常涉及两个主要步骤:特征提取与匹配,以及回环验证。

特征提取与匹配

使用前面提到的ORB特征提取算法,我们可以为每个关键帧提取特征点并计算描述子。然后,通过比较当前帧的描述子与先前帧的描述子,可以使用最近邻匹配来找到潜在的回环。

回环验证

一旦找到潜在的回环,我们需要验证它们是否正确。这可以通过计算两个帧之间的变换矩阵并检查其是否与已知的相机运动模型一致来实现。如果变换矩阵在合理范围内,则可以认为回环是正确的。

4.3.2 地图融合实现

地图融合通常涉及将多个局部地图或关键帧的位姿和特征点合并到一个全局一致的地图中。这可以通过图优化方法来实现。

图优化

使用g2o、Ceres或GTSAM等图优化库,我们可以构建一个包含相机位姿和特征点的图。每个位姿和特征点都是一个顶点,而它们之间的关系则是图的边。通过优化这些边的权重,我们可以得到全局一致的地图。

代码示例

由于回环检测和地图融合通常涉及到复杂的算法和大量的计算,提供一个简化的代码示例可能不太合适。不过,我们可以提供一个使用OpenCV和PCL(Point Cloud Library)进行ICP回环验证的示例:

#include <iostream>
#include <pcl/registration/icp.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/io/pcd_io.h>int main() {// 读取两个点云pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_src(new pcl::PointCloud<pcl::PointXYZ>);pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_tgt(new pcl::PointCloud<pcl::PointXYZ>);pcl::io::loadPCDFile("path/to/previous_frame.pcd", *cloud_src);pcl::io::loadPCDFile("path/to/current_frame.pcd", *cloud_tgt);// 初始化ICPpcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;icp.setInputSource(cloud_src);icp.setInputTarget(cloud_tgt);// 设置ICP参数icp.setMaxCorrespondenceDistance(0.1);icp.setTransformationEpsilon(1e-6);icp.setEuclideanFitnessEpsilon(1e-6);icp.setMaximumIterations(50);// 执行ICP配准pcl::PointCloud<pcl::PointXYZ> final_cloud;icp.align(final_cloud);// 输出结果std::cout << "Has converged: " << icp.hasConverged() << std::endl;std::cout << "Fitness score: " << icp.getFitnessScore() << std::endl;std::cout << "Transformation matrix:" << std::endl;std::cout << icp.getFinalTransformation() << std::endl;// 可视化结果pcl::visualization::PCLVisualizer viewer("ICP Alignment");viewer.addPointCloud(cloud_tgt, "target_cloud");viewer.addPointCloud(final_cloud, "aligned_cloud");while (!viewer.wasStopped()) {viewer.spinOnce();}return 0;
}

在这个示例中,我们首先读取了两个点云,然后使用PCL的ICP算法对它们进行了配准。配准结果可以通过检查icp.hasConverged()icp.getFitnessScore()来确定是否成功。如果配准成功,我们可以将当前帧的位姿和特征点融合到全局地图中。

4.4 小结

回环检测和地图融合是SLAM系统中至关重要的环节,它们使得机器人能够在更大的环境中建立一致性的地图,并减少累积误差。通过结合视觉特征和几何信息,SLAM系统能够实现长期运行和大规模地图构建。在下一部分,我们将探讨SLAM系统的实际应用,以及如何将SLAM技术应用于不同的平台和场景。

第五部分:SLAM系统的实际应用

5.1 SLAM的应用领域

SLAM技术的应用非常广泛,它已经被应用于许多不同的领域和平台,包括但不限于以下几个方面:

5.1.1 自动驾驶汽车

自动驾驶汽车是SLAM技术的一个主要应用领域。通过使用激光雷达(LiDAR)、摄像头和其他传感器,自动驾驶汽车可以在行驶过程中实时构建周围环境的高精度地图,并准确地确定自身的位置和姿态。这些信息对于路径规划、障碍物避让和车辆控制至关重要。

5.1.2 无人机

无人机在空中导航和地图绘制中也广泛使用SLAM技术。无人机通常配备有摄像头和惯性测量单元(IMU),它们可以实时构建周围环境的地图,并用于导航、避障和任务执行。

5.1.3 增强现实(AR)和虚拟现实(VR)

增强现实和虚拟现实技术利用SLAM来实现在用户视野中叠加虚拟物体或创建完全虚拟的环境。通过实时跟踪用户的位置和姿态,SLAM技术可以确保虚拟物体在现实世界中的正确位置和比例。

5.1.4 家用机器人

家用机器人,如扫地机器人和服务机器人,使用SLAM技术来导航和构建家庭环境的地图。这允许它们高效地清理房间或执行其他任务,同时避免碰撞和迷失方向。

5.1.5 工业和制造业

在工业和制造业中,SLAM技术被用于自动化和机器人技术,以提高生产效率和安全性。例如,自动化仓库中的机器人使用SLAM来导航和定位,而工业检查机器人使用SLAM来探索和检查复杂的工业设施。

5.2 SLAM技术挑战

尽管SLAM技术取得了显著的进展,但在实际应用中仍面临一些挑战:

5.2.1 动态环境

在动态环境中,SLAM算法需要能够区分静态和动态物体,并仅对静态环境进行建图。这要求算法具有高效的动态物体检测和跟踪能力。

5.2.2 大规模环境

在大规模环境中,SLAM系统需要处理大量的数据,并保持长时间的运行稳定性。这要求算法具有高效的数据处理能力和鲁棒的错误恢复机制。

5.2.3 多样化的传感器

不同的应用可能需要不同类型的传感器,如激光雷达、摄像头、超声波传感器等。SLAM系统需要能够处理这些不同传感器的数据融合问题,以获得更准确的结果。

5.2.4 计算资源限制

在一些平台上,如嵌入式设备或移动设备,计算资源可能有限。SLAM系统需要优化算法,以适应这些资源限制,同时保持高性能。

5.3 SLAM技术发展趋势

SLAM技术的未来发展趋势包括以下几个方面:

5.3.1 传感器融合

随着传感器技术的进步,将不同类型的传感器数据进行融合,以提高SLAM系统的准确性和鲁棒性,是未来的一个重要发展方向。

5.3.2 深度学习

深度学习在特征提取、数据关联和回环检测等方面的应用,将进一步提高SLAM系统的性能。

5.3.3 分布式SLAM

分布式SLAM系统可以将任务分散到多个机器人或设备上,以提高建图效率和鲁棒性。

5.3.4 云SLAM

利用云计算资源,云SLAM可以将计算密集型的任务转移到云端,从而减轻本地设备的计算负担。

5.4 小结

SLAM技术是机器人、自动驾驶、增强现实等领域的关键技术。随着技术的不断进步和应用的不断拓展,SLAM将在未来发挥更加重要的作用。通过解决实际应用中的挑战,并利用新的技术和算法,SLAM将继续推动智能系统的发展。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 深度学习损失计算
  • SpringBoot使用开发环境的application.properties
  • go语言 fmt的几个打印区别以及打印格式
  • Linux内核启用 bridge 模块
  • UPFC统一潮流控制器的simulink建模与仿真
  • React、Vue的password输入框组件,如何关闭自动填充?
  • Go 语言中的互斥锁 Mutex
  • ARFoundation系列讲解 - 91 Immersal 简介
  • 独角数卡(自动发卡系统)开源自动化售货最新2.0.6
  • 【UE5.1】NPC人工智能——02 NPC移动到指定位置
  • 高性能存储 SIG 月度动态:优化 xfs dax reflink 时延,独立选型并维护 mdadm 和 ledmon
  • gradle学习及问题
  • 【Unity学习笔记】第十九 · 物理引擎约束求解解惑(LCP,最优,拉格朗日乘数法,SI,PGS,基于冲量法)
  • docker-cli nerdctl ctr crictl容器命令比较
  • 基于jeecgboot-vue3的Flowable流程支持bpmn流程设计器与仿钉钉流程设计器-编辑多版本处理
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • 《剑指offer》分解让复杂问题更简单
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • Angular 2 DI - IoC DI - 1
  • CentOS 7 修改主机名
  • css系列之关于字体的事
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • IP路由与转发
  • mysql中InnoDB引擎中页的概念
  • PAT A1120
  • vue-cli3搭建项目
  • 百度小程序遇到的问题
  • 微服务核心架构梳理
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • Java总结 - String - 这篇请使劲喷我
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​香农与信息论三大定律
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #QT项目实战(天气预报)
  • $(this) 和 this 关键字在 jQuery 中有何不同?
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (2015)JS ES6 必知的十个 特性
  • (9)目标检测_SSD的原理
  • (Charles)如何抓取手机http的报文
  • (八十八)VFL语言初步 - 实现布局
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (推荐)叮当——中文语音对话机器人
  • (转载)CentOS查看系统信息|CentOS查看命令
  • (轉貼) 寄發紅帖基本原則(教育部禮儀司頒布) (雜項)
  • .apk 成为历史!
  • .bat批处理(一):@echo off
  • .NET 4.0中的泛型协变和反变
  • .py文件应该怎样打开?
  • /proc/vmstat 详解
  • :“Failed to access IIS metabase”解决方法
  • @在php中起什么作用?
  • [<死锁专题>]
  • [Angular 基础] - 表单:响应式表单