投影仪标定的核心:求投影仪投影格点的三维空间点坐标
方法一:
- 标定相机
- 求投影的投影的3D空间的角点坐标,通过Utilities::pixelToImageSpace()求相机坐标系的点坐标,设置缩放因子为1,z=1,然后转换到世界坐标系中。
- 将相机中心,即相机坐标系的(0,0,0)位置转换到世界坐标系中,
- 由(2)(3)得到逆向投影线,
- 世界坐标系的参考平面z=0,求点法形式的平面坐标系,
- 线面相交得到投影仪的3D空间的角点坐标
方法二:
- 不用标定相机,直接用opencv的cv::findhomography()函数求解单应性矩阵,
- 由单应性矩阵,求解投影仪的3D空间角点坐标,
cv::Mat homo=cv::findHomography(imgPoints,objPoints2d);
可以从图像点到3D点,也可以从3D点到图像点。
单应性是双向的,从三维空间到像素平面是可以的,从像素平面到三维空间也是可以的。
方法三:
- 标定相机
- 用标定的参数求解单应性矩阵
- 由单应性矩阵,求解投影仪的3D空间角点坐标,
CameraCalibration::perspectiveTransformation(cv::vector<cv::Point2f>corners_in,cv::Mat homoMatrix, cv::vector<cv::Point3f>
验证结果:findhomography()求解的投影点效果,比求解内参,外参得到的单应性矩阵效果好。因为findhomography()包含畸变参数。findhomography()里面包含的有畸变参数,而直接由内参,外参求的homo里面没包畸变参数,经过去畸变后再评价,方法3效果不错的,比findhomography()好一点点。
求法向量:
//opencv叉乘
//cv::Mat c1=(cv::Mat_<double>(1,3) <<2, 0,0);
//cv::Mat c2=(cv::Mat_<double>(1,3) <<0, 2,0);
//Mat c3 = c1.cross(c2);
//std::cout<<c3<<std::endl;
//理解:
//逆向投影线是根据收缩因子来确定在相机坐标系中的点坐标,逆向投影线,仍然是先确定点坐标的,再确定逆向投影线。
//确定z=1可以得到逆向投影线上面的一个z=1的点,是在相机坐标系中,跟外参运算后可以得到世界坐标系中的坐标位置
//详细信息查看函数
cv::Point3f Utilities::pixelToImageSpace(cv::Point2f p, VirtualCamera cam)