ORB-SLAM2跑自定义图片序列:从数据准备到轨迹评估

简介:面向视觉SLAM入门者与需要跑通自定义数据集的开发者,这套实操资源围绕ORB SLAM2,解决如何将自拍视频或图像序列整理成系统要求的输入格式,进而完成定位与建图,适用于机器人、无人机或AR场景。整个压缩包共4个文件,大小约4.38MB,包含两个Python脚本(用于视频拆帧与rgb.txt生成)、一段示例视频和一个rgb.txt示例,覆盖从原始视频到ORB SLAM2输入文件的完整链路;其中rgb.txt按‘图片路径 时间戳’格式记录每一帧,是系统顺序读取图像的关键。目前该资源已有5381人学习,适合作为自定义数据集上手的起步参考。借助示例与脚本,读者可快速掌握图片命名与时间戳写法,理解rgb.txt格式要求,并据此修改ORB SLAM2的yaml配置参数,在自己采集的场景中跑通初始化、跟踪、关键帧选择与稀疏建图,获得轨迹和点云结果。

1. ORB-SLAM2跑自己的图片序列:先别急着把视频怼进去

如果你第一次接触ORB SLAM2,最容易踩的动作是:拿手机拍一段视频,然后想着用ORB SLAM2直接把这段视频变成相机轨迹。等真动手才发现,ORB-SLAM2根本不吃视频流,它只接受“图片序列数据集”——一张一张按时序排好的图片,外加一份相机内参文件和一份时间戳。这个反直觉的点劝退过不少人,其实把它整明白了,剩下的事就是在数据组织和参数调试上花时间。这篇笔记我会从数据准备讲到轨迹评估,把跑通自家图片序列的完整路径拆开,适合准备在自定义场景里做视觉SLAM建图、或者在数据集上复现代码的开发者。

2. 数据准备:目录、时间戳、内参一个都不能少

2.1 目录结构:每个图片都是关键帧的候选样本

ORB-SLAM2读取序列的方式比很多人想得简单:它按目录顺序逐张读取图片,目录顺序就是时间顺序。所以你的目录里只要有一堆按序命名的图片文件就行,甚至不要求文件名连续,只要能被排序。实际跑之前我会先确认几件事:

  • 图片格式统一,建议全部转成.png或.jpg,不要混着来;
  • 同一序列的图像尺寸完全一致,不然内参没法用一个;
  • 单目SLAM初始化需要两帧之间有足够视差,所以采集时要让相机有平移或旋转,别对着静止场景发呆。

目录结构我一般这样组织:

my_data/ ├── images/ │ ├── 000000.png │ ├── 000001.png │ ├── 000002.png │ └── ... ├── timestamps.txt └── my_cam.yaml

images/放图片序列,timestamps.txt记录每张图片的时间戳,my_cam.yaml是相机内参。三个文件各管一件事,后面评估轨迹时都会用到。

2.2 生成时间戳:按帧率给图片建一个虚拟时钟

ORB-SLAM2的定位过程不依赖时间戳,它需要时间戳的地方主要在轨迹评估和多传感器同步上。这里有个常见的认知误区:时间戳不影响能不能跑通,但影响评估结果准不准。如果你手里没有硬件时钟,就用帧率去模拟。

import os fps = 30.0 # 采集帧率,改成你实际用的 start_ts = 1477059600.0 # 随便取一个起点,表示采集开始时刻 image_dir = "my_data/images" image_count = len(os.listdir(image_dir)) with open("my_data/timestamps.txt", "w") as f: for i in range(image_count): ts = start_ts + i / fps f.write(f"{ts:.6f}\n")

这段代码的核心是start_ts + i / fps:第 i 张图的时间戳等于起点加上 i 除以帧率,单位是秒。输出保留 6 位小数,精度足够大多数SLAM评估工具使用。如果你是从视频抽帧得到的图片,更合理的做法是直接用video_timestamp + frame_id / video_fps,这样的时间间隔更真实。

有一点要注意:如果图片来自带硬件时间戳的采集设备,比如某些相机同时输出图片和陀螺仪数据,那就优先用硬件时间戳,因为帧率模拟的时钟在长时间序列里会有累积误差。

2.3 相机内参:fx、fy、cx、cy 究竟从哪来

