对三维点集的归一化变换

1. 前言

昨天处理实验室的数据,处理了整整一天, 都没有出来理想的结果, 后来调试发现, 出现了两个问题:
1. 非线性优化中传入的计算参数传错了。
2. 程序中使用各项同性的归一化方法出来的结果, 比非各项同性归一化出来的结果明显要好。

2. 归一化变换

在计算 2D 单应矩阵 H 的时候, 一定存在某些坐标系表示的方式明显优于其他坐标系, 对于3D 空间中的数据变化计算他们之间的 H=(R0TT1) 也有类似的特性, 我们下面按照2D 空间变化进行讨论。

2.1 各向同性缩放 2D

  1. 每幅图像中的坐标进行平移, 使得点集的形心移动至原点
  2. 对坐标系进行缩放, 使得点中 x=(x,y,w)T中的x, y, w 总体上有一样的平均值, 选用一个各向同性的缩放因子, 使得一个点的 坐标等量缩放, 我们令 平均点为 (1,1,1)T, 此时缩放因子使得x 到 原点距离为 2。 同理, 如果是3D 点, 平均点应该为 (1,1,1,1)T, 此时, x 到原点的距离应该为 (3)

2.2 归一化变换的意义

数据归一化, 可以提高结果的精度, 同时, 归一化算法对于任何尺度缩放和坐标原点的选择都是不变的。
我们可以这样去理解: 归一化为测量数据选择了有效的标准坐标系, 预先消除了坐标变换的影响。因此, 在做类似DLT 的相关运算的时候, 代数最小化的过程其实是在一个固定的标准坐标系下进行的, 从而, DLT 算法实际上关于相似变换是不变的。
数据归一化的过程在类似 DLT 的算法中的效果是实质性的, 不能不要视他为可有可无的。

2.3 非各向同性缩放

理论上, 我们也可以进行非各向同性的归一化方法, 效果是不会比各向同性的缩放有显著提高。可是,我们这里的效果不是提高了, 而是下降了, 鉴于这个结果, 我们还是最好就采用各项同性的归一化方法好了。

2.4 归一化变换code

%% 实验室师兄的版本
function [T] = normalize(w)
    % 变换目标:中心在原点且到原点的平均距离为sqrt(3)
    if  size(w,1)<size(w,2)
        w = w';
    end
    t = -mean(w(:,1:3),1);
    w = w(:,1:3) + repmat(t,[size(w,1),1]);
    dis = mean(sqrt(w(:,1).*w(:,1)+w(:,2).*w(:,2)+w(:,3).*w(:,3)));
    v = sqrt(3)/dis;
    t = t'*v;
    T = [eye(3)*v,t];
    T = [T;0,0,0,1];
end
%% normalize A 我的版本
function [T] = normalize(A)
     assert(size(A, 1) == 4, 'A should be 4 x n')
     mean_A = mean(A,2);
     remain = A - repmat(mean_A, [1, size(A, 2)]);
     remain_pt = remain(1:3, :);
     dis = mean(sqrt(remain_pt(1, :).*remain_pt(1, :) + remain_pt(2, :).*remain_pt(2, :) + remain_pt(3, :).*remain_pt(3, :)));
     diag_diag_T_A = repmat(sqrt(3)/dis, [3, 1]);
     T_A = diag([diag_diag_T_A ;1])*...
        [1 0 0 -mean_A(1)
         0 1 0 -mean_A(2)
         0 0 1 -mean_A(3)
         0 0 0 1];
