H矩阵求取旋转和平移分量

最近在做机器人导航项目,于是就顺手在OpenCV里面将以前看过但是不太理解的从Homography求Rotation和Translation实现了一下

代码如下:

 

[cpp]  view plain copy
  1. int calcRTfromHomo(CvMat* H, double t[3], double rodrot[3]){  
  2.       
  3.     double r[9];  
  4.     CvMat _r = cvMat(3, 3, CV_64F, r);          //rotation matrix  
  5.     double intrinsic[9]={1, 0, 0, 0, 1, 0, 0, 0, 1};  
  6.     CvMat _M = cvMat(3, 3, CV_64F, intrinsic); //intrinsic matrix, of no use in this implementation, reserved for future use  
  7.     double ones[]={1,1,1};  
  8.     CvMat _ones = cvMat(3, 1, CV_64F, ones);      
  9. //  double rodrot[3];  
  10.     CvMat _rodrot = cvMat(3, 1, CV_64F, rodrot);  
  11.     //for SVD  
  12.     CvMat* U = cvCreateMat(3, 3, CV_64F);  
  13.     CvMat* W = cvCreateMat(3, 3, CV_64F);  
  14.     CvMat* V = cvCreateMat(3, 3, CV_64F);  
  15.     CvMat* invM = cvCreateMat(3, 3, CV_64F);  
  16.     // three columns of Homography matrix  
  17.     CvMat* h1 = cvCreateMat(3, 1, CV_64F);  
  18.     CvMat* h2 = cvCreateMat(3, 1, CV_64F);  
  19.     CvMat* h3 = cvCreateMat(3, 1, CV_64F);  
  20.     // three columns of rotation matrix  
  21.     CvMat* r1 = cvCreateMat(3, 1, CV_64F);  
  22.     CvMat* r2 = cvCreateMat(3, 1, CV_64F);  
  23.     CvMat* r3 = cvCreateMat(3, 1, CV_64F);  
  24.     // translation vector  
  25.     CvMat _t =  cvMat(3, 1, CV_64F, t);   
  26.     cvGetCol(H,h1,0);  
  27.     cvGetCol(H,h2,1);  
  28.     cvGetCol(H,h3,2);  
  29.     cvGetCol(&_r,r1,0);  
  30.     cvGetCol(&_r,r2,1);  
  31.     cvGetCol(&_r,r3,2);  
  32.       
  33.     cvInvert(&_M, invM);  
  34.     cvMatMul(invM,h1,r1);  
  35.     cvMatMul(invM,h2,r2);  
  36.     cvMatMul(invM,h3,&_t);  
  37.       
  38.     cvNormalize(r1, r1);  
  39.     cvMul(r2,&_ones,r2,1/cvNorm(r1));  
  40.     cvMul(&_t,&_ones, &_t,1/cvNorm(r1) );  
  41.     cvCrossProduct(r1, r2, r3);  
  42.     cvSVD(&_r, W, U, V, CV_SVD_V_T);  
  43.     cvMatMul(U,V,&_r);  
  44.     cvRodrigues2(&_r, &_rodrot, NULL);  
  45.     return 1;  
  46. }  

 


代码原理的话可以参考[1],实现的时候还碰到了一个小问题,即Rotation矩阵三列归一化的时候都是除以第一列矩阵的Norm,当时自己实现的时候没有发现,误用了三列各自的Norm,结果一直没有找到错误,后来参考了[2]的代码才得以解决。

 

函数的输出一个是Translation 向量,另一个是Rodrigues变换之后的向量,该向量的方向代表旋转轴,模代表旋转的角度,具体数学表示见参考[3].

 

函数中的输入Homography矩阵,可以用cvFindHomography求出。至于如何从特征点求得Homography可以参考opencv2.0里find_obj例程的下面这段代码:

 

[c-sharp]  view plain copy
  1. if( !cvFindHomography( &_pt1, &_pt2, &_h, CV_RANSAC, 5 ))  
  2.     return 0;  

 

下面是上面这个函数的一个应用,也是正在进行中的一个工作:(sigh, csdn博客竟然不支持嵌入式视频功能。。。太不给力了,真的是要找下家了。。)

墙外的可以点击:http://www.youtube.com/watch?v=YjrTFO0ftDQ

墙内的youku视频正在上传。。。这里上传好慢。。。

 

 

视频是一个移动机器人在遥控器控制下用BumbleBee2立体摄像头拍的一段视频处理后的结果。

下面是iRobot机器人平台,低角度拍摄很是霸气哈哈。上面有很多传感器,我只用了BumbleBee2:

 

 

 

目前的话,还有两个问题:

 

1. 一个由于SURF点是每个frame都要重新计算的,因此计算出来Homography矩阵不一定准确,表现在视频上的话会产生映射的抖动(见视频mapping的框),而且在特征点比较少的时候,这种抖动尤为明显(可以见当机器人从室内转到走廊这段,由于走廊的SURF点明显减少,映射框剧烈抖动)。这种抖动用optical flow应该可以解决。不过在目前应用中应该也不是特别大的问题,而且个人认为这种连续性需要到scene understanding这个更高的层次解决,而不是死抠这里一些只关注细节的方法。

 

 

2. 另外一个问题是关于Rotation向量的,从这段视频中可以提取出50个连续的场景(目前程序里不同场景的定义两个场景之间匹配的SURF点小于整个场景SURF点的1/8,这个参数是可调的),不同场景之间的旋转和平移量见下图:

 

可以看出场景之间的切换基本都是Translation(T向量的z都是1,所以我省略了), Rotation的量很小(最大也只不过是0.2弧度左右),这与机器人在场景里面的运动相符