内参是整个序列能不能跑出可信轨迹的“地基”。ORB-SLAM2靠相机内参把像素坐标换算到相机坐标系,再估计位姿。内参错了,轨迹不一定崩,但会出现一种让人很头疼的“软漂移”——轨迹看起来在动,跟真实路线对不上。

拿一个常见的640x480图像来说,yaml内参配置大概长这样:

%YAML:1.0 Camera.fx: 528.49 Camera.fy: 528.49 Camera.cx: 320.5 Camera.cy: 240.5 Camera.fps: 30.0 Camera.k1: 0.0 Camera.k2: 0.0 Camera.p1: 0.0 Camera.p2: 0.0

fx和fy是焦距(单位是像素),cx、cy是主点坐标,通常接近图像中心的整数或半整数。k1、k2、p1、p2是畸变系数,如果直接用的普通摄像头没做标定,可以先置零,但轨迹精度会受一些影响。Camera.fps最好跟实际采集帧率一致,我见过差值过大的配置导致关键帧插入频率异常,轨迹上会出现密集的抖动点。

内参来源有三条路:一是查官方相机参数表,二是用棋盘格跑一遍标定,三是用同分辨率下别人标定过的近似值。前两种最可靠,第三种只能拿来先跑通流程,不能在精度敏感的场景下直接信。

2.4 一条 Python 命令完成数据包整理

上面三块都准备好后,我会用一段小脚本把整个数据集整理到一起,顺带生成一个最小的 yaml 骨架,改改参数就能用:

import os, yaml image_dir = "my_data/images" fps = 30.0 start_ts = 1477059600.0 # 统一图片命名,按采集顺序从 0 开始 for i, fname in enumerate(sorted(os.listdir(image_dir))): ext = fname.split(".")[-1] os.rename(os.path.join(image_dir, fname), os.path.join(image_dir, f"{i:06d}.{ext}")) # 生成时间戳 with open("my_data/timestamps.txt", "w") as f: for i in range(len(os.listdir(image_dir))): f.write(f"{start_ts + i / fps:.6f}\n") # 生成内参 yaml 骨架 camera = { "Camera.fx": 528.49, "Camera.fy": 528.49, "Camera.cx": 320.5, "Camera.cy": 240.5, "Camera.fps": fps, "Camera.k1": 0.0, "Camera.k2": 0.0, "Camera.p1": 0.0, "Camera.p2": 0.0, } with open("my_data/my_cam.yaml", "w") as f: f.write("%YAML:1.0\n") yaml.dump(camera, f)

这个脚本把三个文件一口气生成完,省去手工整理的繁琐。参数都在文件开头,下次换数据集只需要改image_dir和fps。注意yaml.dump输出的键之间可能有空行,ORB-SLAM2的yaml解析器一般不受影响,但如果后面报解析错误,就把yaml.dump(..., default_flow_style=False)改成显式逐行写入。

3. 编译与配置:从依赖安装到修改示例程序

3.1 依赖清单:OpenCV、Eigen3、Pangolin、g2o、DBoW2 缺一不可

ORB-SLAM2的依赖不算少,但固定,装一次就能复用。常见依赖和版本建议我整理成了一张表:

依赖库用途版本建议
OpenCV图像读取、特征提取3.x 或 4.x 都行,注意源码接口变化
Eigen3矩阵运算3.3 以上
Pangolin可视化、轨迹显示0.6 以内,新版接口变化较大
g2o图优化后端源码构建,随 ORB-SLAM2 一起编译
DBoW2词袋回环检测源码构建,同样随主项目编译

经验上最容易出问题的组合是 OpenCV 4.x 配旧版 g2o,会出现函数签名不匹配。我一般选择源码编译 g2o 和 DBoW2,而不是用系统包管理安装,这样版本可控。Pangolin 如果版本太新,运行时可能在高分屏下黑屏,先试试 0.6 左右的分支比较稳。

3.2 编译三步走:build.sh 在做什么

ORB-SLAM2 仓库里自带build.sh,真正的构建核心就三步:编译 Thirdparty 里的 DBoW2,编译 g2o,最后编译主工程。命令行如下:

cd ORB_SLAM2 chmod +x build.sh ./build.sh

