Human3.6m数据处理(mhformer代码解读)

对于3d人体姿态估计任务中数据集human3.6m的处理

        写在最前面:这是我自己的理解,说的不一定对。

        human3.6m有很多格式的数据,包括视频、2d ground truth、3d ground truth,还分为xyz坐标的表示形式和旋转向量表示形式,这篇只用到2d 和3d ground truth(坐标表示的)。

        这篇csdn以cvpr2022的mhformer为例,基本上videopose3d之后数据处理的方式都差不多。

源码地址:

GitHub - Vegetebird/MHFormer: [CVPR 2022] MHFormer: Multi-Hypothesis Transformer for 3D Human Pose Estimationicon-default.png?t=N7T8https://github.com/Vegetebird/MHFormer

1  数据集下载

        在代码dataset下的readme中给出了processed data的下载地址,由论文VideoPose3D给出。

        (不要从官网下,那个需要实验室申请,很麻烦,点最后的here下载,下面是下载地址)https://drive.google.com/drive/folders/112GPdRC9IEcwcJRyrLJeYw9_YV4wLdKC?usp=sharingicon-default.png?t=N7T8https://drive.google.com/drive/folders/112GPdRC9IEcwcJRyrLJeYw9_YV4wLdKC?usp=sharing        下载的数据放到代码dataset下:

        包括3d, 2d ground truth, 由cpn获得的2d label

|-- dataset
|   |-- data_3d_h36m.npz
|   |-- data_2d_h36m_gt.npz
|   |-- data_2d_h36m_cpn_ft_h36m_dbb.npz

2  数据格式解析

       由官网信息及各种对数据集介绍的帖子得知,human3.6m数据的具体内容是人体的32个关键点的坐标信息。

        可以用debug查看内容               

图2-1 data_3d_h36m.npz的具体内容示意图

        可以看到,具体内容包括S1等多个subject的数据,每个subject分为15个action,action下是具体的xyz坐标信息。

3 模型的数据处理部分

        3.1 3d数据加载 (Human36mDataset)

    root_path = opt.root_path
    dataset_path = root_path + 'data_3d_' + opt.dataset + '.npz'

    dataset = Human36mDataset(dataset_path, opt)
    actions = define_actions(opt.actions)

        加载3d数据集,这里用到Human36mDataset类(common->load_data_hm36.py中):

        这个类主要用于加载和处理数据,具体来说有两个作用,一:复制相机参数到每一个subject、action的数据下(由原来的position变为 position和camera两块数据);二:remove不需要的点(从32个keypoints到17个keypoints)

        ps:1 相机参数说明:

        相机参数可以用于坐标系的转换等,分为内部参数(intrinsic_params)和外部参数(extrinsic_params)

        内参:

  • 'id':相机的唯一标识符。
  • 'center':相机的中心坐标,是一个包含两个元素的列表,分别表示x和y坐标。
  • 'focal_length':相机的焦距,是一个包含两个元素的列表,分别表示主焦距和次焦距。
  • 'radial_distortion':径向畸变系数,是一个包含三个元素的列表。
  • 'tangential_distortion':切向畸变系数,是一个包含两个元素的列表。
  • 'res_w':相机的水平分辨率。
  • 'res_h':相机的垂直分辨率。
  • 'azimuth':相机的方位角。

        外参:

  • 'orientation':相机的旋转矩阵,是一个包含四个元素的列表,分别表示四元数的四个分量。
  • 'translation':相机的平移向量,是一个包含三个元素的列表,分别表示x、y和z方向上的平移距离。

        ps:2 世界坐标相机坐标说明:

        世界坐标系就是正常的坐标系,3d ground truth的坐标系。

        说一下相机坐标系:相机坐标系是在相机上建立的坐标系。这个坐标系的原点位于小孔,z轴与光轴重合,x轴和y轴平行投影面。

        世界坐标->相机坐标:世界坐标 * 旋转矩阵 + 平移变换 -> 相机坐标(大概是这样,就是说复制相机参数是用于坐标转换的)

        为什么要转换: 我的理解是,原数据每个subject,每个action都有4个机位的视频,对于每一段视频都有自己对应的3d label,而3d ground truth里只是一个实验室的坐标系,所以用相机参数进行转换,可以得到对应的4份3d label

