首页 文章

如何计算方向轴?

提问于
浏览
7

以前,我根据解剖结构计算了方向轴,例如爪子中的脚趾 .

enter image description here

但是我发现这并没有很好地区分脚趾,或者'heel'(蓝色方块)是否已经脱落 . 所以我决定寻找更好的选择,我决定尝试计算the inertial axis .

This page gives a great explanation of how to calculate it,但我无法理解从质量中心(或我的压力)到某个角度的步骤 .

enter image description here

解释归结为:
enter image description here
使用压力中心和值p,其中我不知道它是什么 .

我可以访问为人类脚计算此轴的Matlab代码,并尽力将其转换为Python:

x = 0.508 # sensor size in the x-direction
y = 0.762 # sensor size in the y-direction
Ptot = 0 # total pressure 
Px   = 0 # first order moment(x)
Py   = 0 # first order moment(y)
Pxx  = 0 # second order moment (y)
Pyy  = 0 # second order moment (x)
Pxy  = 0 # second order moment (xy)

for row in range(rows): # y-direction
    for col in range(cols): # x-direction
        if data[row,col] > 0.0: # If not zero
            temp = 1
        else:
            temp = 0
        Ptot = Ptot + temp # Add 1 for every sensor that is nonzero
        Px = Px   + (x * col + x / 2) * temp
        Py = Py   + (y * row + y / 2) * temp
        Pxx = Pxx + (x * y * y * y / 12 + x * y * (row * y + y / 2) * (row * y + y / 2) ) * temp
        Pyy = Pyy + (y * x * x * x / 12 + x * y * (col * x + x / 2) * (col * x + x / 2) ) * temp        
        Pxy = Pxy + (x * y * (row * y + y / 2) * (row * x + x / 2)) * temp

CoPY = Py / Ptot
CoPX = Px / Ptot
CoP = [CoPX, CoPY]

Ixx = Pxx - Ptot * self.x * self.y * CoPY * CoPY
Iyy = Pyy - Ptot * self.x * self.y * CoPX * CoPX
Ixy = Pxy - Ptot * self.x * self.y * CoPY * CoPX
angle = (math.atan(2 * Ixy / (Iyy - Ixx))) / 2

Ixp = Ixx * math.cos(angle) * math.cos(angle) + Iyy * math.sin(angle) * math.sin(angle) - 2 * Ixy * math.sin(angle) * math.cos(angle)
Iyp = Iyy * math.cos(angle) * math.cos(angle) + Ixx * math.sin(angle) * math.sin(angle) + 2 * Ixy * math.sin(angle) * math.cos(angle)
RotationMatrix = [[math.cos(angle), math.sin(angle)], [-math.sin(angle), math.cos(angle)]]

因此,据我所知,来自RotationMatrix的sin(角度)和cos(角度)用于确定轴 . 但我真的不明白如何使用这些值来绘制通过爪子的轴和rotate it around it .

Any idea what I'm doing wrong and/or what I should do to solve it?

如果有人觉得需要进行实验,这里有一个包含所有切片阵列的文件,其中包含每个爪子的压力数据 . 为了澄清:walk_sliced_data是一个包含['ser_3','ser_2','sel_1','sel_2','ser_1','sel_3']的字典,它们是测量的名称 . 每个测量包含另一个字典,[0,1,2,3,4,5,6,7,8,9,10](例如来自'sel_1'),表示提取的影响 .