build.sh内部会把 DBoW2 和 g2o 的build目录建好并执行cmake ../和make,如果这些第三方库已经单独编译过,重跑脚本也只会重新编译主工程。首次编译时间比较长,建议用make -j4或-j8加速,但同时在机器上跑编译会导致内存吃紧,墙内小内存机器建议先-j2试跑一次。

如果你不想用脚本,手动执行也一样:

cd Thirdparty/DBoW2 mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make cd ../../g2o mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make cd ../../../build cmake .. -DCMAKE_BUILD_TYPE=Release make

注意这里统一用了Release模式,调试信息少但速度提升明显。SLAM 是实时性敏感的任务,Release 是唯一合理的选择。如果cmake阶段报找不到 OpenCV,多半是 OpenCV 装到了非标准路径,可以在cmake后面加-DOpenCV_DIR=/path/to/opencv指定。

3.3 修改示例程序:把 KITTI 路径换成你的序列路径

编译完成后,ORB-SLAM2 自带的示例程序带的是 KITTI 数据集的参数和路径。直接跑自己的序列前,需要改一下源码里的路径拼接逻辑。以单目示例mono_kitti.cc为例,核心代码一般长这样:

int main(int argc, char **argv) { if(argc != 4) { cerr << endl << "Usage: ./mono_kitti path_to_vocabulary path_to_settings path_to_sequence" << endl; return 1; } // 创建单目 SLAM 系统,最后一个参数表示开启可视化 ORB_SLAM2::System SLAM(argv[1], argv[2], ORB_SLAM2::System::MONOCULAR, true); // 读取序列路径,这个目录下不能有子目录,必须直接是图片文件 string sequencePath = string(argv[3]); ... // 循环读取图片,逐张送入 SLAM 系统 for (int i = start; i < end; i++) { cv::Mat im = cv::imread(sequencePath + "/" + to_string(i) + ".png", cv::IMREAD_UNCHANGED); SLAM.TrackMonocular(im, timestamp[i]); } }

很多人在这一步直接把sequencePath写死成 KITTI 的绝对路径,我的习惯是不动源码逻辑,只把命令行参数传成自己的目录,这样换数据集不用改代码重编译。如果你的图片命名不是连续数字,比如带日期前缀,就把读取循环里拼文件名的部分改成directory iterator按排序后的文件名读取。图片扩展名也必须在源码里对应好,中间差一个.jpg和.png的不一致,运行时会立刻报读取失败。

4. 跑通第一个序列:单目起步,再切换双目与深度

4.1 单目模式:一条命令跑起来

准备就绪后,第一次跑通推荐用单目模式,因为数据要求最低,只要一台普通相机拍的图片序列就能验证整个链路。命令行如下:

./Examples/Monocular/mono_kitti \ ./Vocabulary/ORBvoc.txt \ ./my_data/my_cam.yaml \ ./my_data/images

三个参数分别是词袋文件、相机内参 yaml、图片目录。ORBvoc.txt是 ORB-SLAM2 预训练好的词袋,所有模式通用,路径不要写错。运行后终端会弹出可视化窗口,显示当前帧的跟踪点和相机轨迹。如果画面里绿色特征点足够多,轨迹圆点逐渐画出来,说明单目流程已经通了。

单目模式有个特点:尺度不确定。轨迹的绝对尺度没法从纯视觉估计出来,所以轨迹看起来会“缩放”,这是单目的通病,不是配置问题。如果后续需要真实尺度,需要引入双目、深度相机,或者事后用地面真值对齐尺度。

4.2 双目与深度模式:时间戳同步才是真正的门槛

从单目切到双目或深度模式,数据准备的成本立刻高了不少。双目要两个相机同步曝光,深度要 depth 图和 rgb 图对齐。ORB-SLAM2 的双目示例stereo_kitti.cc读取每一帧的彩色图、深度图和对应的左右目图,时间戳要求更严格。

./Examples/Stereo/stereo_kitti \ ./Vocabulary/ORBvoc.txt \ ./my_data/stereo_cam.yaml \ ./my_data/sequences/00

双目的 yaml 里需要额外配置Camera.bf,这是基线长度乘以焦距的值,决定深度估计的尺度。深度模式同理,在rgbd_tum.cc里需要提供 RGB 图与深度图的目录,并且两张图的名字要严格对应。同步时间戳是我踩坑最多的地方:如果 RGB 图目录和深度图目录用不同帧率采集,比如 RGB 30fps、深度 15fps,直接喂给 ORB-SLAM2 会频繁报“找不到对应深度图”,轨迹在深度细节处呈现断崖式跳跃。解决办法是先把两路数据按时间戳最近邻对齐,生成同步索引再喂进去。

4.3 RGB 转灰度:特征点数量变化很明显

ORB 特征点提取是在灰度图像上做的。如果你的图片本身是 RGB,ORB-SLAM2 内部会调用cvtColor转灰度,这步默认没问题。但如果你从原始采集设备拿到的图像是 RGB 且带色彩矫正、白平衡等增强,转灰度后灰度分布会被拉偏,特征点数量和质量都可能明显下降。对比一下就会发现,同样一个场景,原图直接送进去能跟踪 2000 个点,先做一次均一化灰度变换可能只剩 1400 个。

我的习惯是拿到任何序列后先统一转成灰度图再送进去,这样中间的色彩处理完全可控:

import cv2, os, glob image_files = sorted(glob.glob("my_data/images/*.png")) for idx, fpath in enumerate(image_files): img = cv2.imread(fpath, cv2.IMREAD_GRAYSCALE) cv2.imwrite(f"my_data/gray/{idx:06d}.png", img)

转灰度后文件占空间更小,读取更快,ORB-SLAM2 内部就少做一次色彩转换,少一点不确定因素。如果你用的相机输出本身是灰度流,就完全不用这步。

5. 常见问题排查:五个最容易翻车的现场

5.1 启动即崩:找不到图片或扩展名不统一

现象:运行后窗口一闪而过,终端报Failed to load image at ...或者corrupted size vs. prev_size。

原因:最常见的是序列目录里的图片命名规则跟源码里to_string(i) + ".png"这种拼法对不上,比如图片实际是.jpg,或者命名从 1 开始而你源码里start=0。其次是目录路径写到了images/的上一级,源码拼接后路径里出现了双斜杠,某些系统解释没问题,但 ORB-SLAM2 里的cv::imread对这种路径返回空矩阵。

解决:先用ls确认图片目录内容,确保图片是纯文件没有子目录;再把源码里的扩展名改成跟实际文件一致。最稳妥的做法是用脚本先把全部图片重命名成000000.png这类连续编号,避免扩展名和起始序号双坑。

5.2 轨迹漂移成迷宫:内参错误或帧率乱

现象:程序不崩,但跑出来的轨迹完全对不上真实路径,或者出现成片的“锯齿”形抖动。

原因:内参fx/fy严重偏离真实值时,ORB 特征点地图会被整体拉伸,位姿估计看起来像在乱走。另一个常见原因是Camera.fps与实际帧率差太远,关键帧插入频率紊乱,轨迹上出现密集的不连续转折点。

解决:回到第 2 章,先核对内参来源。临时拿不到标定参数时,可以先用图像宽高和视场角近似估算fx = width / (2 * tan(fov/2)),至少让量级对得上。fps也改成实际采集帧率,重新生成时间戳再跑一遍。这类问题表现出的“软漂移”很有欺骗性,排查优先级高于优化参数。

5.3 初始化失败:画面静止或特征点太少

现象:运行时窗口显示在读取图片,但一直不进入跟踪状态,后面轨迹起不来,或者报Not enough features。

原因:单目初始化需要两张图之间有足够的视差和足够的匹配点。如果采集时相机保持静止,或者场景是白墙、空旷路面这种纹理稀少的区域,ORB 提取的特征点数量太少,匹配对数不达标就会一直卡初始化。

解决:采集时让相机缓慢移动,保证画面有平移分量,同时找有纹理的区域,比如椅子腿、开关面板、树边。如果场景实在单调,可以调小 ORB 特征提取器的阈值,让低对比度区域也能提取到点,但要注意特征点质量下降会带来跟踪抖动。

5.4 用 evo 评估时轨迹对不齐:时间戳单位不一致

现象:评估工具报Found no matching timestamps,或者画出来的轨迹曲线错位严重。

原因:ORB-SLAM2 输出的时间戳单位是秒,但有些评估工具要求纳秒,比如 TUM 格式。如果你生成时间戳时用了秒,而评估脚本或 ground truth 用的是纳秒,时间轴就差了 9 个数量级,匹配窗口内找不到对应点。

解决:写脚本时统一成一种单位,我一般统一用秒,并在转换轨迹文件时保持跟 ground truth 相同。如果工具要求纳秒,把时间戳乘以1e9再转成整数输出,水到渠成。

5.5 加载完词汇库后卡死:内存不足或线程抢满

现象:程序启动后能打印Vocabulary loaded!,但紧接着像卡住了一样,界面迟迟不出现,或者 CPU 占满但画面冻结。

原因:ORB-SLAM2 的ORBvoc.txt词袋文件比较大,加载时很吃内存。低内存机器在加载后紧接着跑特征提取,可能长时间 GC 停顿或进程被系统 OOM 打掉。另一个原因是本地开了太多后台任务,8 核机器被别的进程占到只剩零星资源,而 SLAM 本身会默认起满所有线程。

解决:先看看词袋文件大小,通常六百兆级别。内存少于 8G 的话,关掉可视化窗口能省不少开销,启动时把System构造函数最后一个true改成false。同时跑top确认 CPU 占用,避免和其他重型任务同时抢。

6. 验证与进阶:轨迹可视化与评估一体化

6.1 轨迹文件转 TUM 格式

跑完一整个序列后,ORB-SLAM2 会输出KeyFrameTrajectory.txt,每行 8 个数:时间戳、xyz、四元数。这个格式很多评估工具不认识,要转成标准的 TUM 轨迹格式再去跟 ground truth 对比。转法很简单:

with open("KeyFrameTrajectory.txt") as f_raw, \ open("trajectory_tum.txt", "w") as f_out: for line in f_raw: parts = line.strip().split() if len(parts) != 8: continue # TUM 格式也是 8 列:时间 ts, x y z, qx qy qz qw f_out.write(" ".join(parts) + "\n")

这段代码只是把空白分隔符归一化一遍,不重排数据。因为 ORB-SLAM2 输出的关键帧轨迹并不是等间距时间戳,TUM 格式的要求是“每行代表一个位姿”,中间少几帧没关系。如果你想要帧级轨迹而不是关键帧轨迹,用frame_trajectory.txt输出文件,行数会多几倍。

6.2 用 evo 做 APE 和 RPE 评估

轨迹验证我常用evo工具包,它支持 TUM 格式直接画图和算误差。命令组合如下:

evo_ape tum ground_truth_tum.txt trajectory_tum.txt -a -va --plot

这里有三个关键参数:

  • -a:做绝对位姿对齐,单目轨迹要先对齐尺度再算误差,不然 APE 会被尺度漂移拉爆;
  • -va:逐帧打印两者的位姿误差分布;
  • --plot:把误差曲线画出来,一眼看出哪段轨迹漂移最大。

如果想看轨迹上的稳定性,用evo_rpe代替evo_ape,RPE 算的是帧间相对位姿误差,对回环优化好坏更敏感。实际使用顺序是先跑 APE 看全局偏差,再跑 RPE 定位具体出问题的区段,然后再回头改采集方式或相机参数。

这一步我吃过亏:第一次拿到像模像样的轨迹时,直接以为成功了,后来用 APE 一算 RMSE 有 0.8 米,整个轨迹被放大了一圈。从那以后,我每次跑自己的图片序列都会强制走一遍“原图转灰度、时间戳按秒统一、轨迹转 TUM、先用 evo 算一次 APE”这四步,再开始调参数。数据准备多花十分钟,后面少走一整晚弯路,这套流程希望帮到你。

本文还有配套的精品资源,点击获取

相关新闻

Qoder与Trae对比:AI编程工具的上下文、知识注入与错误修复深度解析

Qoder与Trae对比:AI编程工具的上下文、知识注入与错误修复深度解析

1. 这场“国产AI编程工具对决”根本不是选边站队&#xff0c;而是重新定义你的开发工作流最近在几个技术群和社区里&#xff0c;总能看到类似“Qoder和Trae到底哪个强”的讨论&#xff0c;标题里还带着“巅峰对决”“程序员必看”这种字眼。说实话&#xff0c;我第一次看到时心…

2026/10/20 2:33:33 阅读更多 →
DQN原理与PyTorch实现:从Q-Learning到经验回放+目标网络

DQN原理与PyTorch实现:从Q-Learning到经验回放+目标网络

很多学习强化学习的读者&#xff0c;在接触 DQN 之前&#xff0c;多半已经能用 Q-Learning 在一个小网格、迷宫或者简单的表格环境里跑通一个 Agent。那一刻你会觉得&#xff1a;强化学习好像也没那么复杂&#xff0c;更新公式背下来&#xff0c;迭代几百轮&#xff0c;Q 表收敛…

2026/10/20 2:33:33 阅读更多 →
胡广书《数字信号处理》Matlab实战代码包解析

胡广书《数字信号处理》Matlab实战代码包解析

简介&#xff1a;本资源是胡广书《数字信号处理理论、算法与实现》&#xff08;清华大学出版社&#xff0c;2003年&#xff09;配套的完整MATLAB实践支撑包&#xff0c;面向高校电子、通信、自动化等专业本科生及研究生&#xff0c;助力理解经典DSP核心概念与算法实现。压缩包含…

2026/10/20 2:32:33 阅读更多 →

最新新闻

STM32 bxCAN实战:从物理层到过滤器配置与调试排障

STM32 bxCAN实战:从物理层到过滤器配置与调试排障

做嵌入式这几年&#xff0c;UART、I2C、SPI都是老朋友&#xff0c;但真正让我觉得“像个通信工程师”的&#xff0c;是开始啃STM32的CAN外设之后。原因很简单&#xff1a;在汽车、机器人和工业现场&#xff0c;CAN总线是默认的“老大哥”&#xff0c;而它在微控制器上的硬件实现…

2026/10/20 6:26:33 阅读更多 →
ReST-MCTS精读:用蒙特卡洛树搜索与过程奖励实现LLM自我训练

ReST-MCTS精读:用蒙特卡洛树搜索与过程奖励实现LLM自我训练

这篇是论文精读系列的第九期。选题的时候我特意挑了一个既讲方法、又讲工程的文章&#xff1a;ReST-MCTS&#xff0c;标题直译过来就是“基于过程奖励引导的树搜索做LLM自我训练”。一句话概括它的核心思想&#xff1a;让大模型不要只想着“快答”&#xff0c;而是像下棋一样&a…

2026/10/20 6:26:33 阅读更多 →
实测,ToClaw为什么是最优秀的OpenClaw龙虾:从 ToDesk 远程到 TaoToken 统一 Key 的配置复盘

实测,ToClaw为什么是最优秀的OpenClaw龙虾:从 ToDesk 远程到 TaoToken 统一 Key 的配置复盘

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 6:26:33 阅读更多 →
diagram-design:从图形类型到布局配色的技术图设计指南

diagram-design:从图形类型到布局配色的技术图设计指南

1. 从"diagram-design"这个标题说起&#xff1a;它到底在解决什么问题第一次看到"diagram-design"这个标题&#xff0c;我脑子里冒出来的第一个念头是&#xff1a;这大概率不是一个单纯的"画图工具"&#xff0c;而是一套关于"如何把复杂信息…

2026/10/20 6:26:33 阅读更多 →
CTF Misc入门:DOCX隐写与ZIP伪加密的底层原理及010 Editor实操

CTF Misc入门:DOCX隐写与ZIP伪加密的底层原理及010 Editor实操

CTF新手村常客——Misc题型里的DOCX隐写和伪加密&#xff0c;对很多刚入坑的朋友来说&#xff0c;看WriteUp觉得挺简单&#xff0c;真上手时又容易卡壳。我最初玩PolarCTF这类靶场时也是这样&#xff0c;面对一个打不开的docx文件&#xff0c;第一反应是直接改后缀名丢进解压工…

2026/10/20 6:26:33 阅读更多 →
HTTP POST表单提交全解析:Content-Type、编码格式与实战避坑指南

HTTP POST表单提交全解析:Content-Type、编码格式与实战避坑指南

1. 从一个被忽略的细节说起&#xff1a;为什么表单提交远不止填个action很多人第一次接触Web开发&#xff0c;接触到的第一个"能跑起来"的功能&#xff0c;大概率就是一个HTML表单。写一个<form>标签&#xff0c;配上action和method"post"&#xff0…

2026/10/20 6:25:32 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →