Python读取c3d文件

部署运行你感兴趣的模型镜像

        某天,小H在公司摸鱼,突然ld发来消息:小H,把这一份文件转换成我们常用的csv方便后续处理。小H一看都蒙圈了,什么c3d文件,根本没有见过,赶紧上网搜索起来。

        原来啊,c3d文件通俗解释其作为运动捕捉数据 "容器" 的特性,比如它如何同时存储标记点轨迹(如膝盖、脚踝的三维坐标)、肌电信号(肌肉活动)、测力台数据(地面反作用力)等多类信息。

        小H拿到的这份是关于一个步态分析的数据《A multimodal dataset of human gait at different walking speeds》,数据内容如下:

          标记点轨迹数据:记录 52 个反光标记点的三维坐标,涵盖全身各部位,用于分析关节运动学。
          模拟数据:包括肌电信号、地面反作用力和力矩,反映肌肉活动和力学特征。
          力板数据:包含力板中心压力坐标、三维地面反作用力和力矩,用于研究步态动力学。
          元数据:存储参与者年龄、性别、体重、身高、腿长等信息,以及脚步事件时间,为数据分析提供背景信息。

        那我们要处理出的csv文件就显而易见了,列名就是对应的数据嘛,然后根据不同的数据类型放到不同的文件夹下面。

        但是c3d文件到底是长什么样子的呢,小H还是有点好奇的,如果能像文件夹一样可视化看到文件结构就好了,于是上网找到了 VBC3Deditor 这下总算是能够看到文件具体是什么样子的。打开其中的一份文件结构就如下了:

        

        就好像每一个文件夹都有了属性一样,不过这些先不管了,小H决定就交一份数据上去再说,所以上网查找什么东西能够快速帮自己读取c3d文件,然后就找到了python c3d库。

import c3d

with open(file_path, 'rb') as f:
    reader = c3d.Reader(f)  # 创建读取器对象

        很简单的导入库和创建读取器对象,然后要读取什么内容呢?

        首先我们关注到这个文件夹有四个大类比,首先看到header。

Header(头信息)

  • 含义:C3D 文件的 “元数据总览”,存储整个文件的基础参数,是解析文件的 “钥匙”。

  • 包含内容:

    • 标记点数量(point_count)、模拟信号通道数(analog_count);

    • 标记点帧率(point_rate,如 100Hz,每秒采集 100 帧标记点);

    • 模拟信号采样率(analog_rate,如 1500Hz,力台、肌电等信号的采样频率);

    • 文件版本、总帧数、数据起始地址等底层格式信息。

  • 作用:告诉解析工具 “如何解读后续数据”,例如 “有多少个标记点”“每秒钟采集多少帧”。

        那我们就看到header里面有什么内容。

        看起来确实是一些参数相关的,可以试着使用reader读取对应的内容。不过我们使用c3d库来进行解析的话有另外一套标准命名,就不能这样直接读取了。

        直接使用reader.header就可以看到有什么属性了。

        可见他解析的命名和原始的还是有一定区别的,不过基本上都可以对应上,然后根据数据集给出的说明文档,我们首要就是提取标记点数据和模拟数据了,也就是Point和analog。

Point Data(标记点数据)

  • 含义:存储运动捕捉中标记点的 3D 空间坐标数据,是文件的核心数据之一。

  • 包含内容:

    • 每个标记点在每帧的 X、Y、Z 三维坐标(单位通常为毫米);

    • 其他

Analog Data(模拟信号数据)

  • 含义:存储连续采集的模拟信号(非离散标记点),通常与标记点数据同步记录。

  • 包含内容:

    • 肌电信号(EMG):肌肉活动的电压变化(单位:伏特);

    • 力台数据:地面反作用力(Fx、Fy、Fz,单位:牛顿)和力矩(Mx、My、Mz,单位:牛・毫米);

    • 其他传感器数据:如加速度计、陀螺仪信号等。

        对于以上俩种数据,我们使用reader.read_frames()来读取,c3d库在这里返回的是(frame_number, points_array, analog_array) (当然也能没有analog这一列)

        for frame_num,points,analog_points in reader.read_frames():
            print(frame_num)
            print(points.shape)
            print(analog_points.shape)

        其中一帧输出是 1 (52,5) (20,15) 和文档说明对上了,接下来就按照目录进行解析就可以了,也就是应该有什么列名写入到csv中。

        看到我们的points坐标应该是x,y,z三维的,所以只需要前面的3项就可以了,analog我们截取15项,因为采样率是point的15倍,也就是说每个frame应该有15个sample

        for frame_info in reader.read_frames():
            frame_num = frame_info[0]
            points = frame_info[1]
            analog_data = frame_info[2]

            point_data.append(points[:,:3])
            print(frame_num)
            print(point_data)
            print(analog_data.shape[0])
            print(analog_data.shape[1])

        这样就可以看到我们完整一帧想要的数据内容有什么了。

        后续我们只要使用point_label 和 analog_label就可以得到上述对应的列名了。

        到这里基本上任务已经可以完成了,提取出数据之后转换为numpy格式在和平时一样去保存到csv里面就可以了。

        小H高高兴兴地把数据都处理完就上传了,但是回过头去看别人给的文档,那么里面应该还有和力平台啊、受测试的人的信息呢?都放在哪里了,那我们文件夹下还有Events和Groups俩个大类好像都没有用到一样。

        

Events(事件数据)

  • 含义:记录运动过程中的关键时间点,用于标记动作的重要阶段。

  • 包含内容:

    • 事件时间(对应标记点的帧编号或模拟信号的采样点);

    • 事件标签(如 “heel_strike” 脚跟着地、“ toe_off ” 脚趾离地、“ stance ” 支撑相、“ swing ” 摆动相);

    • 事件类型(如手动标记、自动检测)。

  • 作用:将原始数据与运动学阶段关联,例如 “第 100 帧是左脚着地时刻”,方便后续分析步态周期。

        不过这份文件并没有这部分,在可视化的文件里面没有,或者直接使用reader.events也没有访问到。

Groups(分组信息)

  • 含义:对标记点或模拟信号通道进行逻辑分组,便于批量处理同类数据

        我们直接使用_groups访问到了group的内容:

        基本和可视化软件给出的是一样的,可以清楚看到有SUBJECT和FORCE_PLATFORM这俩个目标内容,那就可以去访问了。

        如果存在什么问题可以和我联系。

您可能感兴趣的与本文相关的镜像

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃芒果的蘑菇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值