OpenCV使用RANSAC的仿射变换估计 estimateAffine2D

本文介绍了如何在OpenCV中利用RANSAC算法进行仿射变换估计,由于OpenCV自带的findHomography仅适用于透视变换,而getAffineTransform又仅使用三对点,作者在研究源码后,基于SVN Trunk 2.32版本,自定义了一个仿射变换估计方法,以提高计算精度并解决估计问题。
摘要由CSDN通过智能技术生成

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 <
RANSACRandom Sample Consensus)算法是一种常用的模型估计算法,可以用于筛选出在数据集中符合某个模型的数据点,并用这些数据点去估计模型参数。在图像处理中,RANSAC算法可以用于筛选出在两幅图像中匹配的特征点,并用这些特征点去估计图像之间的仿射变换矩阵,从而实现图像间的坐标对齐。 以下是实现图像间坐标对齐的C++代码: ```c++ #include <opencv2/opencv.hpp> using namespace cv; int main() { // 读入两张待对齐的图像 Mat image1 = imread("image1.jpg"); Mat image2 = imread("image2.jpg"); // 提取图像特征点 Ptr<FeatureDetector> detector = ORB::create(); vector<KeyPoint> keypoints1, keypoints2; detector->detect(image1, keypoints1); detector->detect(image2, keypoints2); // 计算特征点的描述子 Ptr<DescriptorExtractor> extractor = ORB::create(); Mat descriptors1, descriptors2; extractor->compute(image1, keypoints1, descriptors1); extractor->compute(image2, keypoints2, descriptors2); // 匹配特征点 Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming"); vector<DMatch> matches; matcher->match(descriptors1, descriptors2, matches); // 筛选匹配点 vector<Point2f> points1, points2; for (int i = 0; i < matches.size(); i++) { points1.push_back(keypoints1[matches[i].queryIdx].pt); points2.push_back(keypoints2[matches[i].trainIdx].pt); } // 估计仿射变换矩阵 Mat H = Mat::zeros(2, 3, CV_64F); double ransacReprojThreshold = 3; H = estimateAffinePartial2D(points1, points2, noArray(), RANSAC, ransacReprojThreshold); // 对图像2进行仿射变换 Mat result; warpAffine(image2, result, H, image1.size()); // 显示图像对齐结果 namedWindow("Image1", WINDOW_NORMAL); namedWindow("Image2", WINDOW_NORMAL); namedWindow("Aligned Image2", WINDOW_NORMAL); imshow("Image1", image1); imshow("Image2", image2); imshow("Aligned Image2", result); waitKey(); return 0; } ``` 以上代码中,首先读入两张待对齐的图像,并使用ORB算法提取图像的特征点,并计算特征点的描述子。然后,使用BruteForce-Hamming算法进行特征点匹配,并筛选出匹配点。接着,使用RANSAC算法估计仿射变换矩阵,并将其应用到图像2上进行仿射变换,从而实现图像间的坐标对齐。最后,将三张图像显示在窗口中,以便观察对齐结果。 需要注意的是,上述代码中的特征点提取、描述子计算、特征点匹配和仿射变换矩阵估计都可以使用OpenCV库中的函数来实现,更加方便和高效。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值