Stereo Rectify get incorrect result! [closed]

asked 2016-04-17 21:00:43 -0500

Roby gravatar image

updated 2016-04-18 02:24:16 -0500

I am working on stereo calibration with these steps: 1. findChessborad -> cornerSubPix 2. stereoCalibrate to get R T E F 3.undistortPoints and computeCorrespondEpilines 4.stereoRectify to get R1 R2 P1 P2 Q 5.initUndistortRectifyMap to get remap matrix 6 remap

all the steps followed the cpp example given in the opencv package. one pair of images I used as below: image description image description

the result I get is: image description

if I use : findFundamentalMat and stereoRectifyUncalibrated instead of stereorectify to get R1 R2 P1 P2 will get a correct result.

here is my code snapshot:

//FOR STD LIB
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <iterator>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sstream>

//FOR OPENCVLIB
#include "opencv2/opencv.hpp"
#include "opencv2/calib3d.hpp"
#include "opencv2/core/core.hpp"

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv/cvaux.hpp"
//using namespace std;
//using namespace cv;


#define infinite 1e400
#define numImagePairs 10

const std::string PathPrefix = "/home/roby/Developer/projects/Calibration_rectify/res/";
typedef std::vector<std::string> ImageNameList;
typedef std::vector<cv::Point2f> PointList;
typedef std::vector<PointList> LEFT_PointVec;
typedef std::vector<PointList> RIGHT_PointVec;
typedef std::vector<std::vector<cv::Point3f> > Point3DList;
const cv::Size CHECKERBOARD_SIZE = cv::Size(7,6);


#define BYTE unsigned char

int main(int argc, const char * argv[])
{
    ImageNameList rightCameraList;
    ImageNameList leftCameraList;

    ImageNameList goodrightCameraList;
    ImageNameList goodleftCameraList;

    LEFT_PointVec leftCameraPTvec;
    RIGHT_PointVec rightCameraPTvec;
    Point3DList objectPoints;

    int numGoodImgPairs = numImagePairs;
    const float squareSize = 1.f;  // Set this to your actual square size
    cv::Size imageSize;

    //load image name
    std::ostringstream ss;

    for (int i = 1; i <= numImagePairs; i++) {
    ss << i;
        rightCameraList.push_back(PathPrefix + "right/right"+ss.str() +".png");
        leftCameraList.push_back(PathPrefix + "left/left"+ss.str() +".png");
        ss.str(""); //clear stream content
    }

    for (int i = 0; i < numImagePairs; i++) {
        cv::Mat rightimg = cv::imread(rightCameraList[i],0);
        cv::Mat leftimg = cv::imread(leftCameraList[i],0);
        if (rightimg.size != leftimg.size) {
            std::cout<<"Left Image size != Right Image Size"<<std::endl;
            return 0;
        }else{
            imageSize = rightimg.size();
        }

        rightimg.convertTo(rightimg, CV_8U);
        leftimg.convertTo(leftimg, CV_8U);

        PointList right_ptList;
        PointList left_ptList;

        if (cv::findChessboardCorners(rightimg, CHECKERBOARD_SIZE, right_ptList)) {
            if (cv::findChessboardCorners(leftimg, CHECKERBOARD_SIZE, left_ptList)) {
                cv::cornerSubPix(rightimg, right_ptList, cv::Size(11,11), cv::Size(-1,-1),
                                 cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS,
                                          30, 0.01));
                cv::cornerSubPix(leftimg, left_ptList, cv::Size(11,11), cv::Size(-1,-1),
                                 cv::TermCriteria(cv::TermCriteria::COUNT+cv::TermCriteria::EPS,
                                          30, 0.01));
                rightCameraPTvec.push_back(right_ptList);
                leftCameraPTvec.push_back(left_ptList);
                goodleftCameraList.push_back(leftCameraList[i]);
                goodrightCameraList.push_back(rightCameraList[i]);
            }else{
                numGoodImgPairs--;
                std::cout<<"CHESSBOARD NOT FOUND in LEFT IMG!"<<std::endl;
            }
        }else{
            numGoodImgPairs--;
            std::cout<<"CHESSBOARD NOT FOUND in RIGHT IMG!"<<std::endl;
        }
    }

    if (numGoodImgPairs < 2) {
        std::cout<<"Error: too little pairs to run the calibration"<<std::endl;
        return 0;
    }
    objectPoints.resize(numGoodImgPairs);

    for( int i = 0; i < numGoodImgPairs; i++ )
    {
        for( int j = 0; j < CHECKERBOARD_SIZE.height; j++ )
            for( int k = 0; k < CHECKERBOARD_SIZE.width; k++ )
                objectPoints[i].push_back(cv::Point3f(k*squareSize, j*squareSize, 0));
    }
    cv::Mat cameraMatrix[2], distCoeffs[2];
    cameraMatrix[0] = cv::Mat ...
(more)
edit retag flag offensive reopen merge delete

Closed for the following reason the question is answered, right answer was accepted by Roby
close date 2016-04-18 21:00:29.041649

Comments

I have a similar problem. I calibrate the cameras independently to find intrinsics (distortions in particular) - I get correct undistorted images (<1 rms). Then stereoCalibrate to find extrinsics only - again I get correct R and T (R almost identity matrix because the cameras are parallel and T having very close to my measured translation). But now when I put all these correct inputs in stereoRectify() I get junk P1, P2 and Q. Or at least the next initUndistortRectifyMap() and remap() functions return very wrong images (like the one you posted, polar like). Any help on this? I haven't tried "uncalibrated".

HG gravatar imageHG ( 2016-04-18 03:19:22 -0500 )edit

yes. if you have any clue ,please let me know! thanks

Roby gravatar imageRoby ( 2016-04-18 20:17:08 -0500 )edit

I finally get the reason.the distortion params used are not appropriate. set CALIB_FIX_K6 will get correct result. my test imgs are not distort severely, so it not nessecery to use K6 in distortion model.

Roby gravatar imageRoby ( 2016-04-18 20:59:19 -0500 )edit