02-八种元素定位方法

一、前言

        自动化测试过程主要包含四步操作:获取元素(定位元素)、操作元素、获取返回结果、断言(返回结果与期望结果是否一致),最后自动生成测试报告。

        元素定位在这四个环节中是至关重要的,如果说按学习精力分配的话,元素定位占70%、操作元素占10%、获取返回结果占10%、断言占10%。如果一个页面上的元素不能被定位到,那后续的操作就无法进行了,接下来就来介绍WebDriver提供的八种元素定位方法。

        以百度网页的搜索框为例:<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">

二、id

        1)百度网页的搜索框有个id属性:id="kw",因此可以使用WebDriver的API根据id属性定位到该元素。

        2)定位到搜索框后,可以使用send_keys()方法,向搜索框中输入内容。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.baidu.com')

# 通过id定位到搜索框,并输入内容
driver.find_element('id', 'kw').send_keys('selenium')

三、name

        百度网页的搜索框有个name属性:name="wd",因此可以使用WebDriver的API根据name属性定位到该元素。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.baidu.com')

# 通过name定位到搜索框,并输入内容
driver.find_element('name', 'wd').send_keys('selenium')

        说明:根据元素的name属性进行定位,前提是该元素有name属性。如果在页面中该元素的name属性值是唯一的,那么可以准确的定位到该元素;如果不是唯一的,则默认返回第一个定位到的元素。

四、class name

        百度网页的搜索框有个class属性:class="s_ipt",因此可以使用WebDriver的API根据class属性定位到该元素。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.baidu.com')

# 通过class定位到搜索框,并输入内容
driver.find_element('class name', 's_ipt').send_keys('selenium')

        说明:根据元素的class属性进行定位,前提是该元素有class属性。如果在页面中该元素的class属性值是单一样式的,比如:class='s_ipt',那么可以使用class name对该元素进行定位;如果是复合样式的,比如:class='s_ipt  border',那么不可以使用class name对该元素进行定位。

五、tag name

        网页中的所有元素都有tag(标签)属性,比如搜索框的tag属性就是最前面的input标签。很明显,在一个页面中,相同的标签有很多,所以一般不用tag属性来进行定位。以下例子,仅供参考和理解。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.baidu.com')

# 通过tag name定位元素
elements = driver.find_elements('tag name', 'input')
print(len(elements))

六、link text

        link text和partial link text专门用于定位超链接(标签是<a></a>)元素,使用link text进行定位时,只能使用<a></a>标签内的全部文本内容进行精准匹配。

        以百度网页的hao123为例:<a href="https://www.hao123.com?src=from_pc" target="_blank" class="mnav c-font-normal c-color-t">hao123</a>

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.baidu.com')

# 通过link text定位超链接元素
driver.find_element('link text', 'hao123').click()

七、partial link text

        使用partial link text进行定位时,可以使用<a></a>标签内的部分文本内容进行模糊匹配。模糊匹配时,最好使用在页面中唯一存在的关键字;如果有多个元素符合条件,则默认返回第一个定位到的元素。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.baidu.com')

# 通过partial link text定位超链接元素
driver.find_element('partial link text', 'hao12').click()

八、xpath

        以上定位方式都是通过元素的某个属性来进行定位的,如果一个元素它既没有id、name、class属性,也不是超链接,那该怎么办呢?或者说在一个页面中,该元素的属性值有很多重复时,该怎么进行定位呢?这个时候就可以用xpath来解决,xpath既可以通过元素的任意属性来定位,又可以通过元素的位置来定位。

        xpath是XML路径语言,通俗一点讲就是通过元素的所在位置来定位到该元素,相当于是通过元素的坐标来进行定位的。以下例子,只是简单介绍xpath定位元素的过程,在下一篇文章中将会对xpath进行详细介绍。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.baidu.com')

# 使用xpath根据位置进行定位
driver.find_element('xpath', "//*[@id='form']/span[1]/input").send_keys('python')

九、css selector

        大部分人在使用selenium定位元素时,都是使用xpath进行定位,因为xpath基本能够解决定位元素的需求。css selector定位往往被忽略掉了,其实css selector定位也有它的价值,css selector定位更快、性能更高、语法更简洁。css selector也能通过元素的任意属性来定位,又能通过元素的位置来定位。以下例子,只是简单介绍css selector定位元素的过程,在后续文章中将会对css selector进行详细介绍。

from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://baidu.com")

# 使用css selector根据位置进行定位
driver.find_element('css selector', "form#form>span:nth-child(1)>input").send_keys('python')

十、总结

