点云数据自动采集系统
本项目使用深度相机采集彩色图像和深度数据,通过 Codroid API 与机械臂通信,保存图像、点云、位姿及 YOLO 自动检测结果,并提供后处理、数据集划分、训练和评估脚本。
当前目录是实验工程,包含多个采集版本、模型和历史训练输出。本文依据现有代码整理;硬件型号、标定参数和实机环境尚未确认,相关表格值留空。本文不代表完整流程已通过实机验证。
Git 仓库的初始版本仅收录源码、文档和配置。下文目录树描述本地实验目录;模型权重(PT/ONNX)、工具 EXE、历史训练结果和缓存已通过 .gitignore 排除,本地文件仍保留。克隆仓库后需另行准备匹配的权重和硬件,下载位置尚待补充。
深度相机:彩色帧 + 对齐后的深度帧
├─ 彩色图、深度可视化图、RGBD 融合图
├─ PLY 点云 + NPZ 深度元数据
└─ YOLO 检测 → JSON 标注
机械臂:启动指定工程 + 查询 APO/CPO
└─ 位姿 TXT
JSON + NPZ + 位姿 TXT → 后处理 → 自定义 11 列 TXT
经人工确认的图像 + 标准 YOLO 标签
→ 数据集划分 → YAML 配置 → YOLO 训练 → 独立测试集评估
自定义 11 列 TXT 与训练用 YOLO 标签是不同格式。当前未提供一条经验证的命令,将全部采集输出直接转换为训练数据。
数据集项目/
├─ README.md
├─ CAPTURE/
│ ├─ Main/ 采集、处理、训练和评估脚本
│ ├─ pythonApi/ Codroid 机械臂通信 SDK
│ │ ├─ src/CodroidApi/ 请求、通信与数据定义
│ │ ├─ test/demo.py 硬件调用示例
│ │ ├─ requirements.txt SDK 的 WebSocket 依赖
│ │ └─ pyproject.toml SDK 打包元信息
│ ├─ 144_black_yaml/ 12 个单类别训练配置
│ ├─ 48_black_yaml/ 10 个单类别训练配置
│ ├─ to_92_yaml/ 12 类数据集配置
│ ├─ models/ 一组 12 个单类别模型
│ ├─ new_models_114/ 另一组 12 个单类别模型
│ ├─ new_models_48/ 一组 10 个单类别模型
│ ├─ new_model_92/ PT、ONNX 与标注工具配置
│ ├─ 1202/runs/ 历史训练结果
│ ├─ 1206/runs/ 历史训练结果
│ ├─ 1207/runs/ 历史训练结果
│ └─ .idea/ 本地 IDE 配置
├─ Depth.Quality.Tool.exe 深度质量工具
├─ Intel.RealSense.Viewer.exe 相机查看工具
├─ X-AnyLabeling-CPU.exe 标注工具
└─ yolov8s.pt 预训练权重
CAPTURE/Main/ 内的脚本说明:
| 脚本 | 用途与差异 |
|---|---|
catch_data.py |
彩色、深度、点云、位姿与自动标注的采集入口;默认引用 models/ZTL11.pt |
catch_data_144.py |
另一采集入口;默认引用 new_models_114/M1A2.pt,采集时长为 4000 秒 |
catch_data_48.py |
10 类模型系列的采集入口;点云输入按 SCALE=1/3 缩放 |
for_48.py |
与 catch_data_48.py 仅默认保存目录不同 |
new.py |
实验采集变体;FRAME_SKIP 存在二次赋值 |
catch_rgb.py |
单独采集 RGB 图像,无机械臂调用 |
catch_data_processor.py |
合并 JSON、NPZ、位姿,生成自定义 TXT |
processor_copy .py |
批量后处理变体;文件名在 .py 前含空格 |
to_val_train.py |
将子目录中的 JPG 和对应 YOLO TXT 复制到 train/val |
get_test_from_train.py |
从训练集抽样复制;不能直接作为独立测试集生成方法 |
index_to_0.py、index_to_what.py |
修改标签中的类别编号,会改写指定目录下的文件 |
rename.py |
重命名并复制数据 |
train_sequence.py |
遍历数据集 YAML,依次训练 YOLO |
test_to_92.py |
检查标签并在 YAML 的 test 集上评估模型 |
Point_p.py |
比较预测框和标注框的中心距离、IoU |
tangle.py |
在图像上交互绘制矩形并查看像素信息 |
watch_cloud.py、test_cloud.py |
点云处理与可视化 |
正式维护的采集入口:。48、144、114、92 的实验命名含义:。
代码使用 pyrealsense2 和 Codroid API,但不能据此确定相机型号或机械臂型号。
| 项目 | 实际信息 |
|---|---|
| 深度相机品牌、型号、数量 | |
| 相机固件、RealSense SDK/驱动版本 | |
| 相机连接方式、接口要求 | |
| 机械臂品牌、型号、自由度 | |
| 控制器型号、固件版本 | |
| Codroid SDK 来源、版本、使用文档 | |
| 机械臂实际 IP、端口与网络设置 | |
| 机械臂端采集工程名称、工程文件及部署方法 | |
| 相机安装位置:固定外置或安装在机械臂上 | |
| 相机与机械臂的坐标系、外参或手眼标定结果 | |
| APO/CPO 各分量含义、顺序、长度及单位 | |
| 深度比例、有效量程、相机内参与畸变参数来源 | |
| 运动轨迹、速度、采集区域与停止方法 | |
| 帧与机械臂位姿的同步方式、允许时间误差 | |
| 实际操作系统、Python、CPU/GPU、CUDA 环境 | |
| 后处理几何参数的来源、物理含义与单位 |
当前代码值仅供定位配置,不表示已确认的设备参数:
- 相机流:640×480,30 FPS;彩色
bgr8,深度z16,深度对齐到彩色。 - 采集目标帧率:主要入口设置为 5 FPS,通过跳帧实现。
- 机械臂连接:代码中写有固定内网 IP、端口
9000和工程名CatchPicture;请在本地按实际设备修改。 - 后处理包含
ANGLE_OFFSET=260、HEIGHT=1400、RADIUS=0.5,以及calculate_df()的几何常量;未经物理含义和单位确认,不应当作通用标定参数使用。
SDK 的 pyproject.toml 声明 Python ≥3.11,但整个项目尚无锁定且实机验证的依赖组合。
| 依赖 | 用途 |
|---|---|
numpy |
图像数组、点云和元数据处理 |
opencv-python |
图像读写、处理、窗口交互 |
open3d |
点云读写与可视化 |
pyrealsense2 |
RealSense 相机采集 |
Pillow |
部分采集版本的图像操作 |
ultralytics |
YOLO 推理、训练与验证 |
| PyTorch / CUDA 环境 | YOLO 计算环境,需与目标设备匹配 |
websocket_client==1.8.0、websockets==15.0.1 |
当前 SDK 声明的通信依赖 |
在项目根目录打开终端。以下是依据导入语句整理的安装起点,尚未通过完整硬件环境验证;安装成功后需记录实际版本。
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r .\CAPTURE\pythonApi\requirements.txt
.\.venv\Scripts\python.exe -m pip install numpy opencv-python open3d pyrealsense2 Pillow ultralytics相机驱动、机械臂控制软件及机械臂端工程需要另行准备。GPU 训练需要匹配的 PyTorch/CUDA 环境;项目暂未提供经验证的安装组合。
当前导入采用 pythonApi.src.CodroidApi...,模型相对路径又以 Main 为起点。为适配现有代码,可在同一 PowerShell 会话中设置:
# 起始位置:项目根目录
$capturePython = (Resolve-Path .\.venv\Scripts\python.exe).Path
$captureSource = (Resolve-Path .\CAPTURE).Path
if ($env:PYTHONPATH) {
$env:PYTHONPATH = "$captureSource;$env:PYTHONPATH"
} else {
$env:PYTHONPATH = $captureSource
}
Set-Location .\CAPTURE\Main
# 只导入依赖,不创建相机或机械臂实例
& $capturePython -c "import cv2, numpy, open3d, pyrealsense2, PIL, ultralytics; from pythonApi.src.CodroidApi.CodroidApi import CodroidApi; print('Imports OK')"该设置仅作用于当前终端。这里没有将 pip install -e CAPTURE/pythonApi 作为已经验证的安装方式:SDK 内部仍混用源码目录导入,且 _init_.py 不是标准的 __init__.py。
当前脚本没有统一命令行配置接口,需要编辑所选脚本顶部配置。
| 配置项 | 需要确认的内容 |
|---|---|
SAVE_DIR |
输出目录、可写权限、可用空间 |
CAPTURE_DURATION、CAPTURE_FPS |
本次时长与目标采集帧率;不同入口默认值差异很大 |
RS_WIDTH、RS_HEIGHT、RS_FPS |
相机支持的流参数 |
ROBOT_IP、ROBOT_PORT |
控制器连接配置 |
ROBOT_PROJECT |
已部署到控制器的采集工程 |
LABEL_CONFIG.model_path |
与本次目标对应的模型文件 |
model_class_mapping |
模型文件名与输出类别 ID 的对应关系 |
conf_threshold、iou_threshold |
检测阈值 |
POINTCLOUD_REGION、SCALE |
点云区域及缩放策略,须与后处理一致 |
路径中现有的 G:/...、Z:/... 是原实验环境路径,需逐一替换。os.path.abspath('../...') 仍依赖启动目录,因此上述运行示例固定在 CAPTURE/Main 下执行。
采集入口会调用机械臂上电、切换自动模式并运行指定工程。只有在硬件、轨迹、工作区域和停止方式确认后,才执行以下示例。 当前程序可能在机械臂启动失败时询问是否继续采集,此时位姿数据可能缺失。
沿用第 4 节终端环境,并完成配置后,选择一个入口:
# 示例:使用 catch_data.py 的采集配置
& $capturePython .\catch_data.py按实验需要,可改用 catch_data_144.py 或 catch_data_48.py,不应同时运行多个入口争用设备。相机线程结束后,程序处理剩余队列并尝试停止机械臂工程。Ctrl+C 是程序中断请求,不能替代设备的急停;实际急停方法待填写。
若只需要彩色图像,先修改 catch_rgb.py 中的保存路径、数量和帧率,再执行:
& $capturePython .\catch_rgb.py检查输出是否齐全、图像是否可读、点云是否合理、位姿是否有效、类别是否正确。现有成功计数不足以证明每帧的图像、点云、位姿和异步标注全部成功,应以实际文件为准。
输出位于所选入口的 SAVE_DIR。以下是代码生成的结构示意,不是仓库已提供的数据样例。
<SAVE_DIR>/
├─ rgb_images/<timestamp>_rgb.png
├─ depth_images/<timestamp>_depth.png
├─ rgbd_images/<timestamp>_rgbd.png
├─ pointclouds/<timestamp>_ply.ply
├─ npz/<timestamp>_meta.npz
├─ position_info/<timestamp>_position.txt
└─ OutputJson/<timestamp>_rgb.json
时间戳格式为 YYYYMMDD_HHMMSS_mmm,由保存阶段的系统时间生成。相同文件名前缀用于关联数据;该前缀不能证明相机与位姿实现了硬件同步。
| 数据 | 当前实现 |
|---|---|
| RGB PNG | 彩色图像 |
| 深度 PNG | 每帧归一化的 8 位灰度可视化,不能直接还原真实距离 |
| RGBD PNG | 彩色图与深度灰度相加后归一化的三通道图像,不是四通道原始 RGB-D 数据 |
| PLY | 带颜色的点云;代码按深度值除以 1000 计算以米表示的坐标,实际比例待确认 |
NPZ pixel_coords |
(N, 2) 像素坐标 (u, v);缩放采集版本使用缩放后的网格 |
NPZ validity |
(N,) 深度是否大于零的布尔掩码 |
NPZ depth_values |
(N,) 深度值,代码按米计算 |
| 位姿 TXT | 两行文本:APO: ... 与 CPO: ...;分量及单位待硬件确认 |
JSON 示例仅展示格式,数值为示意:
[
{
"box_2d": [0.1, 0.2, 0.6, 0.8],
"score": 0.95,
"class_id": 0
}
]box_2d 为归一化 [x_min, y_min, x_max, y_max]。当前主要采集入口仅保留最高置信度的一个框,类别来自模型文件名映射;没有检测框时不生成 JSON,因此缺少 JSON 既可能是无检测结果,也可能是失败,需要结合日志判断。
catch_data_processor.py 读取 JSON、NPZ 和位姿,输出 txt_annotations/<timestamp>_txt.txt,并记录日志。
运行前必须处理以下衔接条件:
- 将
ROOT_DIR指向实际采集目录。 - 当前处理器在
pointclouds查找 NPZ,采集器写入npz。需同时核对顶部目录配置和函数内文件匹配所用的子目录字符串;只修改一个常量不足以保证一致。批处理变体也存在此差异。 - 确认像素坐标尺度。
catch_data_48.py保存缩放后的 NPZ 坐标,而处理器用 640×480 还原 JSON 框;直接连接两者会出现坐标尺度不一致。 - 确认 APO/CPO、几何常量及单位,再使用派生距离或角度结果。
以上条件处理并检查小样例后,沿用第 4 节环境执行:
& $capturePython .\catch_data_processor.py输出为逗号分隔、无表头的 11 列 TXT:
| 列 | 内容 |
|---|---|
| 1 | class_id |
| 2–5 | 归一化 x_min, y_min, x_max, y_max |
| 6 | 检测框区域内的最小有效深度 |
| 7 | calculate_df() 结果加最小深度 |
| 8 | 90 - CPO[3] |
| 9 | CPO[5] |
| 10 | (HEIGHT + CPO[3]) * 0.001 |
| 11 | sqrt(RADIUS**2 + 第10列**2) |
第 10 列在代码中的键名仍含 2000,但当前 HEIGHT=1400;上表按实际计算表达式说明。派生列的物理意义与量纲尚需确认。
训练标签应采用 YOLO 检测格式,每行空格分隔:
class_id x_center y_center width height
坐标相对于图像宽高归一化。自定义 JSON 框如需转换,中心为 ((x_min+x_max)/2, (y_min+y_max)/2),宽高为 (x_max-x_min, y_max-y_min)。自定义 11 列 TXT 不可直接放入 YOLO labels。
当前划分脚本仅收集 .jpg,主要采集入口输出 .png;需先明确图像格式转换或调整读取规则,并保证图片和标签同名。自动标注结果需人工核查。仓库未包含一组用于验证上述转换的完整样例。
to_val_train.py 当前预期输入:
<source_root>/
├─ <类别或批次A>/images/*.jpg
├─ <类别或批次A>/labels/*.txt
├─ <类别或批次B>/images/*.jpg
└─ <类别或批次B>/labels/*.txt
修改脚本底部三个路径与比例后,可执行 to_val_train.py。它默认按 8:2 划分 train/val,随机种子为 42;文件遍历未排序、跨子目录同名文件可能覆盖,因此正式数据应保存划分清单并做重名检查。
不要把 get_test_from_train.py 复制出的数据直接当作独立测试集:这些样本仍存在于训练集中。 应在训练前建立互斥的 train/val/test 集合,连续采集数据宜按批次或场景划分,并核查重复帧。
修改相应 YAML 中的 path、train、val、test、names,确保目标目录存在。to_92_yaml/to_92.yaml 的当前类别顺序为:
0 H 1 T80 2 T90MS 3 T0S1A
4 MK4 5 M1A2 6 ZBD04A 7 PLZ05
8 ZTL11 9 B 10 99 11 T14
48 系列采集映射为:0 99B, 1 B2, 2 E100, 3 FDN, 4 HB, 5 HW, 6 M1A2, 7 SS, 8 T3476, 9 TJH。两套编号不可混用。单类别训练 YAML 的类别编号与合并数据集编号也需要对应转换。
旧 models 目录中的 TOS1A.pt 使用字母 O,而部分映射使用 T0S1A.pt(数字 0);选用该模型前应统一名称,否则可能得到 class_id=-1。
训练前编辑 train_sequence.py:设置 YAML_DIRECTORY、MODEL_TYPE、训练轮数、批大小、图像尺寸、设备,以及函数默认的 project 输出目录。默认设备为 "0",使用 CPU 时需改为 "cpu"。
# 已完成数据准备与路径配置后,在 CAPTURE/Main 中运行
& $capturePython .\train_sequence.py训练结果保存于配置的 project 目录,通常包括权重、args.yaml、数据 YAML、results.csv 和可视化图片。
评估前编辑 test_to_92.py 的模型路径、数据 YAML、测试标签目录、类别数量和阈值,再执行:
& $capturePython .\test_to_92.py该脚本使用 split="test"。YAML 的 test 路径必须与实际独立测试集一致;不能仅修改 TEST_LABELS_PATH 而忽略 YAML。
| 现象或限制 | 检查方向 |
|---|---|
No module named pythonApi |
按第 4 节设置本会话的 PYTHONPATH,检查源码目录 |
| 找不到权重或数据 | 检查旧盘符路径、当前工作目录和 YAML 路径 |
| 相机启动失败 | 检查连接、驱动、流参数与设备占用,具体型号兼容性待确认 |
| 机械臂连接或工程启动失败 | 检查实际网络、控制器状态及工程部署;现有启动代码未完整校验每条命令的响应 |
| 后处理找不到 NPZ | 检查 npz 与 pointclouds 的目录不一致问题 |
| 检测框内无有效深度或点云比例异常 | 检查像素尺度、深度比例、对齐后的相机内参和单位 |
| 输出计数正常但文件不全 | 图像/点云写入返回值未完整检查,异步标注结果也未计入完整成功条件 |
new.py 的帧率与配置不符 |
FRAME_SKIP 计算后被覆盖为 60 |
| 评估指标不可作为独立测试结果 | 核查训练集与测试集重叠、相邻帧泄漏和标签格式 |
相机对齐到彩色后仍使用原深度流内参、固定深度比例、保存时查询位姿等实现需要实机核验。项目尚未记录完整标定信息,不应仅凭文件生成成功判断几何精度和同步精度。
复现实验应记录:代码版本、入口、全部配置、依赖版本、硬件及固件、标定参数、模型来源、数据批次、划分清单和评估命令。训练脚本已有随机种子与参数输出,但仍不足以独立复现完整采集过程。
贡献修改时,请说明影响的入口和数据格式,提供小样例的预期/实际结果;涉及硬件的变更请注明设备、参数和实际验证范围。test_cloud.py、SDK demo.py 是演示脚本,不是离线自动测试套件。
公开发布前应补充:
- 一组允许公开的完整样例及格式校验结果。
- 项目级依赖配置及已验证的安装环境;
.gitignore已提供,新增数据目录时仍需核对忽略范围。 - 代码许可证、数据使用条件、SDK 与模型来源和再分发说明。
- 将完整训练检查点、原始数据、工具 EXE、IDE 配置和 Python 缓存从代码发布范围中分离;按需提供独立下载位置。
当前没有项目级 LICENSE。SDK 的 pyproject.toml 中有 MIT 文本声明及占位作者信息,不能据此认定整个工程及附带数据、模型、工具均适用 MIT。
请维护者补充第 3 节空白信息,并确认以下项目:
- 正式使用哪个采集入口,各版本名称分别代表什么。
- 相机和机械臂型号、SDK/固件版本、安装方式与网络连接。
- 机械臂端工程、运动轨迹、速度和停止方式。
- APO/CPO 字段定义、单位、坐标系、标定及几何参数依据。
- 相机帧与位姿的同步要求、实际采集参数及已验证的软件环境。
- 是否有可公开的完整样例、模型来源以及期望采用的代码/数据许可证。