OpenCV:基本矩阵和移动摄影机

OpenCV:基本矩阵和移动摄影机,opencv,image-processing,camera-calibration,extrinsic-parameters,reprojection-error,Opencv,Image Processing,Camera Calibration,Extrinsic Parameters,Reprojection Error,我有一个经过校准的(固有参数)相机。我从物体上拍摄立体照片,并在再投影过程中使用它们来寻找物体的一些三维信息 为此,首先我计算了基本矩阵。然后,我得到基本矩阵,从那里,我有旋转矩阵和平移向量以及其他需要的信息 问题是,使用不同的参数,我得到的结果非常不同。我知道同一立体图像的基本矩阵可能不同,但我希望有相同的旋转矩阵和平移向量。然而,每个不同的参数(例如匹配特征的数量)都会导致不同的矩阵。我错过了什么吗?相同的立体图像应该提供(相当)相同的旋转、平移和重投影矩阵,这对吗 这是我的密码。任何帮助都

我有一个经过校准的(固有参数)相机。我从物体上拍摄立体照片,并在再投影过程中使用它们来寻找物体的一些三维信息

为此,首先我计算了基本矩阵。然后,我得到基本矩阵,从那里,我有旋转矩阵和平移向量以及其他需要的信息

问题是,使用不同的参数,我得到的结果非常不同。我知道同一立体图像的基本矩阵可能不同,但我希望有相同的旋转矩阵和平移向量。然而,每个不同的参数(例如匹配特征的数量)都会导致不同的矩阵。我错过了什么吗?相同的立体图像应该提供(相当)相同的旋转、平移和重投影矩阵,这对吗

这是我的密码。任何帮助都将不胜感激。谢谢

Mat img_1 = imread( "images/box01-edited.jpg", CV_LOAD_IMAGE_GRAYSCALE );
Mat img_2 = imread( "images/box02-edited.jpg", CV_LOAD_IMAGE_GRAYSCALE );


if( !img_1.data || !img_2.data )
{ return -1; }

//-- Step 1: Detect the keypoints using SURF Detector
int minHessian = 1000;
SurfFeatureDetector detector( minHessian );
std::vector<KeyPoint> keypoints_1, keypoints_2;
detector.detect( img_1, keypoints_1 );
detector.detect( img_2, keypoints_2 );

//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;
Mat descriptors_1, descriptors_2;
extractor.compute( img_1, keypoints_1, descriptors_1 );
extractor.compute( img_2, keypoints_2, descriptors_2 );

//-- Step 3: Matching descriptor vectors with a brute force matcher
BFMatcher matcher(NORM_L1, true);
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );

//-- Draw matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2, matches, img_matches );
//-- Show detected matches
namedWindow( "Matches", CV_WINDOW_NORMAL );
imshow("Matches", img_matches );
waitKey(0);


//-- Step 4: calculate Fundamental Matrix
vector<Point2f>imgpts1,imgpts2;
for( unsigned int i = 0; i<matches.size(); i++ )
{
// queryIdx is the "left" image
imgpts1.push_back(keypoints_1[matches[i].queryIdx].pt);
// trainIdx is the "right" image
imgpts2.push_back(keypoints_2[matches[i].trainIdx].pt);
}
Mat F =  findFundamentalMat  (imgpts1, imgpts2, FM_RANSAC, 0.1, 0.99);


//-- Step 5: calculate Essential Matrix

double data[] = {1189.46 , 0.0, 805.49, 
                0.0, 1191.78, 597.44,
                0.0, 0.0, 1.0};//Camera Matrix
Mat K(3, 3, CV_64F, data);
Mat_<double> E = K.t() * F * K; //according to HZ (9.12)

//-- Step 6: calculate Rotation Matrix and Translation Vector
Matx34d P;
Matx34d P1;
//decompose E to P' , HZ (9.19)
SVD svd(E,SVD::MODIFY_A);
Mat svd_u = svd.u;
Mat svd_vt = svd.vt;
Mat svd_w = svd.w;
Matx33d W(0,-1,0,1,0,0,0,0,1);//HZ 9.13
Mat_<double> R = svd_u * Mat(W) * svd_vt; //HZ 9.19
Mat_<double> t = svd_u.col(2); //u3

if (!CheckCoherentRotation (R)) {
std::cout<<"resulting rotation is not coherent\n";
P1 = 0;
return 0;
}

P1 = Matx34d(R(0,0),R(0,1),R(0,2),t(0),
             R(1,0),R(1,1),R(1,2),t(1),
             R(2,0),R(2,1),R(2,2),t(2));

//-- Step 7: Reprojection Matrix and rectification data
Mat R1, R2, P1_, P2_, Q;
Rect validRoi[2];
double dist[] = { -0.03432, 0.05332, -0.00347, 0.00106, 0.00000};
Mat D(1, 5, CV_64F, dist);

stereoRectify(K, D, K, D, img_1.size(), R, t, R1, R2, P1_, P2_, Q, CV_CALIB_ZERO_DISPARITY, 1, img_1.size(),  &validRoi[0], &validRoi[1] );
Mat img\u 1=imread(“images/box01 edited.jpg”,CV\u LOAD\u IMAGE\u GRAYSCALE);
Mat img_2=imread(“images/box02 edited.jpg”,CV\u LOAD\u IMAGE\u GRAYSCALE);
如果(!img_1.data | |!img_2.data)
{return-1;}
//--步骤1:使用SURF检测器检测关键点
int minHessian=1000;
表面特征检测器(minHessian);
std::向量关键点1,关键点2;
检测器。检测(img_1,关键点_1);
检测器。检测(img_2,关键点_2);
//--步骤2:计算描述符(特征向量)
表面描述符牵引器;
Mat描述符_1,描述符_2;
compute(img_1、关键点_1、描述符_1);
compute(img_2,keypoints_2,描述符_2);
//--步骤3:使用蛮力匹配器匹配描述符向量
BFMatcher匹配器(NORM_L1,true);
标准::向量匹配;
matcher.match(描述符_1,描述符_2,matches);
//--抽签
Mat img_匹配;
抽签匹配(img_1、关键点_1、img_2、关键点_2、匹配、img_匹配);
//--显示检测到的匹配
namedWindow(“匹配”,CV\u窗口\u正常);
imshow(“匹配”,img_匹配);
等待键(0);
//--步骤4:计算基本矩阵
向量MGPTS1,imgpts2;

对于(unsigned int i=0;i我强烈建议您在使用RANSAC算法消除外围特征匹配后,使用标准8点算法优化基本矩阵计算

以下文本取自findFundamentalMat函数的calib3d文档。状态是一个可选的输出参数,用于确定数据集中的异常值

状态–N个元素的输出数组,其中每个元素的离群值设置为0,其他点设置为1。该数组仅在RANSAC和LMedS方法中计算。对于其他方法,它设置为所有1

然后,您可以仅使用带有CV_FM_8POINT选项的内联匹配来获得更可靠的基本矩阵