opencv 图像处理 最小二乘法 仿射变换 详解

在标定时常用到仿射变换,但Opencv中放射变换仅支持三对点作为参数。遇到需要多点标定的情况则需要最小二乘法的仿射变换了。

原opencv中 获取仿射变换的函数getAffineTransform() 的用法如下

vector<Point2f> sro={Point2f(0,0),Point2f(1,0),Point2f(0,1)};

vector<Point2f> dst{Point2f(0,0),Point2f(10,0),Point2f(0,10)};

Mat AffineTransform=getAffineTransform(sro, dst);

其中得到的AffineTransform就是2x3的仿射变换矩阵。

 

接下来介绍如何获得要最小二乘法的仿射变换矩阵。

若要解 A  x = b 中的x。

使用常规超定矩阵解法 具体如下:

1.两边同时加乘 A^t (A^t表示A的转置)

有:A^t  A x =A^t b

2.使x侧(A^t  A)消去,再增乘(At A)^-1

有 (At  A)^-1 (A^t  A) x=(At  A)^-1 A^t b        

左侧 (At  A)^-1 (A^t  A)消去后

即有:x=(At  A)^-1 A^t b

由此得出仿射矩阵的最小二乘法解 x。

用C++和OpenCV代码实现如下:

cv::Mat text233(const vector<cv::Point2f> src, const vector<cv::Point2f> dst)
{
	int n_Points = MIN(src.size(), dst.size());
	cv::Mat_<float> Mat_x;//数量不足时,返回单位矩阵
	Mat_x = (cv::Mat_<float>(2, 3) << 1, 0, 0, 0, 1, 0);
	if (n_Points >= 3)
	{
		//超定方程组求解 A x=b =====> (At A)-1 (At A) x =(At A)-1 At b =====> I x =(At A)-1 At b;
		cv::Mat_<float> Mat_A = cv::Mat(n_Points, 3, CV_32FC1, cv::Scalar(0));
		cv::Mat_<float> Mat_b = cv::Mat(n_Points, 2, CV_32FC1, cv::Scalar(0));
		for (int i = 0; i < n_Points; i++)
		{
			Mat_A(i, 0) = src[i].x;
			Mat_A(i, 1) = src[i].y;
			Mat_A(i, 2) = 1;

			Mat_b(i, 0) = dst[i].x;
			Mat_b(i, 1) = dst[i].y;
		}
		Mat_x = (Mat_A.t() * Mat_A).inv() * Mat_A.t() * Mat_b;//最小二乘法求解过程
		Mat_x = Mat_x.t();//按照Opencv中按列计算习惯,需要转置
	}
	return Mat_x;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章