tracking_inputs是什么?

 引入

 tracking_inputs = [[pose['keypoints'] for pose in poses] for poses in pose_results]

这行代码的目的是从 pose_results 中提取出所有人体姿态的关键点信息,并将其整理成一个适合用于后续跟踪处理的格式。

具体步骤如下:

  1. for poses in pose_results:

    • 这是一个外层的 for 循环,用于遍历 pose_results 中的每一帧检测结果。
    • pose_results 是一个列表,其中每个元素都是一个当前帧中检测到的所有人体姿态。
  2. [pose['keypoints'] for pose in poses]

    • 这是一个内层的列表推导式(List Comprehension)。
    • 它遍历当前帧中的每个人体姿态 pose,并提取出其中的关键点信息 pose['keypoints']
    • 这样,对于每一帧,我们都得到了一个包含所有检测到的人体关键点的列表。
  3. [[pose['keypoints'] for pose in poses] for poses in pose_results]

    • 这是最外层的列表推导式。
    • 它遍历 pose_results 中的每一帧,对于每一帧都执行内层的列表推导式,得到当前帧中所有检测到的人体关键点列表。
    • 最终,我们得到了一个二维列表 tracking_inputs,其中每个元素都是一帧中所有人体关键点的列表。

简单来说,这行代码的作用是将 pose_results 中的原始人体姿态数据转换成一个更加适合进行后续跟踪处理的格式。每个元素都是一帧中所有检测到的人体关键点的列表。这种格式可以很方便地传递给跟踪算法进行处理。

问题

问题1

tracking_inputs是什么数据类型,举个实际例子

tracking_inputs 是一个二维列表(List of Lists)。

通过一个具体的例子来说明:

假设我们有一个 pose_results 列表,其包含了一个视频中的3帧人体姿态检测结果,每帧都检测到了2个人体:

pose_results = [
    [
        {'keypoints': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]},
        {'keypoints': [0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88, 0.99, 1.1]}
    ],
    [
        {'keypoints': [0.12, 0.23, 0.34, 0.45, 0.56, 0.67, 0.78, 0.89, 1.0, 1.11]},
        {'keypoints': [0.13, 0.24, 0.35, 0.46, 0.57, 0.68, 0.79, 0.9, 1.01, 1.12]}
    ],
    [
        {'keypoints': [0.14, 0.25, 0.36, 0.47, 0.58, 0.69, 0.8, 0.91, 1.02, 1.13]},
        {'keypoints': [0.15, 0.26, 0.37, 0.48, 0.59, 0.7, 0.81, 0.92, 1.03, 1.14]}
    ]
]

那么,经过上述代码处理后,tracking_inputs 的值将是:

tracking_inputs = [
    [[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], [0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88, 0.99, 1.1]],
    [[0.12, 0.23, 0.34, 0.45, 0.56, 0.67, 0.78, 0.89, 1.0, 1.11], [0.13, 0.24, 0.35, 0.46, 0.57, 0.68, 0.79, 0.9, 1.01, 1.12]],
    [[0.14, 0.25, 0.36, 0.47, 0.58, 0.69, 0.8, 0.91, 1.02, 1.13], [0.15, 0.26, 0.37, 0.48, 0.59, 0.7, 0.81, 0.92, 1.03, 1.14]]
]

可以看到,tracking_inputs 是一个三层嵌套的列表结构:

  • 最外层列表包含了3个元素,对应于3帧的人体姿态检测结果
  • 每个元素都是一个列表,包含了当前帧中检测到的所有人体的关键点信息
  • 每个人体的关键点信息都是一个列表,包含了10个坐标值

这种数据结构可以很方便地传递给后续的跟踪算法进行处理。

问题2

那如果继续执行for idx, poses in enumerate(tracking_inputs):得到什么

就是把tracking_inputs实参传入pose_tracking函数

for idx, poses in enumerate(tracking_inputs):
    print(f"Frame {idx}: {poses}")

这样执行后,输出就会变成:

Frame 0: [[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], [0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88, 0.99, 1.1]]
Frame 1: [[0.12, 0.23, 0.34, 0.45, 0.56, 0.67, 0.78, 0.89, 1.0, 1.11], [0.13, 0.24, 0.35, 0.46, 0.57, 0.68, 0.79, 0.9, 1.01, 1.12]]
Frame 2: [[0.14, 0.25, 0.36, 0.47, 0.58, 0.69, 0.8, 0.91, 1.02, 1.13], [0.15, 0.26, 0.37, 0.48, 0.59, 0.7, 0.81, 0.92, 1.03, 1.14]]

这样就可以直观地看到每一帧中检测到的所有人体的姿态信息了。

需要注意的是,poses 是一个列表,包含了当前帧中检测到的所有人体的关键点信息。所以在打印时,我们将整个 poses 列表都打印出来了。

如果你只想打印某个特定的人体,可以像下面这样修改代码:

