How to make 3D images in opencv

asked 2014-12-27 03:22:12 -0500

ann gravatar image

updated 2014-12-27 03:23:03 -0500

I want to make 3D images from 2D images. So I tried the following code.

 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 );
 Mat Q; Mat xyz;

// 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
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);

// 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);

// 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


// 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));
 //reprojectImageTo3D ( const Mat &  disparity , Mat &  _3DImage , const Mat &  Q , bool  HandleMissingValues ...
(more)
edit retag flag offensive close merge delete

Comments

How does your Q-matrix look like (in your case H2)? The message says that it expects H2 to be a 4x4 Matrix but your input has a different size.

FooBar gravatar imageFooBar ( 2014-12-27 16:15:59 -0500 )edit

reply me...

ann gravatar imageann ( 2015-01-02 03:14:51 -0500 )edit

I got H2 as (3,3) matrix.I don't know why and how to make it (4,4 ) matrix.

ann gravatar imageann ( 2015-01-03 04:24:19 -0500 )edit

ann, you probably should edit your question with your latest problem ( how do i get a correct Q Mat ?)

berak gravatar imageberak ( 2015-01-14 06:46:39 -0500 )edit