MVG读书笔记——单应矩阵估计这件小事(三)
来源:互联网 发布:linux怎么添加拼音 编辑:程序博客网 时间:2024/06/07 20:33
坐标变换下的不变性
实际应用中,不同程序对于坐标原点的规定可能不同,坐标系的尺度也可能不同。于是很自然会有一个问题,在这些情况下我们通过两幅图像的对应点求解出的单应矩阵还是同一个么?即单应矩阵有没有不变性?
用更加正式点语言表述如下:
假设一幅图像中的点x在另外一套坐标系中表示方法为
考虑
于是可以得到
于是,从新的坐标
那么问题来了,对于任意的
DLT算法的不变性
考虑一系列对应点集合
DLT算法是否能从
如上节一样,定义
其中
对于相似变换
将
R为正交矩阵,所以R不改变向量的范数,于是
用代数误差来表示就是
由此,我们发现对于同样的代数误差(相差一个尺度),可以推导出一组对应的H和
因为在DLT算法求解时为了使得方程有唯一解我们添加了一项约束
事实上,它们不满足简单的对应关系,就是说
因此我们说坐标的变换会导致不同的解。只有当||Ah||不随坐标变换而变换时我们可以找出H与
几何误差的不变性
使用最小化几何误差的方法来寻找H,对于相似变换具有不变性。如前面提到的,考虑一系列对应点集合
这是显然的,因为欧式变换不改变长度(距离)。因此它们最小化的是同一个东西,求出来的H也是双射的,即最小化几何误差对于欧式变换具有不变性。
对于相似变换,几何误差之间显然相差一个相似系数。计算出的
标准化变换
正如开始所讲,DLT算法得出的单应取决于坐标框架,它对于相似变换不具有不变性。也就是说某个坐标框架中计算出的H要好于另外一个框架中计算出的H。为了减少甚至消除这一点的影响,我们在执行DLT算法之前需要进行标准化。
对一幅图像中所有点进行标准化,使得它们的中心移到坐标原点,同时使得它们与坐标原点的平均距离等于
这样的做法使得各种坐标框架上的点被变换到了同一套坐标系下,再进行DLT算法,就使得它有了相似变换不变性。
由此,我们对DLT算法进行改进:
1)对x进行标准化,变换记作T
2)对x’进行标准化,T’
3)DLT算法
4)反标准化。
于是得到了H。
附录:OpenCV里面的求解算法
可以看到,OpenCV使用的单应矩阵的求解算法就是上面所说的方法
int runKernel( InputArray _m1, InputArray _m2, OutputArray _model ) const{ Mat m1 = _m1.getMat(), m2 = _m2.getMat(); int i, count = m1.checkVector(2); const Point2f* M = m1.ptr<Point2f>(); const Point2f* m = m2.ptr<Point2f>(); double LtL[9][9], W[9][1], V[9][9]; Mat _LtL( 9, 9, CV_64F, &LtL[0][0] ); Mat matW( 9, 1, CV_64F, W ); Mat matV( 9, 9, CV_64F, V ); Mat _H0( 3, 3, CV_64F, V[8] ); Mat _Htemp( 3, 3, CV_64F, V[7] ); Point2d cM(0,0), cm(0,0), sM(0,0), sm(0,0); for( i = 0; i < count; i++ ) { cm.x += m[i].x; cm.y += m[i].y; cM.x += M[i].x; cM.y += M[i].y; } cm.x /= count; cm.y /= count; cM.x /= count; cM.y /= count; for( i = 0; i < count; i++ ) { sm.x += fabs(m[i].x - cm.x); sm.y += fabs(m[i].y - cm.y); sM.x += fabs(M[i].x - cM.x); sM.y += fabs(M[i].y - cM.y); } if( fabs(sm.x) < DBL_EPSILON || fabs(sm.y) < DBL_EPSILON || fabs(sM.x) < DBL_EPSILON || fabs(sM.y) < DBL_EPSILON ) return 0; sm.x = count/sm.x; sm.y = count/sm.y; sM.x = count/sM.x; sM.y = count/sM.y; double invHnorm[9] = { 1./sm.x, 0, cm.x, 0, 1./sm.y, cm.y, 0, 0, 1 }; double Hnorm2[9] = { sM.x, 0, -cM.x*sM.x, 0, sM.y, -cM.y*sM.y, 0, 0, 1 }; Mat _invHnorm( 3, 3, CV_64FC1, invHnorm ); Mat _Hnorm2( 3, 3, CV_64FC1, Hnorm2 ); _LtL.setTo(Scalar::all(0)); for( i = 0; i < count; i++ ) { double x = (m[i].x - cm.x)*sm.x, y = (m[i].y - cm.y)*sm.y; double X = (M[i].x - cM.x)*sM.x, Y = (M[i].y - cM.y)*sM.y; double Lx[] = { X, Y, 1, 0, 0, 0, -x*X, -x*Y, -x }; double Ly[] = { 0, 0, 0, X, Y, 1, -y*X, -y*Y, -y }; int j, k; for( j = 0; j < 9; j++ ) for( k = j; k < 9; k++ ) LtL[j][k] += Lx[j]*Lx[k] + Ly[j]*Ly[k]; } completeSymm( _LtL ); eigen( _LtL, matW, matV ); _Htemp = _invHnorm*_H0; _H0 = _Htemp*_Hnorm2; _H0.convertTo(_model, _H0.type(), 1./_H0.at<double>(2,2) ); return 1;}
- MVG读书笔记——单应矩阵估计这件小事(三)
- MVG读书笔记——单应矩阵估计这件小事(一)
- MVG读书笔记——单应矩阵估计这件小事(二)
- MVG读书笔记——单应矩阵估计这件小事(四)
- MVG读书笔记——射影变换的校正(三)
- MVG读书笔记——射影变换的校正(零)
- MVG读书笔记——射影变换的校正(一)
- MVG读书笔记——射影变换的校正(二)
- MVG读书笔记——三维空间中的射影几何(一)
- MVG读书笔记——三维空间中的射影几何(二)
- MVG读书笔记——几何变换
- MVG读书笔记——几何变换续
- MVG读书笔记——齐次坐标与射影几何
- MVG读书笔记——射影几何下的直线
- MVG读书笔记——射影几何下的二次曲线
- MVG读书笔记——三维空间中的欧氏变换
- MVG读书笔记——求解结果的评价
- MVG读书笔记
- P, NP, NP-complete, NP hard问题
- 1073: 级数求和
- OpenCV,在图像中,直观显示HOG特征值
- 重载的可加减乘的点(向量)模板
- 笔试_java基础4
- MVG读书笔记——单应矩阵估计这件小事(三)
- 机器学习之SVM
- 算法分析第一周
- centos6和centos7忘记了root密码怎么办
- 通过读写PEB.Ldr实现模块枚举和模块隐藏(脱链)
- 购物车结算
- 2017/10/09 think
- luoguP1903 数颜色(通过一道题认识带修改莫队)
- dataguard broker failover 配置