for idx, poses in enumerate(tracking_inputs):
    print(f"Frame {idx}:")
    for i, pose in enumerate(poses):
        print(f"Person {i}: {pose}")

这样就可以打印出每一帧中每个人体的关键点信息了。

        if len(poses) == 0:
            continue
        if num_joints is None:
            num_joints = poses[0].shape[0]

问题3

if len(poses) == 0:这个poses是一个二维列表吗?

在这个例子中,poses 是一个二维列表。

具体来说:

  • tracking_inputs 是一个三维列表,表示多帧(第一层)中检测到的多个人体(第二层)的姿态关键点(第三层)。
  • poses 是 tracking_inputs 中的第二层列表,表示当前帧中检测到的所有人体的姿态关键点。
  • 因此, len(poses) 就是当前帧中检测到的人体数量,而 poses[0] 就是第一个人体的姿态关键点(也是一个列表)。

所以在语句 if len(poses) == 0: continue 中, poses 是一个二维列表,表示当前帧中检测到的所有人体的姿态关键点。如果 len(poses) 为 0,就意味着当前帧中没有检测到任何人体,需要跳过继续处理下一帧。

问题4

poses 是一个二维列表,那len(poses)是什么语法?

poses 作为一个二维列表,len(poses) 就是获取这个二维列表的长度,也就是当前帧中检测到的人体数量。

这是一种非常常见的 Python 语法,用来获取列表的长度。

具体解释如下:

  • poses 是一个二维列表,表示当前帧中检测到的所有人体的姿态关键点。
  • len(poses) 就是获取这个二维列表的长度,也就是当前帧中检测到的人体数量。
  • 例如,如果 poses 是 [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 0.9]],那么 len(poses) 的结果就是 3,因为这个二维列表中有 3 个子列表(也就是 3 个人体)。

这种使用 len() 函数获取列表长度的方式在 Python 中非常常见和重要。无论是一维列表还是多维列表,使用 len() 都可以很方便地获取其长度。

问题5

if len(poses) == 0:发现不满足,就不会执行continue

  1. 首先,我们遍历 tracking_inputs 中的每一帧。

  2. 对于每一帧,我们先检查 if len(poses) == 0:

    • 如果 len(poses) == 0,也就是当前帧中没有检测到任何人体,我们直接使用 continue 跳过这个帧,进入下一个。
    • 如果 len(poses) != 0,也就是当前帧中检测到了人体,那么我们就执行下面的代码。
  3. 接下来,我们检查 if num_joints is None:

    • 如果 num_joints 还未被赋值,我们就从第一个人体的关键点数量(poses[0].shape[0])中获取 num_joints 的值。

如果 len(poses) == 0 不满足,程序不会执行 continue,而是会继续执行下面的 if num_joints is None: 语句。

问题6

num_joints变量初始值是None,是重新赋值覆盖吗?

是的,在这个代码中,num_joints变量的初始值被设置为None

当遍历pose_results列表时,如果当前帧检测到了人体,就会执行以下代码:

if num_joints is None:
    num_joints = poses[0].shape[0]

这里的判断是检查num_joints是否为None。如果为None,说明这是第一个检测到人体的帧,此时我们需要获取关键点的数量并将其存储在num_joints变量中。

也就是说,第一次执行这段代码时,num_jointsNone,所以会被重新赋值为当前帧检测到的关键点数量。

此后,在处理后续帧时,num_joints就不再为None了,所以就不会再次赋值。这样可以确保在整个处理过程中,所有帧的关键点数量都是一致的。

总的来说,num_joints变量就是通过这种方式从None被初始化为实际的关键点数量的。

问题7

poses[0].shape[0] 这个语法

poses是一个包含多个人体关键点坐标的列表。在第 0 帧中,poses 是:

[[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], [0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88, 0.99, 1.1]]

poses[0] 表示获取列表 poses 中的第一个元素,也就是第一个人体关键点坐标列表 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]

poses[0].shape[0] 中的 shape 是 Python 中用于获取数组或列表的形状的属性。shape[0] 就是获取这个列表的长度,也就是列表中元素的个数。

在这个例子中,第一个人体关键点坐标列表 [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] 有 10 个元素,所以 poses[0].shape[0] 的结果就是 10。

这个值就被赋给了 num_joints 变量,用于后续的处理。

总的来说,poses[0].shape[0] 就是用来获取当前帧检测到的人体关键点数量的一种方法。

问题8

为什么是shape[0]这个0是什么

shape 属性返回的是一个元组(tuple),里面包含对象的维度信息。

对于一个二维列表(list of lists)来说,shape 会返回一个包含两个元素的元组。比如对于这个例子中的 poses[0]:

[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]

它的 shape 属性会返回 (10,), 这个元组只有一个元素 10

