【opencv】单目标定测量以及遇到的问题

版权声明:本文为博主原创文章,QQ315228399。找工作中…… https://blog.csdn.net/qq_15947787/article/details/78507167

继上篇双目视觉下的空间坐标计算: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;  
}  

猜你喜欢

转载自blog.csdn.net/qq_15947787/article/details/78507167