使用Python和Matplotlib

时间:2018-07-11 12:35:32

标签: python matplotlib edge

下面的代码代表与n行文本文件读取相对应的图形绘制。每行包含4列,前三列是(x,y,z)点的坐标,而第四列是此绘图不必要的二进制变量。

每读取20行,就会读取一个骨架,该骨架是一组20个(x,y,z)点或关节,每个关节由每行的前三列组成。

文本文件包含860行,并且860/20 = 43,即要创建20个(x,y,z)关节骨架的关节数量。然后,该文本文件由43个骨骼组成,生成一个动作。因此,文本文件代表运动

我在构建以逻辑方式将每个(x,y,z)点与其他点连接起来的边线时遇到了问题,因此点的绘制看起来像是骨架。一个循环,这样,每读取20行,就会生成一个骨架,并在按键事件发生后,假设向右箭头键,则会读取下20行并生成另一个骨架。

我是Python和Matplotlib的初学者。我在下面发布了Matploblit生成的没有边缘的骨架的图片,另一幅与我需要用边缘实现的结果相似的图片。

文本文件内容的示例:

1.3200000e+002  8.0000000e+001  6.8100000e+002  1.0000000e+000
1.6900000e+002  8.1000000e+001  6.6500000e+002  1.0000000e+000
1.4800000e+002  7.5000000e+001  6.5000000e+002  0.0000000e+000
1.5100000e+002  9.8000000e+001  6.9800000e+002  0.0000000e+000
1.3200000e+002  1.2000000e+002  6.7400000e+002  1.0000000e+000
1.6100000e+002  1.2200000e+002  6.6200000e+002  8.1730800e-001

此外,在绘制骨骼时,仅采用两个坐标(x,y)来生成2D骨骼,因此将忽略第三个坐标。并且,绘图已经在循环中,但是按键事件部分尚未实现,当关闭当前画布时,将绘制下一个骨架。

此外,您可能会注意到绘图正在生成前一个骨骼与下一个骨骼的重叠,我也张贴了重叠的图片,这是第一个骨骼之后生成的42个骨骼之一。

第一个绘制的无关节骨骼: https://i.stack.imgur.com/FNFTL.png

接下来的42个无关节绘制的骨骼中的一个出现了OVERLAP问题: https://i.stack.imgur.com/D8FQt.png

所需结果的一种方法: https://i.stack.imgur.com/PkWUc.png

from pylab import *
from matplotlib import gridspec
import numpy as np
import sys
import math
import matplotlib.pyplot as plt

movement = np.loadtxt("file01.txt")
number_of_postures = int(len(movement)/20)

listing = []
for i in range(number_of_postures):
    listing.append(movement[(i*20):((i+1)*20),:3]) 

matrixCoord = np.array(listing)

num_plots = number_of_postures
z = 0

for m in range(num_plots):      
   gs = gridspec.GridSpec(1, 2, width_ratios=[3, 1]) # create figure at start of loop

    z += 20
    skeleton = movement[:z,:2]
    x = skeleton[:,0]
    y = -skeleton[:,1]
    plt.subplot(gs[1]) 
    plt.scatter(x,y, s=40)
    plt.title('Skeleton')
    plt.show()

1 个答案:

答案 0 :(得分:1)

仅首先直接回答您的问题:

绘制关节之间的线:
首先创建“骨骼列表”,该列表包含构建骨骼线的所有关节对。可以从您张贴的带有枚举关节的图片中获得:

bone_list = [[1, 3], [2, 3], [3, 4], [4, 7], [5, 7], [6, 7], [1, 8], [2, 9], [8, 10], [9, 11], [10, 12], [11, 13], [5, 14], [6, 15], [14, 16], [15, 17], [16, 18], [17, 19], [3, 20]]

由于枚举从1开始,而python索引从0开始,请将列表转换为numpy数组,以轻松地将所有值减1:

bone_list = np.array(bone_list) - 1

准备好这一步后,您就可以在运动循环中画线,并为每条线(在plt.scatter(x, y, s=40)之后)添加一个额外的循环:

for bone in bone_list:
    plt.plot([x[bone[0]], x[bone[1]]], [y[bone[0]], y[bone[1]]], 'r')

,关于您的重叠问题:
这只是因为

skeleton = movement[:z, :2]

您总是从零开始切片,即在第一个循环(绘制一个骨骼)中为[0:20,:2],在第二个循环(绘制两个骨骼)中为[0:40,:2],依此类推。
更改为

skeleton = movement[z-20:z, :2]    # or [z:z+20, :2] and do z+=20 afterwards

但是,如果我可以在您的脚本中添加一些常规提示:

进口太多(至少对于您发布的部分而言)
有重命名的变量已经存在
有未使用的变量
您不会在循环中使用迭代变量m
gridspec用于在不均匀分布的网格中创建子图-您需要吗?

请记住,您想要的脚本可能如下所示:

import matplotlib.pyplot as plt
import numpy as np

movement = np.loadtxt("file01.txt")
bone_list = [[1, 3], [2, 3], [3, 4], [4, 7], [5, 7], [6, 7], [1, 8], [2, 9], [8, 10], [9, 11], [10, 12], [11, 13], [5, 14], [6, 15], [14, 16], [15, 17], [16, 18], [17, 19], [3, 20]]
bone_list = np.array(bone_list) - 1
number_of_postures = int(len(movement)/20)

for i in range(number_of_postures):
    fig, ax = plt.subplots(1, figsize=(3, 8))
    plt.title('Skeleton')
    plt.xlim(100, 180)
    plt.ylim(-250, 0)
    skeleton = movement[i*20:(i+1)*20]

    x = skeleton[:, 0]
    y = -skeleton[:, 1]

    sc = ax.scatter(x, y, s=40)
    for bone in bone_list:
        ax.plot([x[bone[0]], x[bone[1]]], [y[bone[0]], y[bone[1]]], 'r')