之所以用 shape[0] 来获取长度,是因为对于一维列表(list),shape 返回的元组只有一个元素,表示列表的长度。所以直接取 shape 元组的第 0 个元素就能得到列表的长度。

如果是二维列表,shape 返回的元组会有两个元素,分别表示行数和列数。比如对于 poses 这个二维列表:

[[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], 
 [0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88, 0.99, 1.1]]

它的 shape 属性会返回 (2, 10), 表示有 2 行,每行 10 个元素。所以如果想获取行数,就需要使用 shape[0]

总之, shape[0] 就是用来获取一维列表(或二维列表的第一维)的长度的一种简单方法。

问题9

这个例子中的 poses[0]:是一维列表吧,而poses是二维列表

对,在这个例子中:

  • poses 是一个二维列表,包含多个人体关键点坐标列表。
  • poses[0] 是 poses 列表中的第一个元素,也就是第一个人体关键点坐标列表。
  • 这个 poses[0] 是一个一维列表,包含 10 个元素,表示一个人体的 10 个关键点坐标。

poses[0] 是一个一维列表。

在这个例子中,使用 poses[0].shape[0] 是为了获取第一个人体关键点坐标列表的长度,也就是 10。

这个长度被赋值给 num_joints 变量,用于后续的处理。

问题10

以上面为例,现在相当于 num_joints就是10

如果 num_joints 变量的初始值为 None,那么它就会被赋值为 poses[0].shape[0] 的结果,也就是 10。

所以在这个例子中,num_joints 的值就被设置为 10。

这样做的目的是为了确保 num_joints 变量保存了当前帧检测到的人体关键点数量,后续的处理就可以使用这个值。

总结一下:

  1. 初始时 num_joints 为 None
  2. 通过 poses[0].shape[0],获取第一个人体关键点坐标列表的长度为 10。
  3. 将 10 赋值给 num_joints 变量。

之后在处理其他帧时,num_joints 就不再是 None,会一直保持为 10。这确保了所有帧的关键点数量都是一致的。

问题11

 if len(poses) == 0:如果条件满足怎么办?

就会执行continue

说明当前帧没有检测到任何人体关键点,于是直接使用 continue 语句跳过当前循环,进入下一个循环。

for idx, poses in enumerate(pose_results):
    if len(poses) == 0:
        continue
    # 其他代码

如果 len(poses) == 0 成立,也就是说当前帧没有检测到任何人体关键点,那么程序会执行 continue 语句。

这时,当前循环迭代就会立即结束,程序不会执行 # 其他代码 部分,而是直接进入下一次循环迭代,也就是处理下一帧的数据。

这样做的目的是,当某一帧没有检测到人体关键点时,就跳过这一帧,不执行后续的处理操作,而是直接进入下一帧的处理。这样可以提高程序的效率,避免对没有任何数据的帧进行不必要的计算。

总之,continue 语句的作用是跳过当前循环迭代,进入下一次循环迭代。这在某些情况下可以帮助提高程序的性能和效率。

pyskl/demo/demo_skeleton.py at main · kennymckormick/pyskl · GitHub

ValueError Traceback (most recent call last) <ipython-input-54-536a68c200e5> in <module> 52 return model 53 # lstm network ---> 54 model = create_LSTM_model(X_train,n_steps,n_length, n_features) 55 # summary 56 print(model.summary()) <ipython-input-54-536a68c200e5> in create_LSTM_model(X_train, n_steps, n_length, n_features) 22 X_train = X_train.reshape((X_train.shape[0], n_steps, 1, n_length, n_features)) 23 ---> 24 model.add(ConvLSTM2D(filters=64, kernel_size=(1,3), activation='relu', 25 input_shape=(n_steps, 1, n_length, n_features))) 26 model.add(Flatten()) ~\anaconda3\lib\site-packages\tensorflow\python\trackable\base.py in _method_wrapper(self, *args, **kwargs) 203 self._self_setattr_tracking = False # pylint: disable=protected-access 204 try: --> 205 result = method(self, *args, **kwargs) 206 finally: 207 self._self_setattr_tracking = previous_value # pylint: disable=protected-access ~\anaconda3\lib\site-packages\keras\utils\traceback_utils.py in error_handler(*args, **kwargs) 68 # To get the full stack trace, call: 69 # `tf.debugging.disable_traceback_filtering()` ---> 70 raise e.with_traceback(filtered_tb) from None 71 finally: 72 del filtered_tb ~\anaconda3\lib\site-packages\keras\engine\input_spec.py in assert_input_compatibility(input_spec, inputs, layer_name) 233 ndim = shape.rank 234 if ndim != spec.ndim: --> 235 raise ValueError( 236 f'Input {input_index} of layer "{layer_name}" ' 237 "is incompatible with the layer: " ValueError: Input 0 of layer "conv_lstm2d_12" is incompatible with the layer: expected ndim=5, found ndim=3. Full shape received: (None, 10, 5)解决该错误
05-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值