How to calculate the axis of orientation?
以前,我根据解剖结构计算方向轴,例如爪中的脚趾。
但我发现,当我无法很好地区分脚趾或"鞋跟"(蓝色正方形)离得很远时,这不起作用。所以我决定寻找更好的选择,我决定尝试计算惯性轴。
这一页对如何计算它给出了很好的解释,但是我很难理解从质量中心(在我的例子中是压力)到某个角度的步骤。
解释可以归结为:,它使用的是压力中心和一个p值,我不知道它是什么。
我可以使用matlab代码计算人的脚的轴,并尽我所能将其转换为python:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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)]] |
据我所知,旋转矩阵的sin(角度)和cos(角度)用来确定轴。但我真的不知道如何使用这些值来画出一个轴穿过爪并围绕它旋转。
知道我做错了什么和/或我该怎么解决吗?
如果有人觉得需要进行实验,这里有一个包含每个爪子压力数据的所有切片阵列的文件。对Clarfy来说: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"),表示提取的影响。
好吧,这里有一个实现与上面的代码做同样的事情(并以相关的角度旋转图像)。
但是,就你的爪子而言,我不确定它是否能像人类的脚一样工作。
首先,对于狗的爪,这种方式定义的"长"轴是沿着爪的宽度而不是爪的长度。只要它是一致的,这就没什么关系了,因为我们可以简单地用计算出的角度来旋转,而不是90度——计算出的角度。
然而,狗的爪子接近圆形的事实给了我们更多的问题。
基本上,这可能不会像对人类那样对狗有用。"长轴"的旋转由图像的第二个中心时刻形成的图像的协方差矩阵推导(我认为这是您上面的代码所做的),不太可能是对爪的方向的精确测量。
换言之,狗的爪子接近圆形,它们似乎把大部分重量都放在脚趾上,所以"后"脚趾的重量比这个计算中的字体要轻。正因为如此,我们得到的轴不会一直与"后"脚趾和前脚趾的位置有关系。(希望这有点道理……我是个可怕的作家…这就是为什么我要回答这个问题而不是写我应该写的论文…)
无论如何,足够的闲逛…下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 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() |
在这些图中,中心点是图像的质心,红线定义"长"轴,白线定义"短"轴。
原始(未旋转)爪:
旋转爪子:
这里有一件事要注意…我只是绕着它的中心旋转图像。(同样,
如果你想围绕一个点旋转它(比如说,质心),并将这个点移动到新图像上的一个新位置,你可以通过几个技巧在Scipy的