end
<think>我们已知三点变换前后的三维坐标,需要求解位姿变换的齐次矩阵。位姿变换通常包括旋转和平移,可以用一个4x4的齐次变换矩阵表示。假设我们有三个点A、B、C,变换坐标为A1, B1, C1,变换坐标为A2, B2, C2。 齐次变换矩阵H的形式如下: [ R T ] [ 0 1 ] 其中R是3x3的旋转矩阵,T是3x1的平移向量。 对于每个点,变换关系为:P2 = R * P1 + T (在齐次坐标下,用矩阵乘法表示为 [P2;1] = H * [P1;1]) 我们有三对点,理论上可以建立9个方程(每个点三个分量),而旋转矩阵R有9个参数(但实际是正交矩阵,有约束),平移向量T有3个参数,共12个参数。但旋转矩阵的自由度只有3(例如欧拉角),所以实际上我们只需要6个独立方程(每个点提供两个独立方程,因为三个点不能共线,否则信息不足)。然而,我们有三组点,每组点可以建立三个方程,共9个方程,但其中只有6个是独立的(因为旋转矩阵是正交的,有约束条件)。 因此,我们需要利用最小二乘或其他优化方法,或者通过构造超定方程组来求解。 但是,我们可以利用以下方法:选取三个点构成一个平面,我们可以通过这三个点建立一个局部坐标系,然后通过变换前后两个局部坐标系之间的关系来求解变换矩阵。 具体步骤: 1. 在变换前的三个点A1, B1, C1上建立局部坐标系: 设原点为A1。 X轴方向:B1 - A1,并归一化得到单位向量x1。 Y轴方向:取向量(C1-A1)在垂直于x1的平面上的投影,并归一化得到y1。 Z轴方向:x1与y1的叉积得到z1(并归一化)。 这样得到变换前的局部坐标系1的基向量矩阵R1 = [x1, y1, z1](3x3正交矩阵)。 2. 同理,在变换后的三个点A2, B2, C2上建立局部坐标系: 原点为A2。 X轴方向:B2 - A2,归一化得到x2。 Y轴方向:取向量(C2-A2)在垂直于x2的平面上的投影,归一化得到y2。 Z轴方向:x2与y2的叉积得到z2。 得到变换后的局部坐标系2的基向量矩阵R2 = [x2, y2, z2]。 3. 那么,从局部坐标系1到世界坐标系(即我们给定的坐标所在的坐标系)的变换矩阵为: H1 = [R1, A1; 0,0,0,1] (注意:这里H1表示将局部坐标系1的点变换到世界坐标系,即P_world = R1 * P_local1 + A1) 同理,局部坐标系2到世界坐标系的变换矩阵为: H2 = [R2, A2; 0,0,0,1] 4. 现在,我们考虑同一个点,在局部坐标系1中的坐标(记为P_local1)与在局部坐标系2中的坐标(记为P_local2)应该是相同的(因为三个点构成的刚体在局部坐标系中的相对位置不变)。因此,同一个点在世界坐标系中的坐标有两种表示: P_world = H1 * [P_local1; 1] (从局部坐标系1变换而来) P_world = H2 * [P_local2; 1] (从局部坐标系2变换而来) 而P_local1 = P_local2(因为刚体不变形),所以有: H1 * [P_local; 1] = H2 * [P_local; 1] 因此,H1=H2?这显然不对,因为两个局部坐标系定义在不同的世界坐标系点上。 实际上,我们要求的是从变换前的世界坐标系(记为世界系1)到变换后的世界坐标系(记为世界系2)的变换矩阵H,满足: P2 = H * P1 (其中P1和P2都是世界坐标系下的齐次坐标,即P1=[x1,y1,z1,1]',P2=[x2,y2,z2,1]') 而通过局部坐标系,我们可以这样理解: 点P在变换前在世界系1中的坐标可以表示为:P1 = R1 * P_local + A1 变换后,该点在世界系2中的坐标为:P2 = R2 * P_local + A2 那么,我们要求一个变换H,使得P2 = H * P1(齐次坐标形式) 将P1和P2用P_local表示: P1 = [R1, A1; 0,0,0,1] * [P_local; 1] => [P_local;1] = inv([R1, A1; 0,0,0,1]) * P1 P2 = [R2, A2; 0,0,0,1] * [P_local; 1] => P2 = [R2, A2; 0,0,0,1] * inv([R1, A1; 0,0,0,1]) * P1 因此,H = [R2, A2; 0,0,0,1] * inv([R1, A1; 0,0,0,1]) 所以,我们只需要计算: H = H2 * inv(H1) 其中H1和H2分别是两个局部坐标系到各自世界坐标系的齐次变换矩阵。 注意:这里H1和H2都是4x4矩阵,求逆时可以利用分块矩阵的性质: H1 = [R1, T1; 0,1] 的逆为 [R1', -R1'*T1; 0,1] 因此,我们可以这样计算: H = [R2, A2; 0,0,0,1] * [R1', -R1'*A1; 0,0,0,1] = [R2*R1', -R2*R1'*A1 + A2; 0,0,0,1] 这样我们就得到了变换矩阵H。 但是,这种方法依赖于三个点构成的局部坐标系,要求三个点不共线。如果共线,则无法建立局部坐标系(因为y轴方向无法确定)。 另一种方法是直接求解方程:对于每一对点,我们有: P2 = R * P1 + T 我们可以先求解旋转矩阵R,再求解平移向量T。但是,由于有三个点,我们可以先消除平移向量T。 具体步骤: 1. 计算变换前后两个点的中心(质心): center1 = (A1+B1+C1)/3 center2 = (A2+B2+C2)/3 2. 将每个点减去中心,得到去中心化的坐标: A1c = A1 - center1 B1c = B1 - center1 C1c = C1 - center1 A2c = A2 - center2 B2c = B2 - center2 C2c = C2 - center2 3. 现在,问题转化为求解旋转矩阵R,使得:A2c ≈ R*A1c, B2c≈R*B1c, C2c≈R*C1c 4. 我们可以通过最小二乘法求解R。具体地,我们构造一个3x3矩阵: M = A1c * A2c' + B1c * B2c' + C1c * C2c' 5. 对M进行奇异值分解(SVD): [U, S, V] = svd(M) 6. 则旋转矩阵R为: R = V * U' 7. 注意:如果点是刚体变换,那么V*U'应该是正交矩阵(行列式为1)。但如果有噪声或者点有误差,可能行列式为负,此时我们需要取校正: R = V * diag([1,1,det(V*U')]) * U' (但通常我们使用:如果det(R)<0,则取R = V * diag([1,1,-1]) * U') 8. 然后计算平移向量T: T = center2 - R * center1 9. 最后,齐次变换矩阵为: H = [ R, T; 0,0,0,1 ] 这种方法称为Kabsch算法,用于求解最优旋转矩阵(最小二乘意义)。 在MATLAB中,我们可以实现如下: 步骤: 1. 输入:三个变换前的点:P1, P2, P3(每个点为3x1向量),变换后的点:Q1, Q2, Q3。 2. 计算中心: centerP = (P1+P2+P3)/3; centerQ = (Q1+Q2+Q3)/3; 3. 计算去中心化的坐标: P1c = P1 - centerP; P2c = P2 - centerP; P3c = P3 - centerP; Q1c = Q1 - centerQ; Q2c = Q2 - centerQ; Q3c = Q3 - centerQ; 4. 构造矩阵M: M = P1c * Q1c' + P2c * Q2c' + P3c * Q3c'; 5. 对M进行SVD分解: [U, S, V] = svd(M); 6. 计算旋转矩阵R: R = V * U'; % 确保旋转矩阵是右手系(行列式>0) if det(R) < 0 % 如果行列式为负,则调整 V(:,3) = -V(:,3); % 将V的第三列取负 R = V * U'; end 7. 计算平移向量T: T = centerQ - R * centerP; 8. 构造齐次变换矩阵: H = [R, T; 0,0,0,1]; 注意:这种方法要求三个点不共线,否则M的秩小于3,无法得到正确的旋转矩阵。 根据问题,我们使用第二种方法(Kabsch算法)来求解,因为它更常用且更稳定。 下面用MATLAB代码实现: 假设我们有三组点,变换前为p1, p2, p3(列向量),变换后为q1, q2, q3(列向量)。</think>### 求解位姿变换齐次矩阵的方法 在机器人学和三维空间变换中,齐次变换矩阵用于描述刚体的旋转和平移。给定三点变换前后的三维坐标,可以通过以下步骤求解位姿变换的齐次矩阵: #### 数学原理 设变换前三点坐标为 $A_1, B_1, C_1 \in \mathbb{R}^3$,变换坐标为 $A_2, B_2, C_2 \in \mathbb{R}^3$。齐次变换矩阵 $H$ 满足: $$ H \begin{bmatrix} A_1 \\ 1 \end{bmatrix} = \begin{bmatrix} A_2 \\ 1 \end{bmatrix},\quad H \begin{bmatrix} B_1 \\ 1 \end{bmatrix} = \begin{bmatrix} B_2 \\ 1 \end{bmatrix},\quad H \begin{bmatrix} C_1 \\ 1 \end{bmatrix} = \begin{bmatrix} C_2 \\ 1 \end{bmatrix} $$ 其中 $H$ 的形式为: $$ H = \begin{bmatrix} R & T \\ 0 & 1 \end{bmatrix} $$ $R$ 是 3×3 旋转矩阵,$T$ 是 3×1 平移向量。 #### 求解步骤 1. **构造坐标矩阵** 定义齐次坐标矩阵: $$ P = \begin{bmatrix} A_1 & B_1 & C_1 \\ 1 & 1 & 1 \end{bmatrix},\quad Q = \begin{bmatrix} A_2 & B_2 & C_2 \\ 1 & 1 & 1 \end{bmatrix} $$ 则方程简化为 $HP = Q$。 2. **最小二乘解** 当三点不共线时,$P$ 满秩,可直接求解: $$ H = Q P^{\dagger} $$ 其中 $P^{\dagger} = P^T (PP^T)^{-1}$ 是 $P$ 的伪逆。 3. **分解旋转和平移** 从 $H$ 中提取: $$ R = H(1:3, 1:3),\quad T = H(1:3, 4) $$ #### MATLAB 实现代码 ```matlab function H = compute_homogeneous_matrix(points_before, points_after) % 输入: points_before - 3×3矩阵, 每列是变换坐标 [A1,B1,C1] % points_after - 3×3矩阵, 每列是变换坐标 [A2,B2,C2] % 输出: H - 4×4齐次变换矩阵 % 构造齐次坐标矩阵 P = [points_before; ones(1,3)]; % 4×3 Q = [points_after; ones(1,3)]; % 4×3 % 最小二乘求解 H * P = Q H = Q / P; % 等价于 Q * pinv(P) % 验证结果 (可选) error = norm(H * P - Q, 'fro'); if error > 1e-6 warning('求解误差较大: %e', error); end end ``` #### 使用示例 ```matlab % 定义变换前后的三点坐标 (列向量) before = [0, 1, 0; % A1(x,y,z) 0, 0, 1; 0, 0, 0]; after = [1, 2, 1; % A2(x,y,z) 0, 0, 1; 0, 0, 0]; % 计算齐次变换矩阵 H = compute_homogeneous_matrix(before, after); % 显示结果 disp('齐次变换矩阵 H:'); disp(H); ``` #### 验证方法 1. **正交性检查**:旋转矩阵 $R$ 应满足 $R^T R = I$ 且 $\det(R) \approx 1$ 2. **点变换验证**:$H \begin{bmatrix} A_1 \\ 1 \end{bmatrix}$ 应接近 $A_2$ #### 注意事项 1. 三点需**不共线**,否则矩阵 $P$ 秩不足 2. 若存在噪声,建议使用 SVD 分解优化: ```matlab [U,S,V] = svd(P); H = Q * V * diag(1./diag(S)) * U'; ``` 3. 旋转矩阵需满足正交性,可通过 SVD 修正: ```matlab [U,~,V] = svd(R); R_corrected = U * V'; ``` ### 相关问题 1. **如何验证齐次变换矩阵的精度?** 可通过计算变换坐标与目标坐标的均方误差(MSE)验证: ```matlab transformed = H * P; mse = mean(sum((transformed(1:3,:) - points_after).^2, 1)); ``` 2. **当三点共线时如何求解?** 需额外引入一个非共线点,或使用带约束的优化方法(如 SVD 结合正则化)。 3. **齐次矩阵如何分解为旋转和平移分量?** 直接提取矩阵块: ```matlab R = H(1:3, 1:3); % 旋转矩阵 T = H(1:3, 4); % 平移向量 ``` 4. **如何将齐次矩阵转换为欧拉角/四元数?** 使用 MATLAB 内置函数: ```matlab eul = rotm2eul(R); % 旋转矩阵→欧拉角 quat = rotm2quat(R); % 旋转矩阵→四元数 ``` 5. **位姿变换在机器人运动学中有何应用?** 用于描述机械臂末端执行器的位姿变化,实现坐标系的转换[^1][^2]。例如在 PUMA 机器人中,通过齐次矩阵计算关节运动后的末端位置[^3]。 [^1]: 坐标平移、旋转和刚体变换的描述方法 [^2]: 使用齐次变换矩阵进行机器人正运动学求解 [^3]: 机器人运动过程中末端齐次矩阵的实时计算 [^4]: 基于欧拉角生成齐次变换矩阵的 MATLAB 函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值