class Human36mDataset(MocapDataset):
    def __init__(self, path, opt, remove_static_joints=True):
        super().__init__(fps=50, skeleton=h36m_skeleton)
        self.train_list = ['S1', 'S5', 'S6', 'S7', 'S8']
        self.test_list = ['S9', 'S11']

        self._cameras = copy.deepcopy(h36m_cameras_extrinsic_params)
        for cameras in self._cameras.values():
            for i, cam in enumerate(cameras):
                cam.update(h36m_cameras_intrinsic_params[i])
                for k, v in cam.items():
                    if k not in ['id', 'res_w', 'res_h']:
                        cam[k] = np.array(v, dtype='float32') 

                if opt.crop_uv == 0:
                    cam['center'] = normalize_screen_coordinates(cam['center'], w=cam['res_w'], h=cam['res_h']).astype(
                        'float32')
                    cam['focal_length'] = cam['focal_length'] / cam['res_w'] * 2

                if 'translation' in cam:
                    cam['translation'] = cam['translation'] / 1000 

                cam['intrinsic'] = np.concatenate((cam['focal_length'],
                                                   cam['center'],
                                                   cam['radial_distortion'],
                                                   cam['tangential_distortion']))

        data = np.load(path,allow_pickle=True)['positions_3d'].item()

        self._data = {}
        for subject, actions in data.items():
            self._data[subject] = {}
            for action_name, positions in actions.items():
                self._data[subject][action_name] = {
                    'positions': positions,
                    'cameras': self._cameras[subject],
                }

        if remove_static_joints:
            self.remove_joints([4, 5, 9, 10, 11, 16, 20, 21, 22, 23, 24, 28, 29, 30, 31])

            self._skeleton._parents[11] = 8
            self._skeleton._parents[14] = 8

    def supports_semi_supervised(self):
        return True

        上面是Human36mDataset类代码,通过3.1 3d数据加载这一步,3d的数据到了一个Human36mDataset类的对象中,包括position和camera。

        3.2 数据处理(包括2d和3d)(Fusion)

    if opt.train:
        train_data = Fusion(opt=opt, train=True, dataset=dataset, root_path=root_path)
        train_dataloader = torch.utils.data.DataLoader(train_data, batch_size=opt.batch_size,
                                                       shuffle=True, num_workers=int(opt.workers), pin_memory=True)

    test_data = Fusion(opt=opt, train=False, dataset=dataset, root_path =root_path)
    test_dataloader = torch.utils.data.DataLoader(test_data, batch_size=opt.batch_size,
                                                  shuffle=False, num_workers=int(opt.workers), pin_memory=True)

       用到Fusion类(common->load_data_hm36.py),下面具体说一下这个类:

        1 Fusion->perpare_data 

        先说perpare_data:

        下面这块代码,传入的dataset是3.1中加载的3d数据,folder_list当训练时选s1 s5  s6 s7 s8  测试的时候选s9 s11。

        具体的作用 1:通过world_to_camera把3d数据从世界坐标系转为相机坐标系;2:让2d的序列的长度和3d的序列长度保持一致; 3:数据标准化

    def prepare_data(self, dataset, folder_list):
        for subject in folder_list:
            for action in dataset[subject].keys():
                anim = dataset[subject][action]

                positions_3d = []
                for cam in anim['cameras']:
                    pos_3d = world_to_camera(anim['positions'], R=cam['orientation'], t=cam['translation'])
                    pos_3d[:, 1:] -= pos_3d[:, :1] 
                    positions_3d.append(pos_3d)
                anim['positions_3d'] = positions_3d

        keypoints = np.load(self.root_path + 'data_2d_' + self.data_type + '_' + self.keypoints_name + '.npz',allow_pickle=True)
        keypoints_symmetry = keypoints['metadata'].item()['keypoints_symmetry']

        self.kps_left, self.kps_right = list(keypoints_symmetry[0]), list(keypoints_symmetry[1])
        self.joints_left, self.joints_right = list(dataset.skeleton().joints_left()), list(dataset.skeleton().joints_right())
        keypoints = keypoints['positions_2d'].item()

        for subject in folder_list:
            assert subject in keypoints, 'Subject {} is missing from the 2D detections dataset'.format(subject)
            for action in dataset[subject].keys():
                assert action in keypoints[
                    subject], 'Action {} of subject {} is missing from the 2D detections dataset'.format(action,
                                                                                                         subject)
                for cam_idx in range(len(keypoints[subject][action])):

                    mocap_length = dataset[subject][action]['positions_3d'][cam_idx].shape[0]
                    assert keypoints[subject][action][cam_idx].shape[0] >= mocap_length

                    if keypoints[subject][action][cam_idx].shape[0] > mocap_length:
                        keypoints[subject][action][cam_idx] = keypoints[subject][action][cam_idx][:mocap_length]

        for subject in keypoints.keys():
            for action in keypoints[subject]:
                for cam_idx, kps in enumerate(keypoints[subject][action]):
                    cam = dataset.cameras()[subject][cam_idx]
                    if self.crop_uv == 0:
                        kps[..., :2] = normalize_screen_coordinates(kps[..., :2], w=cam['res_w'], h=cam['res_h'])
                    keypoints[subject][action][cam_idx] = kps
        
        return keypoints

        2 Fusion->fetch         

        

    def fetch(self, dataset, subjects, subset=1, parse_3d_poses=True):
        out_poses_3d = {}
        out_poses_2d = {}
        out_camera_params = {}

        for subject in subjects:
            for action in self.keypoints[subject].keys():
                if self.action_filter is not None:
                    found = False
                    for a in self.action_filter:
                        if action.startswith(a):
                            found = True
                            break
                    if not found:
                        continue

                poses_2d = self.keypoints[subject][action]

                for i in range(len(poses_2d)):
                    out_poses_2d[(subject, action, i)] = poses_2d[i]

                if subject in dataset.cameras():
                    cams = dataset.cameras()[subject]
                    assert len(cams) == len(poses_2d), 'Camera count mismatch'
                    for i, cam in enumerate(cams):
                        if 'intrinsic' in cam:
                            out_camera_params[(subject, action, i)] = cam['intrinsic']

                if parse_3d_poses and 'positions_3d' in dataset[subject][action]:
                    poses_3d = dataset[subject][action]['positions_3d']
                    assert len(poses_3d) == len(poses_2d), 'Camera count mismatch'
                    for i in range(len(poses_3d)): 
                        out_poses_3d[(subject, action, i)] = poses_3d[i]

        if len(out_camera_params) == 0:
            out_camera_params = None
        if len(out_poses_3d) == 0:
            out_poses_3d = None

        stride = self.downsample
        if subset < 1:
            for key in out_poses_2d.keys():
                n_frames = int(round(len(out_poses_2d[key]) // stride * subset) * stride)
                start = deterministic_random(0, len(out_poses_2d[key]) - n_frames + 1, str(len(out_poses_2d[key])))
                out_poses_2d[key] = out_poses_2d[key][start:start + n_frames:stride]
                if out_poses_3d is not None:
                    out_poses_3d[key] = out_poses_3d[key][start:start + n_frames:stride]
        elif stride > 1:
            for key in out_poses_2d.keys():
                out_poses_2d[key] = out_poses_2d[key][::stride]
                if out_poses_3d is not None:
                    out_poses_3d[key] = out_poses_3d[key][::stride]

        return out_camera_params, out_poses_3d, out_poses_2d

        ..今天先写这么多吧,希望下次打开它的时候不用再重读这个代码了

        下次打开的时候该看fetch函数了

        如果方向可以选,不要做hpe!光是数据就好复杂啊!

        在草稿箱里存了半年了吧,今天终于动笔了,为什么要写这个呢,因为我含泪看了很久,困扰了好几个月,当时多么希望有人能给我讲讲,希望写出来能给别人撑撑伞(555

       

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/207832.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS应用开发者基础认证考试(98分答案)

基于最近大家都在考这个应用开发者基础认证考试&#xff0c;因此出了一期&#xff0c;一样复制word里面搜索做&#xff0c;很快&#xff0c;当然good luck 判断题 Ability是系统调度应用的最小单元,是能够完成一个独立功能的组件。一个应用可以包含一个或多个Ability。 正确(Tr…

Swift构造器继承链

类类型的构造器代理 Swift构造器需遵循以下三大规则&#xff1a; 指定构造器必须调用它直接父类的指定构造器方法便利构造器必须调用同一个类中定义的其他初始化方法便利构造器在最后必须调用一个指定构造器 两段式构造过程 Swift 中类的构造过程包含两个阶段。第一个阶段&a…

Redis主从与哨兵架构详解

目录 主从架构 主从环境搭建 主从复制流程 1. 全量复制 2. 部分复制 主从风暴 哨兵架构 概念 哨兵环境搭建 主从架构 主从环境搭建 1. 复制一份redis.conf文件, 修改下面几行配置 port 6380 pidfile /var/run/redis_6380.pid logfile "6380.log" dir /usr/…

PowerDesigner数据库建模软件的安装

解压&#xff1a; 解压好以后&#xff0c;点击PowerDesigner.exe安装 这个安装的版本是15 选择安装路径&#xff0c;可以默认可以自定义&#xff1a; 直接点next&#xff1a; 全选了 点击next&#xff1a; 点击next&#xff1a; 点finish 汉化&#xff1a; 先把pojie和汉化文件…

Unity中Shader编译目标级别

文章目录 前言一、Shader Model二、Shader编译目标级别法1&#xff1a; #pragma target 3.0法2&#xff1a;#pragma require integers geometry 三、测试代码 前言 针对不同平台的特性&#xff0c;所做的一些功能 一、Shader Model ShaderModel 由微软提出&#xff0c;要求显…

蔚碳科技联合中投会发布国内首个 ESG 尽职调查服务标准

11 月 26 日&#xff0c;蔚碳&#xff08;上海&#xff09;科技有限公司&#xff08;以下简称“蔚碳科技”&#xff09;受邀出席由深圳市人民政府主办&#xff0c;深圳市发展和改革委员会、深圳市生态环境局、龙岗区人民政府共同承办的 2023 碳达峰碳中和论坛暨深圳国际低碳城论…

使用 SDKMAN 管理多版本本地 Java 环境---Centos8 Windows

文章目录 windows 安装centos8 安装卸载sdkman使用 windows 安装 SDKMAN是一个 jdk 多版本管理工具&#xff0c;类似于 nodejs 中的 nvm。可以在本地存在多个 java 环境&#xff0c;快速切换功能&#xff0c;同时&#xff0c;他不止于 java sdk&#xff0c;还有maven、tomcat等…

WhatsApp群发消息脚本功能介绍及代码分享!

随着社交媒体的普及&#xff0c;通讯应用成为了人们日常沟通的主要工具之一&#xff0c;其中&#xff0c;WhatsApp凭借其简洁、易用的特点&#xff0c;成为了全球广受欢迎的通讯应用之一&#xff0c;除了基础的聊天功能&#xff0c;WhatsApp还提供了一系列辅助工具功能&#xf…

关于 ls -s 输出文件大小的单位问题的讨论

自己看书正好看到这里&#xff0c;正纳闷呢&#xff0c;上网查了下&#xff0c;发现不是我自己在为这个问题感到困惑。 有个大哥提出一个问题&#xff1a; 问题标题&#xff1a; ls -s的单位到底是什么&#xff1f; man ls -s, --size print the alloca…

web前端之css变量的妙用、通过JavaScrip改变css文件中的属性值、querySelector、setProperty

MENU 效果图htmlJavaScripstylequerySelectorsetProperty 效果图 html <div id"idBox" class"p_r w_680 h_160 b_1s_red"><div id"idItem" class"p_a l_0 t_30 w_100 h_100 bc_rgba_255_00_05 radius_50_"></div> …

matlab 基于卡尔曼滤波的GPS-INS的数据融合的导航

1、内容简介 略 25-可以交流、咨询、答疑 2、内容说明 基于卡尔曼滤波的GPS-INS的数据融合的导航 "基于卡尔曼滤波的GPS-INS的数据融合的导航 基于卡尔曼滤波实现GPS-INS组合导航系统" 卡尔曼滤波、GPS、INS、数据融合、导航 3、仿真分析 4、参考论文 略 …

YOLOv8-Seg改进:SENetV2,squeeze和excitation全面升级,效果优于SENet | 2023年11月最新成果

🚀🚀🚀本文改进: SENetV2,squeeze和excitation全面升级,作为注意力机制引入到YOLOv8,放入不同网络位置实现涨点 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何训练YOLOv8-s…

FTP协议详解

一&#xff1a;概述 FTP协议是一个用于在计算机网络上在客户端和服务器之间进行文件传输的应用层协议&#xff0c;其英文全称是File Transfer Protocol。是TCP/IP协议簇中的重要一员。客户端和服务器按照FTP的协议规范进行通讯来实现文件传输。 对于FTP服务器好理解&#xff0c…

后仿真 ERROR

后仿真 error ERROR (SFE-23): "input.scs" 252: The instance _57_D32_noxref is referencing an undefined model or subcircuit, parasitic_nwd. Either include the file containing the definition of parasitic_nwd, or define parasitic_nwd before running t…

Adobe ColdFusion文件读取漏洞(CVE-2010-2861)

任务一&#xff1a; 复现漏洞 任务二&#xff1a; 尝试利用漏洞读取目标系统中的“opt/coldfusion8/license.txt"文件 1.环境搭建&#xff08;网上写的密码是admin&#xff0c;就用admin&#xff09; 2.看答案就是一层一层进行路径穿越攻击&#xff0c;这里要注意如果…

Vue+Element-ui实例_在form中动态校验tag标签

1.开发需求 在日常开发中&#xff0c;我们会遇到form表单的动态添加和校验&#xff0c;当我们需要在动态添加的内容中再次动态使用输入框的时候&#xff0c;就会变得很繁琐&#xff0c;我在网上找了很多案例&#xff0c;没有符合自己需求的内容&#xff0c;只好闲暇时间自己搞…

实现优雅的自增枚举类:Python中的枚举与自增技巧

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 枚举类型在编程中扮演着重要的角色&#xff0c;它们为变量赋予了更加清晰的含义。然而&#xff0c;在Python中&#xff0c;实现自增的枚举类并非直接而简单的任务。本文将深入讨论如何通过不同的方式优雅地实现自…

matlab 混沌动力学行为-分岔图-李雅普指数等

1、内容简介 略 24-可以交流、咨询、答疑 2、内容说明 混沌动力学行为-分岔图-李雅普指数等 包含各种类型的混沌模型求解&#xff0c;包含其分叉图、李雅普指数等 混沌、分叉图、李雅普指数 3、仿真分析 略 4、参考论文 略 链接&#xff1a;https://pan.baidu.com/…

JMX的使用

1. 定义和意义 JMX是Java Management Extention的缩写&#xff0c;出发点是让外部通过属性/方法来读取或设置程序状态。对于提供对外服务的程序来说&#xff0c;天生就有这样的能力&#xff0c;Web程序通过HTTP接口对外暴露&#xff0c;RPC应用通过RPC接口暴露。不过带来的问…

matlab simulink 永磁同步电机PI调速控制

1、内容简介 略 27-可以交流、咨询、答疑 2、内容说明 永磁同步电机调速控制 永磁同步电机PI调速控制 永磁同步电机PI调速控制、PMSM 3、仿真分析 略 4、参考论文 略 链接&#xff1a;https://pan.baidu.com/s/1AAJ_SlHseYpa5HAwMJlk1w 提取码&#xff1a;rvol 路…