Dexcap复现代码数据预处理全流程(四)——demo_clipping_3d.py

此脚本的主要功能是可视化点云数据文件(.pcd 文件),并通过键盘交互选择演示数据的起始帧和结束帧,生成片段标记文件 (clip_marks.json)

主要流程包括:

  • 用户指定数据目录:检查目录是否存在并处理标记文件 ->
  • 加载帧数据并渲染:使用 Open3D 可视化点云数据和几何结构 ->
  • 监听键盘输入:通过键盘动态导航帧,并标记片段的起始和结束 ->
  • 保存标记数据:将标记的片段保存为 JSON 文件

目录

[1 库引用](#1 库引用)

[2 主程序入口](#2 主程序入口)

[3 处理 clip_marks.json 文件](#3 处理 clip_marks.json 文件)

[3 初始化 ReplayDataVisualizer](#3 初始化 ReplayDataVisualizer)

[4 键盘交互](#4 键盘交互)

[5 回放帧可视化](#5 回放帧可视化)


1 库引用

python 复制代码
import argparse
import os
import copy
import zmq
import cv2
import sys
import json
import shutil
import open3d as o3d
import numpy as np
import platform
from pynput import keyboard
from transforms3d.quaternions import qmult, quat2mat
from transforms3d.axangles import axangle2mat
from scipy.spatial.transform import Rotation
from transforms3d.euler import quat2euler, mat2euler, quat2mat, euler2mat
from visualizer import *

# 全局变量定义
clip_marks = []  # 存储所有片段标记
current_clip = {}  # 当前片段的起始和结束标记
next_frame = False  # 用于指示是否跳转到下一帧
previous_frame = False  # 用于指示是否跳转到上一帧

2 主程序入口

python 复制代码
# 主程序入口
if __name__ == "__main__":
    # 解析命令行参数
    parser = argparse.ArgumentParser(description="Visualize saved frame data.")
    parser.add_argument("--directory", type=str, default="./saved_data", help="Directory with saved data")
    args = parser.parse_args()

    # 检查输入目录是否存在
    assert os.path.exists(args.directory), f"given directory: {args.directory} not exists"

解析命令行参数 -> 检查并处理 clip_marks.json -> 初始化数据可视化器 -> 启动回放帧可视化,并监听用户交互

命令行参数解析与输入校验:

  1. 解析命令行参数:--directory 参数指定数据目录,默认为 ./saved_data

  2. 校验输入路径:检查指定目录是否存在,否则直接报错退出

3 处理 clip_marks.json 文件

python 复制代码
    # 检查是否已有 clip_marks.json 文件,避免误覆盖
    if os.path.exists(os.path.join(args.directory, 'clip_marks.json')):
        response = (
            input(
                f"clip_marks.json already exists. Do you want to override? (y/n): "
            )
            .strip()
            .lower()
        )
        if response != "y":
            print("Exiting program without overriding the existing directory.")
            sys.exit()

如果 clip_marks.json 已存在,提示用户是否覆盖:

  • 输入 y:继续运行,并允许覆盖文件
  • 输入其他内容:程序退出,避免覆盖原有标记数据

3 初始化 ReplayDataVisualizer

python 复制代码
    # 数据目录
    dataset_folder = args.directory

    # 初始化可视化器
    visualizer = ReplayDataVisualizer(args.directory)

    # 加载左右手校准数据(偏移和旋转)
    visualizer.right_hand_offset = np.loadtxt("{}/calib_offset.txt".format(args.directory))
    visualizer.right_hand_ori_offset = np.loadtxt("{}/calib_ori_offset.txt".format(args.directory))
    visualizer.left_hand_offset = np.loadtxt("{}/calib_offset_left.txt".format(args.directory))
    visualizer.left_hand_ori_offset = np.loadtxt("{}/calib_ori_offset_left.txt".format(args.directory))

    # 开始帧回放和交互
    visualizer.replay_frames()

初始化自定义类 ReplayDataVisualizer,继承自 DataVisualizer 类

从文件中加载左右手的偏移数据(位置偏移和旋转偏移),用于调整点云的显示

4 键盘交互

python 复制代码
# 键盘按下事件的回调函数
def on_press(key):
    """
    当键盘按键被按下时触发。
    根据按键执行相应的功能,例如帧跳转、标记起始/结束、保存标记等。
    """
    global next_frame, previous_frame, frame, clip_marks, current_clip

    # 当前帧的文件夹名
    frame_folder = 'frame_{}'.format(frame)

    # 根据键盘按键的类型执行操作
    if key == keyboard.Key.up:  # 按下"上箭头"保存当前所有标记到 JSON 文件
        with open(os.path.join(dataset_folder, 'clip_marks.json'), 'w') as f:
            json.dump(clip_marks, f, indent=4)
    elif key == keyboard.Key.down:  # 按下"下箭头"跳转到上一帧
        previous_frame = True
    elif key == keyboard.Key.page_down:  # 按下"Page Down"键跳转到下一帧
        next_frame = True
    elif key == keyboard.Key.end:  # 按下"End"键标记当前片段结束
        if 'start' in current_clip.keys():  # 只有当前片段有起点时才允许结束
            print("end", frame_folder)
            current_clip['end'] = frame_folder  # 设置结束帧
            clip_marks.append(current_clip)  # 将当前片段添加到标记列表
            current_clip = {}  # 清空当前片段
    elif key == keyboard.Key.insert:  # 按下"Insert"键标记当前片段开始
        print("start", frame_folder)
        current_clip['start'] = frame_folder  # 设置起始帧
    else:
        print("Key error", key)  # 其他按键未定义功能

监听键盘输入,并根据按键触发相应功能:

  • Insert:标记当前帧为片段的起始帧
  • End:标记当前帧为片段的结束帧,并保存到 clip_marks 列表
  • Page Down:跳转到下一帧
  • Down Arrow:跳转到上一帧
  • Up Arrow:将标记的片段保存到 clip_marks.json 文件

5 回放帧可视化

python 复制代码
# 定义自定义可视化类,继承 DataVisualizer
class ReplayDataVisualizer(DataVisualizer):
    def __init__(self, directory):
        """
        初始化 ReplayDataVisualizer 类
        :param directory: 数据目录路径
        """
        super().__init__(directory)

    def replay_frames(self):
        """
        帧回放和交互函数。
        可视化点云数据,并支持用户通过键盘交互切换帧和标记片段。
        """
        global next_frame, previous_frame, frame

        # 初始化基准帧
        if self.R_delta_init is None:
            self.initialize_canonical_frame()

        # 加载初始帧数据
        self._load_frame_data(frame)

        # 将几何体添加到可视化场景中
        self.vis.add_geometry(self.pcd)  # 添加点云
        self.vis.add_geometry(self.coord_frame_1)  # 添加坐标系1
        self.vis.add_geometry(self.coord_frame_2)  # 添加坐标系2
        self.vis.add_geometry(self.coord_frame_3)  # 添加坐标系3
        for joint in self.left_joints + self.right_joints:  # 添加所有关节
            self.vis.add_geometry(joint)
        for cylinder in self.left_line_set + self.right_line_set:  # 添加所有连杆
            self.vis.add_geometry(cylinder)

        # 使用键盘监听器处理交互事件
        try:
            with keyboard.Listener(on_press=on_press) as listener:
                while True:
                    # 跳转到下一帧
                    if next_frame:
                        next_frame = False
                        frame += 10  # 每次跳转10帧
                    # 跳转到上一帧
                    if previous_frame:
                        previous_frame = False
                        frame -= 10  # 每次返回10帧

                    # 加载新帧数据
                    self._load_frame_data(frame)

                    # 更新几何体的显示
                    self.vis.update_geometry(self.pcd)
                    self.vis.update_geometry(self.coord_frame_1)
                    self.vis.update_geometry(self.coord_frame_2)
                    self.vis.update_geometry(self.coord_frame_3)
                    for joint in self.left_joints + self.right_joints:
                        self.vis.update_geometry(joint)
                    for cylinder in self.left_line_set + self.right_line_set:
                        self.vis.update_geometry(cylinder)

                    # 渲染场景
                    self.vis.poll_events()
                    self.vis.update_renderer()
                listener.join()
        finally:
            # 输出累积校正信息(如果有)
            print("cumulative_correction ", self.cumulative_correction)

加载并可视化当前帧数据:渲染点云数据和其他几何体(坐标系、关节、连杆等)

键盘监听:根据用户输入跳转到下一帧或上一帧

更新渲染:每次跳转后重新加载当前帧数据,并更新渲染场景

相关推荐
天弈初心1 分钟前
python:利用神经网络技术确定大量离散点中纵坐标可信度的最高集中区间
开发语言·python·神经网络
Serendipity_Carl4 分钟前
爬虫基础之爬取某基金网站+数据分析
爬虫·python·pycharm·数据分析·数据可视化
dundunmm17 分钟前
【数据挖掘】深度高斯过程
python·深度学习·机器学习·数据挖掘·高斯过程·深度高斯过程
灵魂画师向阳21 分钟前
AI绘画 Stable Diffusion【应用篇】【角色一致性】:如何从不同视角创造一致的人物角色?
人工智能·ai作画·stable diffusion·aigc·美女
程序员正茂27 分钟前
AnaConda下载PyTorch慢的解决办法
人工智能·pytorch
IT古董37 分钟前
【漫话机器学习系列】039.点积(dot product)
人工智能·线性代数·机器学习
leisigoyle42 分钟前
第四届智能系统、通信与计算机网络国际学术会议(ISCCN 2025)
网络·人工智能·计算机网络
小张认为的测试1 小时前
Selenium 浏览器驱动代理 - 无需下载本地浏览器驱动镜像!(Java 版本!)
java·python·selenium·测试工具·浏览器
8Qi81 小时前
多目标优化算法——基于聚类的不规则Pareto前沿多目标优化自适应进化算法(CA-MOEA)
人工智能·算法·多目标优化·进化计算·群体智能·ca-moea
泡芙萝莉酱1 小时前
中国税务年鉴PDF电子版Excel2022年-社科数据
大数据·人工智能·深度学习·数据挖掘·数据分析·毕业论文·统计年鉴