用Numpy将矩阵乘以另一个矩阵的每一行

4

我有一个大小为(4x4)的齐次变换矩阵和一个大小为(nx3)的轨迹。该轨迹的每一行都是一个向量。

我想将齐次变换矩阵乘以轨迹的每一行。以下是代码:

#append zero column at last
trajectory = np.hstack((trajectory, np.zeros((trajectory.shape[0], 1)))) #(nx3)->(nx4)

trajectory_new = np.zeros((1, 3)) #(1x3)
for row in trajectory:
    vect = row.reshape((-1,1)) #convert (1x4) to (4x1)
    vect = np.dot(HTM, vect) #(4x4) x (4x1) = (4x1)
    vect = vect.T #(1x4)
    vect = np.delete(vect, -1, axis=1) #remove last element from vector
    trajectory_new = np.vstack((trajectory_new, vect)) #(nx3)

trajectory_new = np.delete(trajectory_new, 0, axis=0)#remove first row

上述代码可以正常运行。不过,我正在寻找更简单的解决方案,如下所示:
trajectory_new = np.apply_along_axis(np.multiply, 0, trajectory, HTM)

任何帮助,请。
答案:
trajectory = np.hstack((trajectory, np.ones((trajectory.shape[0], 1))))#(nx3)->(nx4)
trajectory_new = trajectory.dot(HTM.T)[:,:-1]

你可以不使用堆栈来实现,就像这篇帖子中所示。 - Divakar
@Divakar:你是在谈论这个吗?它因形状不匹配而出现错误。请查看我在帖子中的评论。 - ravi
实际上,轨迹只包含3列数据,即在xyz方向上的位置。最后一个零是为了使计算变得可能。HTM是(4x4)的矩阵,而trajectory在添加了零列之后是(4x1)的矩阵。现在的乘法计算是HTM x trajectory,也就是(4x4) x (4x1) = (4x1)。 - ravi
再说一遍,使用 np.delete(vect, -1, axis=1) #从向量中删除最后一个元素 并没有利用它的功能。这就是为什么我评论的重点是我们不需要在开头堆叠零的原因。 - Divakar
(4x4) x (4x1) 得到 (4x1)。对这个向量进行转置得到 (1x4)。这是一个位置向量。这个向量的最后一个元素没有用处,所以我将其改为 (1x3)。我的意思是 HTM[:,:3] 是不正确的。HTMHTM[:3,:] 是正确的。 - ravi
显示剩余3条评论
4个回答

1
我认为你想要的是这样的东西:

trajectory_new = np.einsum('ij,kj->ik', HTM[:,:3], trajectory)

不确定顺序,但这应该比for循环快得多


1
你可以在堆叠 zeros 之前,使用 np.dot 对输入进行矩阵乘法。
trajectory.dot(HTM[:,:3].T)[:,:3]

方法 -

def dot_based(trajectory):
    return trajectory.dot(HTM[:,:3].T)[:,:3]

def original_app(trajectory):
    # append zero column at last
    traj_stacked = np.hstack((trajectory, np.zeros((trajectory.shape[0], 1))))

    trajectory_new = np.zeros((1, 3)) #(1x3)
    for row in traj_stacked:
        vect = row.reshape((-1,1)) #convert (1x4) to (4x1)
        vect = np.dot(HTM, vect) #(4x4) x (4x1) = (4x1)
        vect = vect.T #(1x4)
        vect = np.delete(vect, -1, axis=1) #remove last element from vector
        trajectory_new = np.vstack((trajectory_new, vect)) #(nx3)

    trajectory_new = np.delete(trajectory_new, 0, axis=0)#remove first row
    return trajectory_new

样例运行 -

In [37]: n = 5
    ...: trajectory = np.random.rand(n,3)
    ...: HTM = np.random.rand(4,4)
    ...: 

In [38]: np.allclose(dot_based(trajectory), original_app(trajectory))
Out[38]: True

1

能否提供一个输入和输出的例子?但似乎np.dot(HTM, trajectory.T)[:3].T就可以解决问题了?

为什么不删除HTM的最后一行,而要在trajectory中添加一列0呢?


np.dot(HTM, trajectory.T)[:3].T 返回以下错误:形状 (3,4) 和 (3,5) 不对齐:4 (维度 1) != 3 (维度 0) - ravi

0
你的轨迹是 nx3,但为了正确相乘,你需要 3xn。因此,你需要进行两次转置。一次是在相乘之前,一次是在相乘之后。
就像这样,
trajectory = (HTM[:3,:3] @ trajectory.T).T

我假设轨迹是一个向量,你想忽略HTM的起点?如果你也想添加起点,那么你可以这样做。
trajectory = (HTM[:3,:3] @ trajectory.T).T + HTM[:3,3]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接