私の質問は次のとおりです。
- 基本行列が正しいかどうかを確認するにはどうすればよいですか?
- 以下に投稿したコードは、それに向けて良い努力をしていますか?
私の最終目標は、ある種の3D再構成を行うことです。現在、2台のカメラの差を推定できるように、基本行列を計算しようとしています。私はこれをopenFrameworks内で、ofxCvアドオンを使用して行っていますが、ほとんどの場合、それは純粋なOpenCVです。ofxCvも開発中であるため、問題を切り分けるコードを投稿することは困難です。
私のコードは基本的に、ウェブカメラがわずかに異なる位置から取得した2つの640x480フレームを読み取ります(基本的には、ラップトップを少し水平にスライドさせるだけです)。を使用するofxCvのキャリブレーションコードから取得した、そのキャリブレーションマトリックスをすでに持っていますfindChessboardCorners
。歪みのないサンプルコードは、キャリブレーションマトリックスが正確であることを示しているようです。画像間のオプティカルフロー(またはのいずれcalcOpticalFlowPyrLK
かcalcOpticalFlowFarneback
)を計算し、それらのポイントペアをにフィードしfindFundamentalMatrix
ます。
基本行列が有効かどうかをテストするために、回転行列と変換行列に分解しました。次に、回転行列に2番目の画像のポイントを掛けて、カメラ間の回転の違いを確認しました。違いは小さいはずだと思いましたが、大きな違いが出てきています。
これが私の最後のコードの基本的な回転行列です。
fund: [-8.413948689969405e-07, -0.0001918870646474247, 0.06783422344973795;
0.0001877654679452431, 8.522397812179886e-06, 0.311671691674232;
-0.06780237856576941, -0.3177275967586101, 1]
R: [0.8081771697692786, -0.1096128431920695, -0.5786490187247098;
-0.1062963539438068, -0.9935398408215166, 0.03974506055610323;
-0.5792674230456705, 0.02938723035105822, -0.8146076621848839]
t: [0, 0.3019063882496216, -0.05799044915951077;
-0.3019063882496216, 0, -0.9515721940769112;
0.05799044915951077, 0.9515721940769112, 0]
これが、2枚目の写真が撮られた後に発生するコードの私の部分です。
const ofImage& image1 = images[images.size() - 2];
const ofImage& image2 = images[images.size() - 1];
std::vector<cv::Point2f> points1 = flow->getPointsPrev();
std::vector<cv::Point2f> points2 = flow->getPointsNext();
std::vector<cv::KeyPoint> keyPoints1 = convertFrom(points1);
std::vector<cv::KeyPoint> keyPoints2 = convertFrom(points2);
std::cout << "points1: " << points1.size() << std::endl;
std::cout << "points2: " << points2.size() << std::endl;
fundamentalMatrix = (cv::Mat)cv::findFundamentalMat(points1, points2);
cv::Mat cameraMatrix = (cv::Mat)calibration.getDistortedIntrinsics().getCameraMatrix();
cv::Mat cameraMatrixInv = cameraMatrix.inv();
std::cout << "fund: " << fundamentalMatrix << std::endl;
essentialMatrix = cameraMatrix.t() * fundamentalMatrix * cameraMatrix;
cv::SVD svd(essentialMatrix);
Matx33d W(0,-1,0, //HZ 9.13
1,0,0,
0,0,1);
cv::Mat_<double> R = svd.u * Mat(W).inv() * svd.vt; //HZ 9.19
std::cout << "R: " << (cv::Mat)R << std::endl;
Matx33d Z(0, -1, 0,
1, 0, 0,
0, 0, 0);
cv::Mat_<double> t = svd.vt.t() * Mat(Z) * svd.vt;
std::cout << "t: " << (cv::Mat)t << std::endl;
Vec3d tVec = Vec3d(t(1,2), t(2,0), t(0,1));
Matx34d P1 = Matx34d(R(0,0), R(0,1), R(0,2), tVec(0),
R(1,0), R(1,1), R(1,2), tVec(1),
R(2,0), R(2,1), R(2,2), tVec(2));
ofMatrix4x4 ofR(R(0,0), R(0,1), R(0,2), 0,
R(1,0), R(1,1), R(1,2), 0,
R(2,0), R(2,1), R(2,2), 0,
0, 0, 0, 1);
ofRs.push_back(ofR);
cv::Matx34d P(1,0,0,0,
0,1,0,0,
0,0,1,0);
for (int y = 0; y < image1.height; y += 10) {
for (int x = 0; x < image1.width; x += 10) {
Vec3d vec(x, y, 0);
Point3d point1(vec.val[0], vec.val[1], vec.val[2]);
Vec3d result = (cv::Mat)((cv::Mat)R * (cv::Mat)vec);
Point3d point2 = result;
mesh.addColor(image1.getColor(x, y));
mesh.addVertex(ofVec3f(point1.x, point1.y, point1.z));
mesh.addColor(image2.getColor(x, y));
mesh.addVertex(ofVec3f(point2.x, point2.y, point2.z));
}
}
何か案は?私の基本行列は正しく見えますか、それともテストで間違った考えを持っていますか?