如何估计两个2D numpy数组之间的最优rigid transformation矩阵?
问题描述
我有两个尺寸相同、元素为0和1的2D numpy数组,示例如下:
# 原始数组 [[0, 0, 0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 1, 0]]
其中1代表位置(x,y)处存在点,0代表无点,可将该矩阵视为点云。
第二个数组是第一个数组的所有1元素沿同一方向平移相同步数得到的,部分1会移出数组范围,同时空余位置会出现新的1,示例如下:
# 平移后的数组 [[1, 0, 1, 0, 1, 0, 1, 0, 1], [0, 0, 0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 0, 1, 0, 0, 1, 0, 0]]
如上例中,第一个数组向下平移1行,第二数组新增第一行,原数组最后一行因平移消失。平移方向任意,但属于保持点间距离的刚性变换(rigid transformation)。
尝试过OpenCV的多种方法但未得到理想结果,请问是否有巧妙的方法可估计这两个数组间的最优warp matrix?
解决方案
针对这种纯平移的刚性变换场景,直接利用点集互相关或相位相关是最高效的方法,步骤如下:
1. 提取点坐标
首先从两个数组中提取所有值为1的坐标点集:
import numpy as np # 示例数组 arr1 = np.array([ [0, 0, 0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 0, 1, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0, 0, 1, 0] ]) arr2 = np.array([ [1, 0, 1, 0, 1, 0, 1, 0, 1], [0, 0, 0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 0, 0, 1], [1, 0, 0, 1, 0, 0, 1, 0, 0] ]) # 提取坐标 (y, x),numpy的where返回(行索引, 列索引)对应图像坐标系的(y, x) points1 = np.argwhere(arr1 == 1) points2 = np.argwhere(arr2 == 1)
2. 用相位相关计算平移量
相位相关基于傅里叶变换的平移不变性,能精准计算两个数组的平移偏移,即使存在部分点缺失/新增也能稳定工作:
from scipy.signal import correlate2d # 计算互相关 corr = correlate2d(arr1, arr2, mode='same') # 找到互相关峰值的位置 y_peak, x_peak = np.unravel_index(np.argmax(corr), corr.shape) # 转换为实际平移量(相对于数组中心的偏移) y_shift = y_peak - (arr1.shape[0] // 2) x_shift = x_peak - (arr1.shape[1] // 2) # 示例中arr1向下平移1行对应y_shift=1 print(f"平移量:y方向 {y_shift}, x方向 {x_shift}")
3. 构建Warp Matrix
2D平移对应的仿射变换矩阵(warp matrix)形式为:
[1 0 dx] [0 1 dy] [0 0 1]
其中dx是x方向平移量,dy是y方向平移量。根据计算出的偏移量直接构建:
# 构建3x3的变换矩阵(兼容OpenCV的仿射变换格式) warp_matrix = np.array([ [1, 0, x_shift], [0, 1, y_shift], [0, 0, 1] ], dtype=np.float32)
关键说明
- 相位相关的优势:无需特征匹配,通过整体信号的相关性找到最优偏移,对部分点不重叠的场景鲁棒性更强。
- 坐标方向注意:numpy数组索引是
(行, 列),对应图像坐标系的(y, x),平移量方向需和业务场景对应。 - OpenCV兼容:生成的
warp_matrix可直接传入cv2.warpAffine完成变换验证。
内容的提问来源于stack exchange,提问作者Watchdog
相关产品推荐
相关产品推荐

