OpenCV自带有findHomography这个用RANSAC随机采样求透视变换的方法,很好用,但是没有一个类似的求仿射的.
自带的getAffineTransform只是简单的使用三对点.
而estimateAffine3D使用的是三维坐标,转换起来有点不方便,而且我在使用中发现,即使把z坐标设置为0,有时候求出来的模型竟然100%都是内点,而且偏差很大.
只好研究了下OpenCV的源码,自己提取,封装了一下.用的是SVN的Trunk,主版本2.32
有几个改动:
1.OpenCV的estimator都是继承自CvModelEstimator2,而这个父类并不是导出类,所以只能把代码都再写一遍
2.据我观察,估计时内部用的是64位浮点数,增加计算精度,我把getAffineTransform也再写了一遍,对应64位精度
//Affine2D.hpp
class Affine2DEstimator
{
public:
Affine2DEstimator();
int runKernel( const CvMat* m1, const CvMat* m2, CvMat* model );
bool runRANSAC( const CvMat* m1, const CvMat* m2, CvMat* model,
CvMat* mask, double threshold,
double confidence=0.99, int maxIters=2000 );
bool getSubset( const CvMat* m1, const CvMat* m2,
CvMat* ms1, CvMat* ms2, int maxAttempts=1000 );
bool checkSubset( const CvMat* ms1, int count );
int findInliers( const CvMat* m1, const CvMat* m2,
const CvMat* model, CvMat* error,
CvMat* mask, double threshold );
void computeReprojError( const CvMat* m1, const CvMat* m2, const CvMat* model, CvMat* error );
protected:
CvRNG rng;
int modelPoints;
CvSize modelSize;
int maxBasicSolutions;
bool checkPartialSubsets;
};
int estimateAffine2D(cv::InputArray _from, cv::InputArray _to,
cv::OutputArray _out, cv::OutputArray _inliers,
double param1=3, double param2=0.99);
int Affine2DEstimator::findInliers( const CvMat* m1, const CvMat* m2,
const CvMat* model, CvMat* _err,
CvMat* _mask, double threshold )
{
int i, count = _err->rows*_err->cols, goodCount = 0;
const float* err = _err->data.fl;
uchar* mask = _mask->data.ptr;
computeReprojError( m1, m2, model, _err );
threshold *= threshold;
for( i = 0; i <