1 回答

  • 7

    好吧,这是一个实现与上面代码相同的实现(并通过相关角度旋转图像) .

    但是,对于你的爪子,我不确定它是否会像人脚一样好用 .

    首先,对于狗的爪子,这样定义的“长”轴是沿着爪子的宽度而不是爪子的长度 . 这并不重要,只要它是一致的,因为我们可以简单地旋转计算的角度而不是90 - 计算的角度 .

    然而,狗的爪子接近圆形的事实给我们带来了更多的问题 .

    基本上,这对狗来说可能不会像人类那样有用 . 由图像的第二个中心矩形成的图像的协方差矩阵推导出的“长”轴的旋转(这是我认为上面的代码所做的)不太可能是对方向的精确测量 . 爪子 .

    换句话说,一只狗的爪子接近圆形,并且它们的大部分重量都显示在它们的脚趾上,因此“背”脚趾的重量比该计算中的字体重 . 因此,我们获得的轴不会始终与“后”脚趾与前脚趾的位置有关系 . (希望这有点意义......我是一个可怕的作家...这就是为什么我回答这个问题,而不是在写我应该做的论文......)

    无论如何,足够漫无边际......这是一个例子:

    import cPickle
    import numpy as np
    import matplotlib.pyplot as plt
    
    from scipy import ndimage
    
    def main():
        measurements = cPickle.load(open('walk_sliced_data', 'r'))
        plot(measurements['ser_1'].values())
        plt.show()
    
    def raw_moment(data, iord, jord):
        nrows, ncols = data.shape
        y, x = np.mgrid[:nrows, :ncols]
        data = data * x**iord * y**jord
        return data.sum()
    
    def intertial_axis(data):
        data_sum = data.sum()
        m10 = raw_moment(data, 1, 0)
        m01 = raw_moment(data, 0, 1)
        x_bar = m10 / data_sum
        y_bar = m01 / data_sum
        u11 = (raw_moment(data, 1, 1) - x_bar * m01) / data_sum
        u20 = (raw_moment(data, 2, 0) - x_bar * m10) / data_sum
        u02 = (raw_moment(data, 0, 2) - y_bar * m01) / data_sum
        angle = 0.5 * np.arctan(2 * u11 / (u20 - u02))
        return x_bar, y_bar, angle
    
    
    def plot(impacts):
        def plot_subplot(pawprint, ax):
            x_bar, y_bar, angle = intertial_axis(pawprint)
            ax.imshow(pawprint)
            plot_bars(x_bar, y_bar, angle, ax)
            return angle
    
        fig1 = plt.figure()
        fig2 = plt.figure()
        for i, impact in enumerate(impacts[:9]):
            ax1 = fig1.add_subplot(3,3,i+1)
            ax2 = fig2.add_subplot(3,3,i+1)
    
            pawprint = impact.sum(axis=2)
            angle = plot_subplot(pawprint, ax1)
    
            pawprint = ndimage.rotate(pawprint, np.degrees(angle))
            plot_subplot(pawprint, ax2)
    
        fig1.suptitle('Original')
        fig2.suptitle('Rotated')
    
    def plot_bars(x_bar, y_bar, angle, ax):
        def plot_bar(r, x_bar, y_bar, angle, ax, pattern):
            dx = r * np.cos(angle)
            dy = r * np.sin(angle)
            ax.plot([x_bar - dx, x_bar, x_bar + dx], 
                    [y_bar - dy, y_bar, y_bar + dy], pattern)
        plot_bar(1, x_bar, y_bar, angle + np.radians(90), ax, 'wo-')
        plot_bar(3, x_bar, y_bar, angle, ax, 'ro-')
        ax.axis('image')
    
    
    if __name__ == '__main__':
        main()
    

    在这些图中,中心点是图像的质心,红色线定义“长”轴,而白线定义“短”轴 .

    原始(未旋转)爪子:
    enter image description here

    旋转的爪子:
    enter image description here

    这里要注意的一件事......我只是围绕它的中心旋转图像 . (此外, scipy.ndimage.rotate 对于N-D阵列也适用于2D . 您可以轻松旋转原始3D "pawprint-over-time"阵列 . )

    如果你想围绕一个点(比如质心)旋转它,并将该点移动到新图像上的新位置,你可以通过几个技巧在scipy的 ndimage 模块中相当容易地完成它 . 如果你对这个例子有点长的话,我可举个例子,不过......

相关问题