如何用Numpy高效实现矩阵与向量数组的逐向量乘法?
高效实现矩阵与向量数组的逐元素乘法
针对3D渲染中矩阵批量乘向量的需求,有几种比for循环高效得多的Numpy方案,完全不用手动循环:
1. 维度调整+矩阵乘法
假设你的变换矩阵M是4x4(齐次坐标常用),向量数组vecs是(N,4)格式(每行一个4维向量):
# 转置向量数组为列向量矩阵,乘完再转置回来 transformed_vecs = (M @ vecs.T).T
如果你的向量数组原本就是(4,N)(每列一个向量),直接用M @ vecs就能得到(4,N)的变换结果,每个列对应变换后的向量——你之前得到错误结果可能是因为对输出维度的预期和实际不匹配,比如需要(N,4)格式就再转置一次。
2. 使用np.einsum(更直观的维度控制)
einsum可以明确指定维度的运算关系,避免维度混淆:
# 对于(N,4)的行向量数组,每个向量左乘M,输出(N,4) transformed_vecs = np.einsum('ij,kj->ki', M, vecs) # 对于(4,N)的列向量数组,每个向量左乘M,输出(4,N) transformed_vecs = np.einsum('ij,jk->ik', M, vecs)
这种方式可读性更强,不用记转置的方向,适合复杂的维度运算场景。
3. 使用np.dot(等价于行向量左乘矩阵)
如果向量是(N,4)的行向量格式,用dot结合矩阵转置也能实现:
transformed_vecs = np.dot(vecs, M.T)
原理是行向量v左乘矩阵M的结果,等于v与M.T的点积,Numpy会自动广播完成批量运算。
后续处理:批量除以w分量
变换后如果需要将齐次坐标转为笛卡尔坐标,直接利用Numpy的广播特性即可:
# 假设w分量是每个向量的第4个元素(索引3) w = transformed_vecs[:, 3:4] # 保持维度为(N,1)以支持广播 normalized_vecs = transformed_vecs / w
内容的提问来源于stack exchange,提问作者Jacob
相关产品推荐
相关产品推荐

