我在现实生活中有一个3D矩形墙,可以转换为2D图像。考虑到我拥有他所有的4点坐标。如何找到他相对于相机的真实Z角位置?
我试图测量不同角度视角下矩形的边缘之间的比率,并以此为常数,如果将其乘以某些边缘的比率,它将得到当前的Z角。这没有用,因为当旋转墙时,边缘之间的比率并不总是改变。 我还能做些什么吗?
图片1: image 1 预期输出:0度
图片2: image 2
预期输出:20度左右
图片3: image 3
预期输出:大约45度
答案 0 :(得分:1)
基础数学
假设您有2张2D图像,并且希望找到它们之间的旋转。例如,第一个图像是正面平行0度。然后第二个是您希望找到的角度。
请从这里开始https://www.ifi.uzh.ch/dam/jcr:5759a719-55db-4930-8051-4cc534f812b1/VO_Part_I_Scaramuzza.pdf
这是从图像特征对应中捕获2D到2D运动的过程。数学涉及太多。我不会全力以赴。本质上,您正在寻找一个2级且包含所有旋转和平移矢量
的基本矩阵。如
所述,最小情况解决方案涉及五个2-D到2-D对应关系E。 Kruppa,“ Zur ermittlung eines objektes aus zwei perspektiven mit 内部定向”,Sitzungsberichte der Akademie der Wissenschaften, 维也纳,数学研究中心(Mathematisch-Naturwissenschaftlichen Klasse),Abteilung IIa, 卷122,第1939-1948年,1913年。
最受欢迎的方法是Longuet-Higgins的八点算法。超过8个对应的匹配点。
只需列出匹配点,如下所示
由于您可以在手柄之前校准相机,所以F可以直接用E代替。
此外,还必须仔细阅读上图所示的Multiview几何书中的对极几何
如果您的相机是RGBD相机,则只需3个点即可进行匹配,这在第一个链接中称为3D到3D运动估计。
编码
假设您了解所有背景数学。相应地安装opencv
假设您使用的图像位于img1和img2中。 img 1是前并行。图2是您要查找的旋转角度。
Mat img_1_c = imread(filename1);
Mat img_2_c = imread(filename2); //each file should not have any color drawing inside
您可以手动编辑匹配点,例如带有中心点的四个角
vector<Point2f> points1, points2; //each topic have at least 5 point inside
最简单的方法是在OpenCV中使用功能检测路由(可选)
cvtColor(img_1_c, img_1, COLOR_BGR2GRAY);
cvtColor(img_2_c, img_2, COLOR_BGR2GRAY);
featureDetection(img_1, points1); //detect features in img_1
vector<uchar> status;
featureTracking(img_1,img_2,points1,points2, status); //track those features to img_2
如果基线移动太大,则可以使用检测器描述符匹配器方式。 (可选)
SurfFeatureDetector detector(400);
vector<KeyPoint> keypoints1, keypoints2;
detector.detect(img_1, keypoints1);
detector.detect(img_2, keypoints2);
// computing descriptors
SurfDescriptorExtractor extractor;
Mat descriptors1, descriptors2;
extractor.compute(img_1, keypoints1, descriptors1);
extractor.compute(img_2, keypoints2, descriptors2);
// matching descriptors
BFMatcher matcher(NORM_L2);
vector<DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);
// drawing the results
namedWindow("matches", 1);
Mat img_matches;
drawMatches(img_1, keypoints1, img_2, keypoints2, matches, img_matches);
imshow("matches", img_matches);
输入来自相机固有校准https://docs.opencv.org/2.4/doc/tutorials/calib3d/camera_calibration/camera_calibration.html
的相机焦点和主要点 double focal = XXXX;
cv::Point2d pp(XXXXX, XXxxx); // this should be around the center of image if it is too far away, check you calibration process
Mat E, R, t, mask;
E = findEssentialMat(points2, points1, focal, pp, RANSAC, 0.999, 1.0, mask);
recoverPose(E, points2, points1, R, t, focal, pp, mask);
R和t包含旋转和平移(不是真实世界的比例)。
Mat Euler_vec;
Rodrigues(R,Euler_vec);
cout<<Euler_vec<<endl;
然后,Euler_vec应该包含您想要的角度。您要查找的值应该在第一列或最后一列