但是可以看Rotation向量,计算出来的值似乎是显示所有的旋转都是绕着第三个量也就是Z轴进行的,而在实际过程中,旋转似乎是主要绕着Y轴进行的。

当然根据这个结果我们可以大致绘制出机器人的行进路线图,背后的原理似乎还有点那么不通,感觉这是由于我对于Affine Space和Othodogical Space没有完全理解导致的。求高人解答。

 

*******************************************************************

 

刚刚去问了老师。。。整个彻底错了。。。立体的场景不是一个平面,中间的点是不能用Homography来映射的,这个地方是需要用Fundamental矩阵的。这也是为什么Homography抖动以及求出Rotation Translation有误的原因。

 

基础不牢,地动山摇,本文权当反面教材吧。

 

********************************************************************

再补充20110525:

经验证 利用宽松限制(比如允许误差在10像素以内)的RANSAC求Homography是可以粗略筛选outlier匹配对的,效果比用RANSAC做FindFundmental好。因为Homography在两幅视图里是点对应,而Fundamental在两幅视图里是点和极线对应

 

_________________________________________________________________

 

Reference:

[1]. Chapter 11, Learning OpenCV: P384-P391

[2]. https://gist.github.com/740979

[3]. http://opencv.willowgarage.com/documentation/camera_calibration_and_3d_reconstruction.html#rodrigues2

<think>嗯,用户想要了解旋转矩阵平移的实现方法以及相关资料。首先,我需要回忆一下相关的线性代数知识,特别是三维空间中的变换。旋转矩阵通常用来描述物体绕某个坐标轴的旋转,而平移则是将物体沿着某个方向移动一定距离。不过,平移在齐次坐标下才能用矩阵表示,否则只能用向量加法。 根据引用[1],旋转矩阵平移矩阵相乘可以得到一个组合变换矩阵,但需要注意顺序。比如先旋转平移平移旋转结果可能不同。引用[3]提到,变换矩阵T由旋转矩阵R平移向量t组成,通常表示为块矩阵的形式。当需要矩阵时,可以通过分块矩阵的逆来简化计算,如R的逆-R^T*t的组合。 用户可能需要具体的实现步骤,比如如何用代码构建这样的变换矩阵。例如,在OpenCV中,可能会用到Rodrigues函数将旋转向量转换为旋转矩阵。同时,引用[3]中的代码示例展示了如何从变换矩阵中提取旋转平移部分,以及如何通过两种方法计算相机在二维码坐标系下的坐标。 还需要注意齐次坐标的使用,这样才能将旋转平移统一到一个4x4的矩阵中。此外,投影矩阵的推导可能涉及将点投影到某个平面或直线上,如引用[2]中的投影矩阵公式,但用户的问题主要集中在旋转平移,所以可能不需要深入投影部分。 用户的问题可能涉及到三维刚体变换,包括旋转平移的组合。需要解释清楚变换矩阵的结构,以及如何分解变换矩阵得到旋转平移分量。另外,应用场景如AR/VR、机器人定位中的坐标变换可能也是用户关心的点。 最后,确保回答中正确引用提供的参考资料,并生成相关问题,帮助用户进一步探索。</think>### 旋转矩阵平移的实现方法 #### 1. **旋转矩阵平移的基础概念** - **旋转矩阵**:描述三维空间中绕坐标轴的旋转变换,例如绕$Y$轴旋转$\theta$角的矩阵为: $$ R_Y(\theta) = \begin{pmatrix} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{pmatrix} $$ 旋转矩阵是正交矩阵,满足$R^T R = I$[^1]。 - **平移向量**:表示物体在空间中的位移,如平移向量$t = (t_x, t_y, t_z)^T$。平移无法直接用3×3矩阵表示,需通过齐次坐标扩展为4×4矩阵。 #### 2. **组合旋转平移的变换矩阵** 在齐次坐标系下,旋转矩阵$R$平移向量$t$可合并为4×4变换矩阵: $$ T = \begin{pmatrix} R & t \\ 0 & 1 \end{pmatrix} $$ 该矩阵可实现“先旋转平移”的操作。例如,引用[3]中提到的二维码坐标系到相机坐标系的变换矩阵即为此形式。 #### 3. **实现方法** - **代码示例(C++/OpenCV)**: ```cpp // 构造旋转矩阵R平移向量t Mat R, t; Rodrigues(rotation_vector, R); // 将旋转向量转为旋转矩阵 Mat T = Mat::eye(4, 4, CV_64F); R.copyTo(T(Rect(0, 0, 3, 3))); // 填充旋转部分 t.copyTo(T(Rect(3, 0, 1, 3))); // 填充平移部分 // 从变换矩阵提取旋转平移 Mat extracted_R = T(Rect(0, 0, 3, 3)); Mat extracted_t = T(Rect(3, 0, 1, 3)); ``` 引用[3]中通过`getRTMatrix()`获取变换矩阵,并通过逆矩阵计算坐标系的转换。 - **坐标系变换公式**: - 若已知点$P$在坐标系A下的坐标为$P_A$,则其在坐标系B下的坐标为: $$ P_B = R \cdot P_A + t $$ - 逆变换(坐标系B到A)为: $$ P_A = R^{-1} \cdot (P_B - t) = R^T \cdot (P_B - t) $$ 引用[3]中`pose2 = R.inv()*(-t)`即为此原理的应用。 #### 4. **应用场景** - **AR/VR定位**:通过二维码(如ArUco码)的旋转矩阵平移向量计算相机位姿[^3]。 - **机器人导航**:利用变换矩阵实现地图坐标系与传感器坐标系的转换。 - **三维重建**:将多视角的点云通过旋转平移对齐到统一坐标系。 --- ###
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值