1)元素定位方式的选择
  • 当页面元素有id属性时,优先使用id属性来定位,其次是name属性。
  • xpath功能很强大,但定位性能不是很好,当其他定位方法不好用时,可以使用xpath解决。
  • 定位一组相同元素时,可以考虑使用name属性或者tag name。
  • 定位超链接时,可以考虑使用link text或者partial link text。
2)定位元素的注意事项
  • 找到待定位元素的唯一属性。
  • 如果该元素没有唯一属性,则先找到能够被唯一定位到的父元素,再使用xpath或者css selector进行基于位置的定位。
  • 如果待定位元素的唯一属性是动态变化的,最好是不要用该属性进行定位。
  • 最重要的是多和研发人员沟通,尽量把关键元素的id或name属性加上,并减少不合理的页面元素,比如:重复id这样的事情最好不要发生。
一字不落重复以下内容:以下是根据你提供的 Python 代码撰写的 **完整技术文档**,适用于项目说明、团队协作或学术报告场景。该文档详细解释了程序的功能、架构、使用方法和关键算法逻辑。 --- # 📄 COLMAP 轨迹重建与真值误差评估系统 ## —— 基于视频输入的多相机轨迹分析工具 > **版本**: v1.0 > **作者**: [你的名字] > **语言**: Python + COLMAP/GloMap + FFmpeg > **用途**: 自动化运行 SLAM/SfM 流程,并对重建轨迹进行定量精度评估 --- ## 🔍 一、功能概述 本工具旨在从一组多视角视频中自动提取图像帧,使用 **COLMAP(或 GloMap)** 进行稀疏三维重建,解析相机位姿轨迹,并与给定的 **Ground Truth (GT) 相机轨迹 JSON 文件**进行对比,计算旋转和平移误差。 ### ✅ 主要功能: - 视频帧提取(支持多种格式) - 自动调用 COLMAP 完成特征提取、匹配与稀疏建图 - 解析 COLMAP 输出的 `images.txt` 中的相机位姿 - 解析外部 GT JSON 文件中的真值轨迹 - 将绝对位姿转换为相对位姿(以第一帧为参考) - 应用尺度对齐后计算平均旋转误差和 ATE(绝对轨迹误差) - 可选:3D 轨迹可视化(需 matplotlib) - 结果汇总输出至 CSV 表格 --- ## 🧱 二、系统结构与流程 ```text 输入: ├── 多个摄像头子文件夹 (cam01/, cam02/, ...) │ └── 各自包含一个视频文件 (.mp4/.avi等) └── Ground Truth JSON 文件 (含各相机 c2w 矩阵) 处理流程: 1. 遍历每个摄像头目录 2. 提取视频帧 → images/ 3. 运行 COLMAP pipeline: a. 特征提取 b. 特征匹配 c. 稀疏重建 (mapper) d. 模型导出为 TXT 格式 4. 解析 COLMAP 的 images.txt 获取 c2w 位姿 5. 解析 GT JSON 获取对应相机的真值位姿 6. 统一时间对齐并转为相对轨迹 7. 计算尺度因子并缩放生成轨迹 8. 计算旋转 & 平移误差 9. 可视化(可选) 10. 汇总结果保存为 CSV ``` --- ## 📂 三、输入数据格式要求 ### 1. 视频文件组织结构 ```bash videos_root/ ├── cam01/ │ └── video.mp4 ├── cam02/ │ └── clip.avi ├── ... ``` > 支持扩展名:`.mp4`, `.avi`, `.mov`, `.mkv` 每台相机一个独立文件夹,命名如 `cam01`, `cam02`... 工具会自动识别这些名称并与 GT 文件匹配。 --- ### 2. Ground Truth JSON 文件格式 ```json { "frame0": { "cam01": "[r00 r01 r02 t0] [r10 r11 r12 t1] [r20 r21 r22 t2]", "cam02": "[...] [...]" }, "frame1": { "cam01": "...", "cam02": "..." }, ... } ``` - 每个 `"frame{N}"` 对应第 N 帧。 - 每个 `"camXX"` 键对应一台相机。 - 值是一个字符串形式的 3×4 或 4×4 矩阵(列优先存储),例如 `[1 0 0 0] [0 -1 0 0] [0 0 -1 2]`。 - 在代码中会自动转置并作为 `c2w` 使用。 > ⚠️ 注意:矩阵是原始存储格式,脚本内部会做 `.T` 转置处理。 --- ## 🛠 四、核心模块详解 ### 1. `parse_colmap_images(file_path)` **作用**:读取 COLMAP 的 `images.txt` 文件,提取每张图像对应的相机位姿。 #### 输入- `file_path`: COLMAP 输出的 `images.txt` 路径 #### 输出: - `R_gen_abs`: 所有帧的旋转矩阵数组 `(N, 3, 3)` —— c2w 形式 - `T_gen_abs`: 所有帧的平移向量数组 `(N, 3)` —— c2w 形式 #### 关键步骤: 1. 读取每一偶数行(COLMAP 中描述图像信息的行) 2. 解析四元数 `qw qx qy qz` 和平移 `tx ty tz` 3. 构造 w2c 旋转矩阵 $ R_{w2c} $ 4. 转换为 c2w: $ R_{c2w} = R_{w2c}^T $ $ T_{c2w} = -R_{w2c}^T \cdot T_{w2c} $ > ❗ 不再应用额外坐标系变换(如 OpenCV ←→ OpenGL) --- ### 2. `parse_ground_truth(json_path, cam_type)` **作用**:从 JSON 文件中加载指定相机类型的真值轨迹。 #### 步骤: 1. 加载 JSON 数据 2. 查找所有 `frame{N}` 下的 `camXX` 条目 3. 使用 `parse_matrix_from_gt_str()` 解析 `[r r r t]` 字符串为 4×4 数组 4. 转置得到 c2w 矩阵(符合 COLMAP 存储习惯) 5. 分离出 `R_gt_abs` 和 `T_gt_abs` --- ### 3. `convert_to_relative_poses(R_abs, T_abs)` **作用**:将全局 c2w 位姿转换为相对于第一帧的相对位姿(即 $ T_{c0}^{ci} $) #### 公式推导: 设第一帧的位姿为 $ T_w^{c0} = [R_0 | T_0] $,则其逆为: $$ T_{c0}^w = \begin{bmatrix} R_0^T & -R_0^T T_0 \\ 0 & 1 \end{bmatrix} $$ 当前帧 $ i $ 的相对位姿为: $$ T_{c0}^{ci} = T_{c0}^w \cdot T_w^{ci} \Rightarrow \begin{cases} R_{rel} = R_0^T R_i \\ T_{rel} = R_0^T (T_i - T_0) \end{cases} $$ > 实际实现中使用:`T_rel_i = R0_inv @ Ti + T0_inv`,其中 `T0_inv = -R0.T @ T0` --- ### 4. `calculate_relative_errors_with_scale_alignment(...)` **作用**:在尺度对齐后比较两条相对轨迹之间的误差。 #### 步骤: 1. **计算尺度因子**: $$ s = \frac{\text{GT 总路径长度}}{\text{COLMAP 总路径长度}}, \quad \text{length} = \sum \| \Delta T \| $$ 2. **对 COLMAP 平移轨迹缩放**: $$ T_{gen\_scaled} = s \cdot T_{gen} $$ 3. **计算平移 RMSE(ATE)**: $$ \text{ATE}_{trans} = \frac{1}{N} \sum_{i=1}^{N} \| T_{gt,i} - T_{gen\_scaled,i} \| $$ 4. **计算平均旋转误差(单位:度)**: 对每个相对旋转误差矩阵 $ R_{err} = R_{gt} R_{gen}^T $: $$ \theta = \arccos\left( \frac{\mathrm{tr}(R_{err}) - 1}{2} \right), \quad \text{mean\_rot\_deg} = \frac{1}{N} \sum \theta_i \times \frac{180}{\pi} $$ > ✅ 优势:通过尺度对齐解决 SfM 缺乏真实尺度的问题。 --- ### 5. `run_colmap_pipeline(data_dir)` **作用**:端到端执行 COLMAP SfM 流程。 #### 包括四个阶段: | 阶段 | 命令 | |------|------| | 1. 特征提取 | `colmap feature_extractor --use_gpu 1` | | 2. 特征匹配 | `colmap exhaustive_matcher --use_gpu 1` | | 3. 稀疏建图 | `glomap mapper` *(或 colmap mapper)* | | 4. 导出文本模型 | `colmap model_converter --output_type TXT` | > 💡 若使用 **GloMap**(更快更鲁棒),请确保已安装且命令可用。 --- ### 6. `visualize_trajectories(...)` **作用**:使用 Matplotlib 可视化三条轨迹: - Ground Truth(蓝色实线) - COLMAP 原始相对轨迹(橙色虚线) - 缩放后的 COLMAP 轨迹(绿色实线) > 📌 提示:可通过 `--visualize` 参数启用此功能。 --- ## 🖥 五、运行方式 ### 1. 安装依赖 ```bash pip install numpy pyquaternion matplotlib opencv-python ``` 确保以下命令行工具已加入环境变量: - `ffmpeg` - `colmap` - (可选)`glomap` ### 2. 执行命令 ```bash python evaluate_trajectory.py \ --videos /path/to/videos_root \ --json /path/to/ground_truth.json \ --visualize ``` #### 参数说明: | 参数 | 必需 | 说明 | |------|------|------| | `--videos` | ✅ | 包含多个 `camXX/` 子目录的根路径 | | `--json` | ✅ | GT 轨迹 JSON 文件路径 | | `--visualize` | ❌ | 是否显示 3D 轨迹图 | --- ## 📊 六、输出结果 ### 1. 中间产物(按摄像头+视频组织) ```bash cam01/ └── colmap_output_frame_0001/ ├── images/ # 提取的图像帧 ├── database.db # COLMAP 数据库 ├── sparse/0/ │ ├── cameras.txt │ ├── images.txt # ← 用于位姿解析 │ └── points3D.txt ├── feature_extractor.log ├── matcher.log └── mapper.log ``` --- ### 2. 最终输出:CSV 报告 (`camera_errors_summary.csv`) ```csv camera,video,rot_err_deg,trans_err_rmse cam01,video,2.1345,0.0876 cam02,clip,1.8921,0.0732 ... ``` 字段含义: - `rot_err_deg`: 平均相对旋转误差(角度制) - `trans_err_rmse`: 平移误差(RMSE,单位与 GT 一致,通常为米) --- ## ⚠️ 七、注意事项与常见问题 | 问题 | 原因 | 解决方案 | |------|------|----------| | COLMAP 报错“no matches” | 图像模糊/重复/光照变化大 | 手动检查帧质量,调整提取间隔 | | 帧数不匹配 | GT 与 COLMAP 输出数量不同 | 检查排序逻辑是否正确;建议命名连续数字 | | 尺度异常(scale ≈ 0) | COLMAP 轨迹坍缩 | 检查特征点数量、三角化成功率 | | 无法找到 `images.txt` | 模型未成功生成 | 检查 mapper 日志,确认稀疏重建完成 | | 旋转误差偏高 | 初始对准不准或漂移严重 | 考虑添加回环检测或 Bundle Adjustment | --- ## 📎 八、可扩展方向 ✅ 当前局限性及改进思路: | 方向 | 描述 | |------|------| | ✅ 添加 BA 优化 | 在 mapper 后增加全局 bundle adjustment 提升精度 | | ✅ 时间同步校正 | 若 GT 与视频存在延迟,可引入时间偏移搜索 | | ✅ 更稳健的尺度估计 | 使用 ICP 或 Procrustes 对齐代替简单路径长度比 | | ✅ 支持 IMU 融合 | 若提供 IMU 数据,可改用 VIO 方法 | | ✅ 批量参数配置 | 引入 YAML 配置文件控制 COLMAP 参数 | --- ## 📜 九、附录:函数接口一览 | 函数名 | 输入 | 输出 | 用途 | |--------|------|------|------| | `parse_colmap_images` | `str` (path) | `R, T` (abs c2w) | 解析 COLMAP 输出 | | `parse_ground_truth` | `json_path, cam_type` | `R, T` (abs c2w) | 加载真值轨迹 | | `convert_to_relative_poses` | `R_abs, T_abs` | `R_rel, T_rel` | 转换为相对轨迹 | | `calculate_relative_errors_with_scale_alignment` | 两组相对位姿 | `rot_err, trans_err` | 计算误差 | | `run_colmap_pipeline` | `data_dir` | `bool` | 执行完整 SfM | | `visualize_trajectories` | 三组 T 轨迹 | None | 3D 可视化 | --- ## 🏁 十、结语 本工具实现了从 **原始视频 → 重建轨迹 → 定量评估** 的全流程自动化,特别适用于机器人、AR/VR、自动驾驶等领域中对视觉定位系统的性能验证。 它具备良好的可读性和可维护性,适合作为基础框架进一步集成到更大规模的测试平台中。 --- 📌 **建议实践顺序**: 1. 先用小段清晰视频测试流程通顺 2. 检查 `images.txt` 是否正常输出 3. 开启 `--visualize` 查看轨迹对齐效果 4. 调整 COLMAP 参数提升稳定性 5. 批量运行全部视频并分析 CSV 结果 --- 如有需要,我也可以为你生成: - Markdown 版本文档(适合 GitHub) - LaTeX 排版论文级报告 - Docker 镜像打包部署方案 - Web UI 可视化前端(Flask/Vue) 欢迎继续提问!
最新发布
10-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值