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;
}

 

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