1. 程式人生 > >【opencv】單目標定測量以及遇到的問題

【opencv】單目標定測量以及遇到的問題

繼上篇雙目視覺下的空間座標計算:http://blog.csdn.net/qq_15947787/article/details/53366592

結合普通相機標定流程:http://blog.csdn.net/qq_15947787/article/details/51471535

單目標定測量這裡只是簡單的通過一個相機測量桌面(標定板平面為固定平面)上其他物體的尺寸。

影象上的點與世界座標系下的點與相機的內外參滿足這樣一個關係:

其中Zc是攝像機座標系下的一個座標分量,最後可以消去。

把上式的內外參乘進去,形成下式:

所以空間中的一個點(X,Y,Z)通過這個關係式可以找到唯一對應的影象上點座標(u,v)。而影象上點座標(u,v)通過這個關係式可以找到滿足等式的一個面(Z值不確定),兩個方程,三個未知量。

而雙目構成的系統,則有四個方程,三個未知量,通過最小二乘法可以得到(X,Y,Z)。

將上式寫成方程形式:

而我們要求固定平面下的(X,Y),Z為常數,可以修改上式為:

解出X,Y即可得到空間座標

————————————————————————————————

以上是簡單的求解過程,首先是通過opencv單目標定得到相機內外參,以及每張標定板圖的旋轉矩陣和平移向量,計算出重對映誤差,我這裡在重對映誤差最小的一張圖上建立空間座標系,由於標定板是水平放置在桌面上的,所以Z軸方向就是物體的高度方向,然後在物體上找到邊緣點,通過上面計算得到空間的座標。

單位都是mm,標定板一個格子是41mm,根據博文:http://blog.csdn.net/shenxiaolu1984/article/details/50165635

可以知道這張標定圖的世界座標系情況,但是我在試驗的時候,發現卻不符合。但是不管符合不符合世界座標系的情況,而且找不到這個世界座標系的位置,但是計算的距離都是非常準確的。

//計算空間座標
Point3f uv2xyz(Point2f uv)  
{  
	//棋盤格上兩個點測量
	//uv.x = 711;
	//uv.y = 917;  計算點(-48.9, -176.7)
	//uv.x = 630;
	//uv.y = 932;  計算點(-89.1, -184.6)
	//棋盤格大小41mm,測量結果為40.9689
	//誤差0.03mm

	//   |u|      |X|  
	//Zc*|v| = Ml*|Y| 
	//   |1|      |Z| 
	//            |1| 
	Mat camRT = Mat(3, 4, CV_64F);//相機M矩陣
	hconcat(camRotation, camTranslation, camRT);  
	Mat camM = camIntrinsic * camRT;

	//最小二乘法A矩陣  
	Mat A = Mat(2,2,CV_64F);  
	double aaa = uv.x * camM.at<double>(2,0);
	double bbb = camM.at<double>(0,0);
	A.at<double>(0,0) = uv.x * camM.at<double>(2,0) - camM.at<double>(0,0);  
	A.at<double>(0,1) = uv.x * camM.at<double>(2,1) - camM.at<double>(0,1);  

	A.at<double>(1,0) = uv.y * camM.at<double>(2,0) - camM.at<double>(1,0);  
	A.at<double>(1,1) = uv.y * camM.at<double>(2,1) - camM.at<double>(1,1);  

	//最小二乘法B矩陣  
	Mat B = Mat(2,1,CV_64F);  
	float Z = 200;//物體高度
	B.at<double>(0,0) = camM.at<double>(0,3) - uv.x * camM.at<double>(2,3) - Z * (uv.x * camM.at<double>(2,2) - camM.at<double>(0,2));  
	B.at<double>(1,0) = camM.at<double>(1,3) - uv.y * camM.at<double>(2,3) - Z * (uv.y * camM.at<double>(2,2) - camM.at<double>(1,2));  

	Mat XY = Mat(2,1,CV_64F);  
	//採用SVD最小二乘法求解XY 
	solve(A,B,XY,DECOMP_SVD);  

	//世界座標系中座標  
	Point3f world;  
	world.x = XY.at<double>(0,0);  
	world.y = XY.at<double>(1,0);  
	world.z = Z;  

	return world;  
}