我尝试使用opencv来校准立体相机。
但是,屏幕没有正常显示。
我使用“findChessboardCorners”访问了角落。
确认结果坐标正常。
通过“stereoCalibrate”函数输出参数,
使用参数输出到屏幕。
然而,它没有正常输出。
是什么原因?
// call the function
FindChessboard(matImg1, matImg2, true);
const Size boardSize;
const Size2f squareSize;
vector<vector<Point2f>> imagePoints1, imagePoints2;
Size imageSize;
Mat map1, map2, map3, map4;
// Retrieves the corner
int FindChessboard (Mat view1, Mat view2, bool reg)
{
if (view1.empty()) {
return 0;
}
if (view2.empty()) {
return 0;
}
assert (view1.size() == view2.size());
imageSize = view1.size();
Mat viewGray1, viewGray2;
cvtColor (view1, viewGray1, CV_BGR2GRAY);
cvtColor (view2, viewGray2, CV_BGR2GRAY);
vector<Point2f> pointbuf1, pointbuf2;
// Find the corner
bool found1 = findChessboardCorners(view1, boardSize, pointbuf1,
CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK | CV_CALIB_CB_NORMALIZE_IMAGE);
bool found2 = findChessboardCorners(view2, boardSize, pointbuf2,
CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK | CV_CALIB_CB_NORMALIZE_IMAGE);
// find
if (found1 && found2) {
// improve the found corners' coordinate accuracy
cornerSubPix (viewGray1, pointbuf1, Size(11,11), Size(-1,-1), TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));
cornerSubPix (viewGray2, pointbuf2, Size(11,11), Size(-1,-1), TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));
// push corner position
if (reg) {
imagePoints1.push_back (pointbuf1);
imagePoints2.push_back (pointbuf2);
}
drawChessboardCorners (view1, boardSize, Mat(pointbuf1), found1);
drawChessboardCorners (view2, boardSize, Mat(pointbuf2), found2);
}
return imagePoints1.size();
}
以上功能用于获得角落。
// start callibration
bool RunCalibration ()
{
int size = imagePoints1.size();
vector<vector<Point3f> > objectPoints;
objectPoints.resize(size);
// ..??
for (int i = 0; i < size; i++)
{
for (int j = 0; j < boardSize.height; j++)
for (int k = 0; k < boardSize.width; k++)
objectPoints[i].push_back(Point3f(k*squareSize.width, j*squareSize.height, 0));
}
objectPoints.resize(imagePoints1.size(), objectPoints[0]);
//
// 좌우 camera의 체스판 영상의 점들로부터 camera matrix, distortion coefficients와 R, P 행렬을 계산한다
//
Mat cameraMatrix1 = Mat::eye(3, 3, CV_64F);
Mat cameraMatrix2 = Mat::eye(3, 3, CV_64F);
Mat distCoeffs1 = Mat::zeros(8, 1, CV_64F);
Mat distCoeffs2 = Mat::zeros(8, 1, CV_64F);
Mat R, T, E, F;
//cameraMatrix1 = initCameraMatrix2D(objectPoints, imagePoints1, imageSize, 0);
//cameraMatrix2 = initCameraMatrix2D(objectPoints, imagePoints2, imageSize, 0);
// start calibration
double rms = stereoCalibrate(objectPoints, imagePoints1, imagePoints2,
cameraMatrix1, distCoeffs1,
cameraMatrix2, distCoeffs2,
imageSize, R, T, E, F,
CALIB_FIX_ASPECT_RATIO +
CALIB_ZERO_TANGENT_DIST +
CALIB_USE_INTRINSIC_GUESS +
CALIB_SAME_FOCAL_LENGTH +
CALIB_RATIONAL_MODEL +
CALIB_FIX_K3 + CALIB_FIX_K4 + CALIB_FIX_K5,
TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, 1e-5));
bool ok = checkRange(cameraMatrix1) && checkRange(distCoeffs1) && checkRange(cameraMatrix2) && checkRange(distCoeffs2);
if (ok) {
Mat R1, R2, P1, P2, Q;
Rect validRoi1, validRoi2;
stereoRectify (cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2,
imageSize, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, 1, imageSize, &validRoi1, &validRoi2);
// save intrinsic parameters
FileStorage fs("D:\\Sources\\trunk\\Sources\\Stereo_Scopic\\intrinsics.yml", CV_STORAGE_WRITE);
if (!fs.isOpened()) return false;
fs << "M1" << cameraMatrix1;
fs << "D1" << distCoeffs1;
fs << "M2" << cameraMatrix2;
fs << "D2" << distCoeffs2;
fs.release();
fs.open("D:\\Sources\\trunk\\Sources\\Stereo_Scopic\\extrinsics.yml", CV_STORAGE_WRITE);
if (!fs.isOpened()) return false;
fs << "R" << R;
fs << "T" << T;
fs << "R1" << R1;
fs << "R2" << R2;
fs << "P1" << P1;
fs << "P2" << P2;
fs << "Q" << Q;
fs << "imageSize" << imageSize;
fs.release();
initUndistortRectifyMap (cameraMatrix1, distCoeffs1, R1, P1, imageSize, CV_16SC2, map1, map2);
initUndistortRectifyMap (cameraMatrix2, distCoeffs2, R2, P2, imageSize, CV_16SC2, map3, map4);
}
return ok;
}
// show
int distortionCorrection(Mat leftImg, Mat rightImg) {
float scale = 1.f;
Mat img1 = leftImg.clone();
Mat img2 = rightImg.clone();
Size img_size = img1.size();
string intrinsic_filename = "D:\\Sources\\trunk\\Sources\\Stereo_Scopic\\intrinsics.yml";
string extrinsic_filename = "D:\\Sources\\trunk\\Sources\\Stereo_Scopic\\extrinsics.yml";
Mat Q;
Rect roi1, roi2;
// load parameters
if (!intrinsic_filename.empty())
{
// reading intrinsic parameters
Mat cameraMatrix1 = Mat::eye(3, 3, CV_64F);
Mat cameraMatrix2 = Mat::eye(3, 3, CV_64F);
Mat distCoeffs1 = Mat::zeros(8, 1, CV_64F);
Mat distCoeffs2 = Mat::zeros(8, 1, CV_64F);
FileStorage fs("D:\\Sources\\trunk\\Sources\\Stereo_Scopic\\intrinsics.yml", CV_STORAGE_READ);
if (!fs.isOpened()) return false;
fs["M1"] >> cameraMatrix1;
fs["D1"] >> distCoeffs1;
fs["M2"] >> cameraMatrix2;
fs["D2"] >> distCoeffs2;
//read extrinsic parameters
Mat R, T;
Mat R1, R2, P1, P2, Q;
Rect validRoi1, validRoi2;
fs.open("D:\\Sources\\trunk\\Sources\\Stereo_Scopic\\extrinsics.yml", CV_STORAGE_READ);
if (!fs.isOpened()) return false;
fs["R"] >> R;
fs["T"] >> T;
fs["R1"] >> R1;
fs["P1"] >> P1;
fs["R2"] >> R2;
fs["P2"] >> P2;
fs["Q"] >> Q;
FileNode is = fs["imageSize"];
img_size.width = is[0];
img_size.height = is[1];
Mat map11, map12, map21, map22;
initUndistortRectifyMap(cameraMatrix1, distCoeffs1, R1, P1, img_size, CV_16SC2, map11, map12);
initUndistortRectifyMap(cameraMatrix2, distCoeffs2, R2, P2, img_size, CV_16SC2, map21, map22);
Mat img1r, img2r;
remap(img1, img1r, map11, map12, INTER_LINEAR);
remap(img2, img2r, map21, map22, INTER_LINEAR);
img1 = img1r;
img2 = img2r;
namedWindow("img1m", 1);
imshow("img1m", img1);
namedWindow("img2m", 1);
imshow("img2m", img2);
waitKey(10);
//stereo(img1, img2);
}
}