私はこの分野では新しく、2D画像から3Dで単純なシーンをモデル化しようとしていますが、カメラに関する情報はありません。私は3 optionsがあることを知っている:カメラに関する情報のない2枚の画像からの再構築
が、私は2枚の画像を持っていると私は私のカメラ(intrisics)のモデルを知っている私は、インスタンス
loadXMLFromFile()
=>stereoRectify()
=>reprojectImageTo3D()
私のためにXMLからロードされていますそれらを持っていないが、私は調整することができます私のカメラ=>
stereoCalibrate()
=>stereoRectify()
=>reprojectImageTo3D()
私が撮影したカメラを持っていないので、私は、それは私の場合です(カメラを校正することはできません2 i例えば、私はSURF、SIFTを使って両方の画像上に対のキーポイントを見つけ(実際にはブロブ検出器を使うことができます)、これらのキーポイントのディスクリプタを計算し、ディスクリプタに従って画像の右と左の画像からキーポイントをマッチングさせ、それらから基本行列を見つける。処理がはるかに困難であり、このようなものだ:
- 検出キーポイント(SURF、SIFT)=>
- 抽出ディスクリプタ(SURF、SIFT)=>
- コンペアマッチ記述子(ブルートフォース、FLANNはベースアプローチ)=>
- これらの対からの基本的なマット(
findFundamentalMat()
)を見つける=> stereoRectifyUncalibrated()
=>reprojectImageTo3D()
私は最後のアプローチを使用していて、私の質問は次のとおりです。
1)は、右か?
2)大丈夫なら、私は最後のステップについて疑問を持っていますstereoRectifyUncalibrated()
=>reprojectImageTo3D()
reprojectImageTo3D()
関数のシグネチャは次のとおり
void reprojectImageTo3D(InputArray disparity, OutputArray _3dImage, InputArray Q, bool handleMissingValues=false, int depth=-1)
cv::reprojectImageTo3D(imgDisparity8U, xyz, Q, true) (in my code)
パラメータ:
disparity
- 入力単一チャネルの8ビットの符号なし、16ビット、32ビットの符号付きまたは符号付き32ビット浮動小数点視差画像。_3dImage
- 同じサイズの出力3チャネル浮動小数点画像。disparity
。_3dImage(x,y)
の各要素には、視差マップから計算された点(x,y)
の3D座標が含まれています。Q
-stereoRectify()
で得られる4x4透視変換行列です。handleMissingValues
- 関数が欠損値(すなわち、視差が計算されなかった点)を処理する必要があるかどうかを示します。handleMissingValues=true
の場合、外れ値に対応する最小視差を持つピクセル(StereoBM::operator()
を参照)は、非常に大きなZ値(現在10000に設定されている)を持つ3Dポイントに変換されます。ddepth
- オプションの出力配列の深さです。-1の場合、出力イメージの深さはCV_32F
になります。ddepth
は、CV_16S
,CV_32S
または `CV_32F 'に設定することもできます。
Q
マトリックスを取得するにはどうすればよいですか? F
,H1
およびH2
などの方法で、あるいは別の方法でQ
行列を得ることは可能ですか?
3)カメラを較正せずにxyz座標を取得する別の方法はありますか?
私のコードは次のとおり
#include <opencv2/core/core.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/contrib/contrib.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <conio.h>
#include <opencv/cv.h>
#include <opencv/cxcore.h>
#include <opencv/cvaux.h>
using namespace cv;
using namespace std;
int main(int argc, char *argv[]){
// Read the images
Mat imgLeft = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
Mat imgRight = imread(argv[2], CV_LOAD_IMAGE_GRAYSCALE);
// check
if (!imgLeft.data || !imgRight.data)
return 0;
// 1] find pair keypoints on both images (SURF, SIFT):::::::::::::::::::::::::::::
// vector of keypoints
std::vector<cv::KeyPoint> keypointsLeft;
std::vector<cv::KeyPoint> keypointsRight;
// Construct the SURF feature detector object
cv::SiftFeatureDetector sift(
0.01, // feature threshold
10); // threshold to reduce
// sensitivity to lines
// Detect the SURF features
// Detection of the SIFT features
sift.detect(imgLeft,keypointsLeft);
sift.detect(imgRight,keypointsRight);
std::cout << "Number of SURF points (1): " << keypointsLeft.size() << std::endl;
std::cout << "Number of SURF points (2): " << keypointsRight.size() << std::endl;
// 2] compute descriptors of these keypoints (SURF,SIFT) ::::::::::::::::::::::::::
// Construction of the SURF descriptor extractor
cv::SurfDescriptorExtractor surfDesc;
// Extraction of the SURF descriptors
cv::Mat descriptorsLeft, descriptorsRight;
surfDesc.compute(imgLeft,keypointsLeft,descriptorsLeft);
surfDesc.compute(imgRight,keypointsRight,descriptorsRight);
std::cout << "descriptor matrix size: " << descriptorsLeft.rows << " by " << descriptorsLeft.cols << std::endl;
// 3] matching keypoints from image right and image left according to their descriptors (BruteForce, Flann based approaches)
// Construction of the matcher
cv::BruteForceMatcher<cv::L2<float> > matcher;
// Match the two image descriptors
std::vector<cv::DMatch> matches;
matcher.match(descriptorsLeft,descriptorsRight, matches);
std::cout << "Number of matched points: " << matches.size() << std::endl;
// 4] find the fundamental mat ::::::::::::::::::::::::::::::::::::::::::::::::::::
// Convert 1 vector of keypoints into
// 2 vectors of Point2f for compute F matrix
// with cv::findFundamentalMat() function
std::vector<int> pointIndexesLeft;
std::vector<int> pointIndexesRight;
for (std::vector<cv::DMatch>::const_iterator it= matches.begin(); it!= matches.end(); ++it) {
// Get the indexes of the selected matched keypoints
pointIndexesLeft.push_back(it->queryIdx);
pointIndexesRight.push_back(it->trainIdx);
}
// Convert keypoints into Point2f
std::vector<cv::Point2f> selPointsLeft, selPointsRight;
cv::KeyPoint::convert(keypointsLeft,selPointsLeft,pointIndexesLeft);
cv::KeyPoint::convert(keypointsRight,selPointsRight,pointIndexesRight);
/* check by drawing the points
std::vector<cv::Point2f>::const_iterator it= selPointsLeft.begin();
while (it!=selPointsLeft.end()) {
// draw a circle at each corner location
cv::circle(imgLeft,*it,3,cv::Scalar(255,255,255),2);
++it;
}
it= selPointsRight.begin();
while (it!=selPointsRight.end()) {
// draw a circle at each corner location
cv::circle(imgRight,*it,3,cv::Scalar(255,255,255),2);
++it;
} */
// Compute F matrix from n>=8 matches
cv::Mat fundemental= cv::findFundamentalMat(
cv::Mat(selPointsLeft), // points in first image
cv::Mat(selPointsRight), // points in second image
CV_FM_RANSAC); // 8-point method
std::cout << "F-Matrix size= " << fundemental.rows << "," << fundemental.cols << std::endl;
/* draw the left points corresponding epipolar lines in right image
std::vector<cv::Vec3f> linesLeft;
cv::computeCorrespondEpilines(
cv::Mat(selPointsLeft), // image points
1, // in image 1 (can also be 2)
fundemental, // F matrix
linesLeft); // vector of epipolar lines
// for all epipolar lines
for (vector<cv::Vec3f>::const_iterator it= linesLeft.begin(); it!=linesLeft.end(); ++it) {
// draw the epipolar line between first and last column
cv::line(imgRight,cv::Point(0,-(*it)[2]/(*it)[1]),cv::Point(imgRight.cols,-((*it)[2]+(*it)[0]*imgRight.cols)/(*it)[1]),cv::Scalar(255,255,255));
}
// draw the left points corresponding epipolar lines in left image
std::vector<cv::Vec3f> linesRight;
cv::computeCorrespondEpilines(cv::Mat(selPointsRight),2,fundemental,linesRight);
for (vector<cv::Vec3f>::const_iterator it= linesRight.begin(); it!=linesRight.end(); ++it) {
// draw the epipolar line between first and last column
cv::line(imgLeft,cv::Point(0,-(*it)[2]/(*it)[1]), cv::Point(imgLeft.cols,-((*it)[2]+(*it)[0]*imgLeft.cols)/(*it)[1]), cv::Scalar(255,255,255));
}
// Display the images with points and epipolar lines
cv::namedWindow("Right Image Epilines");
cv::imshow("Right Image Epilines",imgRight);
cv::namedWindow("Left Image Epilines");
cv::imshow("Left Image Epilines",imgLeft);
*/
// 5] stereoRectifyUncalibrated()::::::::::::::::::::::::::::::::::::::::::::::::::
//H1, H2 – The output rectification homography matrices for the first and for the second images.
cv::Mat H1(4,4, imgRight.type());
cv::Mat H2(4,4, imgRight.type());
cv::stereoRectifyUncalibrated(selPointsRight, selPointsLeft, fundemental, imgRight.size(), H1, H2);
// create the image in which we will save our disparities
Mat imgDisparity16S = Mat(imgLeft.rows, imgLeft.cols, CV_16S);
Mat imgDisparity8U = Mat(imgLeft.rows, imgLeft.cols, CV_8UC1);
// Call the constructor for StereoBM
int ndisparities = 16*5; // < Range of disparity >
int SADWindowSize = 5; // < Size of the block window > Must be odd. Is the
// size of averaging window used to match pixel
// blocks(larger values mean better robustness to
// noise, but yield blurry disparity maps)
StereoBM sbm(StereoBM::BASIC_PRESET,
ndisparities,
SADWindowSize);
// Calculate the disparity image
sbm(imgLeft, imgRight, imgDisparity16S, CV_16S);
// Check its extreme values
double minVal; double maxVal;
minMaxLoc(imgDisparity16S, &minVal, &maxVal);
printf("Min disp: %f Max value: %f \n", minVal, maxVal);
// Display it as a CV_8UC1 image
imgDisparity16S.convertTo(imgDisparity8U, CV_8UC1, 255/(maxVal - minVal));
namedWindow("windowDisparity", CV_WINDOW_NORMAL);
imshow("windowDisparity", imgDisparity8U);
// 6] reprojectImageTo3D() :::::::::::::::::::::::::::::::::::::::::::::::::::::
//Mat xyz;
//cv::reprojectImageTo3D(imgDisparity8U, xyz, Q, true);
//How can I get the Q matrix? Is possibile to obtain the Q matrix with
//F, H1 and H2 or in another way?
//Is there another way for obtain the xyz coordinates?
cv::waitKey();
return 0;
}
Fabio - language? – Tim
@Tim C++ with OpenCV2.3.1 – Fobi
私はそれはだと思いますが、あなたは何かが欠けています。不一致はいくつかの関数で得ることができます。あなたはopenCVのドキュメントをチェックする必要があります。 http://opencv.willowgarage.com/documentation/camera_calibration_and_3d_reconstruction.html –