基於opencv的相機標定
利用opencv中帶的相機標定camera_calibration.cpp檔案,整理後進行相機矯正。
在opencv中的目錄:/opencv-3.3.0/samples/cpp/tutorial_code/calib3d/camera_calibration
在裡面還有需要的in_VID5.xml、VID5.xml根據自己需要進行修改。
另外需要事先拍好的圖片或視訊或直接用攝像頭進行標定。
一、認識函式
1、bool cv::findChessboardCorners( // 如果找到角點則返回true
cv::InputArray image, // 輸入的棋盤格影象(8UC1或8UC3)
cv::Size patternSize, // 棋盤格內部角點的行、列數
cv::OutputArray corners, // 輸出的棋盤格角點
int flags = cv::CALIB_CB_ADAPTIVE_THRESH
| cv::CALIB_CB_NORMALIZE_IMAGE
);
2、void cv::cornerSubPix(
cv::InputArray image, // 輸入影象
cv::InputOutputArray corners, // 角點(既作為輸入也作為輸出)
cv::Size winSize, // 區域大小為 NXN; N=(winSize*2+1)
cv::Size zeroZone, // 類似於winSize,但是總具有較小的範圍,Size(-1,-1)表示忽略
cv::TermCriteria criteria // 停止優化的標準
);
3、 void cv::drawChessboardCorners(
cv::InputOutputArray image, // 棋盤格影象(8UC3)即是輸入也是輸出
cv::Size patternSize, // 棋盤格內部角點的行、列數
cv::InputArray corners, // findChessboardCorners()輸出的角點
bool patternWasFound // findChessboardCorners()的返回值
);
4、bitwise_not(Mat, Mat);//影象反轉
5、void cv::undistort ( InputArray src,
OutputArray dst,
InputArray cameraMatrix,
InputArray distCoeffs,
InputArray newCameraMatrix = noArray()
)
6、void cv::initUndistortRectifyMap(
InputArray _cameraMatrix,
InputArray _distCoeffs,
InputArray _matR,
InputArray _newCameraMatrix,
Size size, int m1type,
OutputArray _map1,
OutputArray _map2 )
7、void cv::remap ( InputArray src,
OutputArray dst,
InputArray map1,
InputArray map2,
int interpolation,
int borderMode = BORDER_CONSTANT,
const Scalar & borderValue = Scalar()
)
二、程式碼,有註釋
1.cameracalibrate.hpp
#ifndef CAMERACALIBRATE_HPP
#define CAMERACALIBRATE_HPP
#include <iostream>
#include <time.h>
#include <sstream>
#include <stdio.h>
#include <opencv2/core/core.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
enum { DETECTION = 0, CAPTURING = 1, CALIBRATED = 2 };
class cameraCalibrate;
class cameraCalibrate
{
public:
/**
* @brief 建構函式,初始化引數inputDetect,flag
* @param
* @author
* @data
*/
cameraCalibrate();
/**
* @brief 向輸出檔案寫入資料
* @param
* @author
* @data
*/
void write(FileStorage &fs) const;
/**
* @brief 從輸入檔案讀取節點資料
* @param
* @author
* @data
*/
void read(const FileNode &node);
/**
* @brief 切換到下一張圖片
* @param
* @author
* @data
*/
Mat nextImage();
/**
* @brief 從圖片資料檔案中讀取圖片列表
* @param
* @author
* @data
*/
static bool readImageList(const string& filename, vector<string>& list);
/**
* @brief 檢查從資料檔案讀取的引數是否合法,通過inputCheck訪問
* @param
* @author
* @data
*/
void chectInput();
public:
enum Pattern { NOT_EXISTING, CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID }; //檢測模式
//無檢測,棋盤,圓形網格,非對稱圓形網格
enum InputType {INVALID, CAMERA, VIDEO_FILE, IMAGE_LIST}; //輸入型別:無型別,相機,視訊,影象
int cameraID; // 使用攝像頭為攝像頭標號
vector<string> imageList; // 使用影象為影象名字列表
int atImageList; // 當前第幾張影象
VideoCapture inputCapture; // 使用攝像頭,開啟的攝像頭
InputType inputType; // 輸入型別,包括INVALID, CAMERA, VIDEO_FILE, IMAGE_LIST
bool inputCheck; // 檢測輸入資料是否合法
int flag; // 執行動作標誌
Pattern calibrationPattern; // 檢測模式,包括NOT_EXISTING, CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID
// 由patternToUse轉化
string patternToUse; // 將要使用的模式,從輸入檔案中讀取轉化為Pattern
Size boardSize; // 棋盤格子個數 橫排個數width,縱排個數height
float squareSize; // 格子大小 邊長單位 mm
int nrFrames; // 圖片張數
float aspectRatio; // 寬高比
int delay; // video延時獲取幀
bool bwritePoints; // 非0在輸出檔案中寫入特徵點
bool bwriteExtrinsics; // 非0在輸出檔案中寫入相機外部引數
bool calibZeroTangentDist; // 非0假設切向畸變為0
bool calibFixPrincipalPoint;// 非0在全域性優化中主角點不變
bool flipVertical; // 非0在水平軸上翻轉輸入影象
string outputFileName; // 輸出檔名稱
bool showUndistorsed; // 非0顯示採集影象
string input; // 影象輸入檔名稱,可以是攝像頭標號
public:
/**
* @brief 執行校準並儲存
* @param
* @author
* @data
*/
bool runCalibrationAndSave(/*cameraCalibrate& s, */Size imageSize, Mat& cameraMatrix, Mat& distCoeffs,
vector<vector<Point2f> > imagePoints );
/**
* @brief 計算重投影誤差
* @param
* @author
* @data
*/
double computeReprojectionErrors( const vector<vector<Point3f> >& objectPoints,
const vector<vector<Point2f> >& imagePoints,
const vector<Mat>& rvecs, const vector<Mat>& tvecs,
const Mat& cameraMatrix , const Mat& distCoeffs,
vector<float>& perViewErrors);
/**
* @brief 計算特徵角位置
* @param
* @author
* @data
*/
void calcBoardCornerPositions(/*Size boardSize, float squareSize, */vector<Point3f>& corners/*,
cameraCalibrate::Pattern patternType*/);
/**
* @brief 執行校準
* @param
* @author
* @data
*/
bool runCalibration( /*cameraCalibrate& s, */Size& imageSize, Mat& cameraMatrix, Mat& distCoeffs,
vector<vector<Point2f> > imagePoints, vector<Mat>& rvecs, vector<Mat>& tvecs,
vector<float>& reprojErrs, double& totalAvgErr);
/**
* @brief 儲存相機引數
* @param
* @author
* @data
*/
void saveCameraParams( /*cameraCalibrate& s, */Size& imageSize, Mat& cameraMatrix, Mat& distCoeffs,
const vector<Mat>& rvecs, const vector<Mat>& tvecs,
const vector<float>& reprojErrs, const vector<vector<Point2f> >& imagePoints,
double totalAvgErr );
};
static void read(const FileNode& node, cameraCalibrate& x, const cameraCalibrate& default_value = cameraCalibrate())
{
if(node.empty())
{
x = default_value;
}
else
{
x.read(node);
}
}
#endif // CAMERACALIBRATE_HPP
2.cameracalibrate.cpp
#include "cameracalibrate.hpp"
cameraCalibrate::cameraCalibrate() : inputCheck(false), flag(0)
{
}
void cameraCalibrate::write(FileStorage &fs) const
{
fs << "{" << "BoardSize_Width" << boardSize.width
<< "BoardSize_Height" << boardSize.height
<< "Square_Size" << squareSize
<< "Calibrate_Pattern" << patternToUse
<< "Calibrate_NrOfFrameToUse" << nrFrames
<< "Calibrate_FixAspectRatio" << aspectRatio
<< "Calibrate_AssumeZeroTangentialDistortion" << calibZeroTangentDist
<< "Calibrate_FixPrincipalPointAtTheCenter" << calibFixPrincipalPoint
<< "Write_DetectedFeaturePoints" << bwritePoints
<< "Write_extrinsicParameters" << bwriteExtrinsics
<< "Write_outputFileName" << outputFileName
<< "Show_UndistortedImage" << showUndistorsed
<< "Input_FlipAroundHorizontalAxis" << flipVertical
<< "Input_Delay" << delay
<< "Input" << input
<< "}";
}
void cameraCalibrate::read(const FileNode &node)
{
node["BoardSize_Width" ] >> boardSize.width;
node["BoardSize_Height"] >> boardSize.height;
node["Calibrate_Pattern"] >> patternToUse;
node["Square_Size"] >> squareSize;
node["Calibrate_NrOfFrameToUse"] >> nrFrames;
node["Calibrate_FixAspectRatio"] >> aspectRatio;
node["Write_DetectedFeaturePoints"] >> bwritePoints;
node["Write_extrinsicParameters"] >> bwriteExtrinsics;
node["Write_outputFileName"] >> outputFileName;
node["Calibrate_AssumeZeroTangentialDistortion"] >> calibZeroTangentDist;
node["Calibrate_FixPrincipalPointAtTheCenter"] >> calibFixPrincipalPoint;
node["Input_FlipAroundHorizontalAxis"] >> flipVertical;
node["Show_UndistortedImage"] >> showUndistorsed;
node["Input"] >> input;
// cout<<input;
node["Input_Delay"] >> delay;
chectInput();
}
Mat cameraCalibrate::nextImage()
{
Mat result;
if( inputCapture.isOpened() )
{
Mat view0;
inputCapture >> view0;
view0.copyTo(result);
}
else if( atImageList < (int)imageList.size() )
result = imread(imageList[atImageList++], CV_LOAD_IMAGE_COLOR);
// imshow("aa",result);
// cout<<"aa";
return result;
}
bool cameraCalibrate::readImageList(const string &filename, vector<string> &list)
{
list.clear();
FileStorage fs(filename, FileStorage::READ);
if( !fs.isOpened() )
return false;
FileNode n = fs.getFirstTopLevelNode();
if( n.type() != FileNode::SEQ )
return false;
FileNodeIterator it = n.begin(), it_end = n.end();
for( ; it != it_end; ++it )
{
list.push_back((string)*it);
// cout<<(string)*it<<endl;
}
return true;
}
void cameraCalibrate::chectInput()
{
inputCheck = true;
if (boardSize.width <= 0 || boardSize.height <= 0)
{
cerr << "Invalid Board size: " << boardSize.width << " " << boardSize.height << endl;
inputCheck = false;
}
if (squareSize <= 10e-6)
{
cerr << "Invalid square size " << squareSize << endl;
inputCheck = false;
}
if (nrFrames <= 0)
{
cerr << "Invalid number of frames " << nrFrames << endl;
inputCheck = false;
}
if (input.empty()) // Check for valid input
inputType = INVALID;
else
{
if (input[0] >= '0' && input[0] <= '9')
{
stringstream ss(input);
ss >> cameraID;
inputType = CAMERA;
}
else
{
// cout<<input;
if (readImageList(input, imageList))
{
inputType = IMAGE_LIST;
nrFrames = (nrFrames < (int)imageList.size()) ? nrFrames : (int)imageList.size();
}
else
inputType = VIDEO_FILE;
}
if (inputType == CAMERA)
inputCapture.open(cameraID);
if (inputType == VIDEO_FILE)
inputCapture.open(input);
if (inputType != IMAGE_LIST && !inputCapture.isOpened())
inputType = INVALID;
}
if (inputType == INVALID)
{
cerr << " Inexistent input: " << input;
inputCheck = false;
}
flag = 0;
if(calibFixPrincipalPoint) flag |= CV_CALIB_FIX_PRINCIPAL_POINT;
if(calibZeroTangentDist) flag |= CV_CALIB_ZERO_TANGENT_DIST;
if(aspectRatio) flag |= CV_CALIB_FIX_ASPECT_RATIO;
calibrationPattern = NOT_EXISTING;
if (!patternToUse.compare("CHESSBOARD")) calibrationPattern = CHESSBOARD;
if (!patternToUse.compare("CIRCLES_GRID")) calibrationPattern = CIRCLES_GRID;
if (!patternToUse.compare("ASYMMETRIC_CIRCLES_GRID")) calibrationPattern = ASYMMETRIC_CIRCLES_GRID;
if (calibrationPattern == NOT_EXISTING)
{
cerr << " Inexistent camera calibration mode: " << patternToUse << endl;
inputCheck = false;
}
atImageList = 0;
}
bool cameraCalibrate::runCalibrationAndSave(Size imageSize, Mat &cameraMatrix, Mat &distCoeffs, vector<vector<Point2f> > imagePoints)
{
vector<Mat> rvecs, tvecs;
vector<float> reprojErrs;
double totalAvgErr = 0;
bool ok = runCalibration(imageSize,cameraMatrix,distCoeffs,imagePoints,rvecs,tvecs,reprojErrs,totalAvgErr);
cout<< (ok ? "Calibration succeeded" : "Calibration failed")
<< ". avg reprojection error = " << totalAvgErr << endl;
if(ok)
saveCameraParams(imageSize,cameraMatrix,distCoeffs,rvecs,tvecs,reprojErrs,imagePoints,totalAvgErr);
return ok;
}
double cameraCalibrate::computeReprojectionErrors(const vector< vector<Point3f> > &objectPoints, const vector<vector<Point2f> > &imagePoints, const vector<Mat> &rvecs, const vector<Mat> &tvecs, const Mat &cameraMatrix, const Mat &distCoeffs, vector<float> &perViewErrors)
{
vector<Point2f> imagePoints2;
size_t totalPoints = 0;
double totalErr = 0, err;
perViewErrors.resize(objectPoints.size());
for(size_t i = 0; i < objectPoints.size(); ++i )
{
projectPoints(objectPoints[i], rvecs[i], tvecs[i], cameraMatrix, distCoeffs, imagePoints2);
err = norm(imagePoints[i], imagePoints2, NORM_L2);
size_t n = objectPoints[i].size();
perViewErrors[i] = (float) std::sqrt(err*err/n);
totalErr += err*err;
totalPoints += n;
}
return std::sqrt(totalErr/totalPoints);
}
void cameraCalibrate::calcBoardCornerPositions(/*Size boardSize, float squareSize, */vector<Point3f> &corners/*, cameraCalibrate::Pattern patternType*/)
{
corners.clear();
switch (calibrationPattern) {
case cameraCalibrate::CHESSBOARD:
case cameraCalibrate::CIRCLES_GRID:
for(int i = 0; i < boardSize.height; ++i)
for(int j = 0; j < boardSize.width; ++j)
corners.push_back(Point3f(j*squareSize,i*squareSize,0));
break;
case cameraCalibrate::ASYMMETRIC_CIRCLES_GRID:
for( int i = 0; i < boardSize.height; i++ )
for( int j = 0; j < boardSize.width; j++ )
corners.push_back(Point3f((2*j + i % 2)*squareSize, i*squareSize, 0));
break;
default:
break;
}
}
bool cameraCalibrate::runCalibration(Size &imageSize, Mat &cameraMatrix, Mat &distCoeffs, vector<vector<Point2f> > imagePoints, vector<Mat> &rvecs, vector<Mat> &tvecs, vector<float> &reprojErrs, double &totalAvgErr)
{
cameraMatrix = Mat::eye(3,3,CV_64F);
if(flag & CALIB_FIX_ASPECT_RATIO)
cameraMatrix.at<double>(0,0) = aspectRatio;
distCoeffs = Mat::zeros(8,1,CV_64F);
vector< vector<Point3f> > objectPoints(1);
calcBoardCornerPositions(objectPoints[0]);
objectPoints.resize(imagePoints.size(),objectPoints[0]);
double rms;
rms = calibrateCamera(objectPoints,imagePoints,imageSize,cameraMatrix,distCoeffs,rvecs,tvecs,
flag|CV_CALIB_FIX_K4|CV_CALIB_FIX_K5);
cout << "Re-projection error reported by calibrateCamera: " << rms << endl;
bool ok = checkRange(cameraMatrix) && checkRange(distCoeffs);
totalAvgErr = computeReprojectionErrors(objectPoints,imagePoints,rvecs,tvecs,cameraMatrix,
distCoeffs,reprojErrs);
return ok;
}
void cameraCalibrate::saveCameraParams(Size &imageSize, Mat &cameraMatrix, Mat &distCoeffs, const vector<Mat> &rvecs, const vector<Mat> &tvecs, const vector<float> &reprojErrs, const vector<vector<Point2f> > &imagePoints, double totalAvgErr)
{
FileStorage fs(outputFileName,FileStorage::WRITE);
time_t tm;
time(&tm);
struct tm *t2 = localtime(&tm);
char buf[1024];
strftime(buf,sizeof(buf),"%c",t2);
fs << "calibration_time" << buf;
if(!rvecs.empty() || !reprojErrs.empty())
fs << "nr_of_frames" << (int)max(rvecs.size(),reprojErrs.size());
fs << "image_width" << imageSize.width;
fs << "image_height" << imageSize.height;
fs << "board_width" << boardSize.width;
fs << "board_height" << boardSize.height;
fs << "square_size" << squareSize;
if(flag & CALIB_FIX_ASPECT_RATIO)
fs << "fix_aspect_ratio" << aspectRatio;
if(flag)
{
stringstream flagsStringStream;
flagsStringStream << "flags:"
<< (flag & CALIB_USE_INTRINSIC_GUESS ? " +use_intrinsic_guess" : "")
<< (flag & CALIB_FIX_ASPECT_RATIO ? " +fix_aspectRatio" : "")
<< (flag & CALIB_FIX_PRINCIPAL_POINT ? " +fix_principal_point" : "")
<< (flag & CALIB_ZERO_TANGENT_DIST ? " +zero_tangent_dist" : "");
fs.writeComment(flagsStringStream.str());
}
fs << "flags" << flag;
fs << "camera_matrix" << cameraMatrix;
fs << "distortion_coefficients" << distCoeffs;
fs << "avg_reprojection_error" << totalAvgErr;
if (!reprojErrs.empty())
fs << "per_view_reprojection_errors" << Mat(reprojErrs);
if(!rvecs.empty() && !tvecs.empty() )
{
CV_Assert(rvecs[0].type() == tvecs[0].type());
Mat bigmat((int)rvecs.size(), 6, CV_MAKETYPE(rvecs[0].type(), 1));
bool needReshapeR = rvecs[0].depth() != 1 ? true : false;
bool needReshapeT = tvecs[0].depth() != 1 ? true : false;
for( size_t i = 0; i < rvecs.size(); i++ )
{
Mat r = bigmat(Range(int(i), int(i+1)), Range(0,3));
Mat t = bigmat(Range(int(i), int(i+1)), Range(3,6));
if(needReshapeR)
rvecs[i].reshape(1, 1).copyTo(r);
else
{
//*.t() is MatExpr (not Mat) so we can use assignment operator
CV_Assert(rvecs[i].rows == 3 && rvecs[i].cols == 1);
r = rvecs[i].t();
}
if(needReshapeT)
tvecs[i].reshape(1, 1).copyTo(t);
else
{
CV_Assert(tvecs[i].rows == 3 && tvecs[i].cols == 1);
t = tvecs[i].t();
}
}
fs.writeComment("a set of 6-tuples (rotation vector + translation vector) for each view");
fs << "extrinsic_parameters" << bigmat;
}
if(!imagePoints.empty() )
{
Mat imagePtMat((int)imagePoints.size(), (int)imagePoints[0].size(), CV_32FC2);
for( size_t i = 0; i < imagePoints.size(); i++ )
{
Mat r = imagePtMat.row(int(i)).reshape(2, imagePtMat.cols);
Mat imgpti(imagePoints[i]);
imgpti.copyTo(r);
}
fs << "image_points" << imagePtMat;
}
}
3.main.cpp
#include <iostream>
#include <cameracalibrate.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
cameraCalibrate camcal;
//提取配置檔案中引數
const string inputFile = argc > 1 ? argv[1] : "in_Arlco_Camera_data.xml";
FileStorage fs(inputFile,FileStorage::READ);
if(!fs.isOpened())
{
cout << "Could not open the configuration file: \"" << inputFile << "\"" << endl;
return -1;
}
fs["Settings"] >> camcal;
fs.release();
if(!camcal.inputCheck)
{
cout << "Invalid input detected. Application stopping." << endl;
return -1;
}
//相機標定引數
vector< vector<Point2f> > imagePoints;
Mat cameraMatrix, distCoeffs;
Size imageSize;
int mode = camcal.inputType == cameraCalibrate::IMAGE_LIST ? CAPTURING : DETECTION;
clock_t prevTimestamp = 0;
const Scalar RED(0,0,255),GREEN(0,255,0);
const char ESC_KEY = 27;
for(;;)
{
//讀入圖片
Mat view;
bool blinkOutput = false;
view = camcal.nextImage();
if(mode == CAPTURING && imagePoints.size() >= (size_t)camcal.nrFrames)
{
if(camcal.runCalibrationAndSave(imageSize,cameraMatrix,distCoeffs,imagePoints))
mode = CALIBRATED;
else
mode = DETECTION;
}
if(view.empty())
{
if(mode != CALIBRATED && !imagePoints.empty())
camcal.runCalibrationAndSave(imageSize,cameraMatrix,distCoeffs,imagePoints);
break;
}
imageSize = view.size();
if(camcal.flipVertical) flip(view,view,0);
vector<Point2f> pointBuf;
bool found;
int chessBoardFlags = CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE | CALIB_CB_FAST_CHECK;
//棋盤格角點檢測
switch (camcal.calibrationPattern) {
case cameraCalibrate::CHESSBOARD:
found = findChessboardCorners(view,camcal.boardSize,pointBuf,chessBoardFlags);
break;
case cameraCalibrate::CIRCLES_GRID:
found = findCirclesGrid( view, camcal.boardSize, pointBuf );
break;
case cameraCalibrate::ASYMMETRIC_CIRCLES_GRID:
found = findCirclesGrid( view, camcal.boardSize, pointBuf, CALIB_CB_ASYMMETRIC_GRID );
break;
default:
found = false;
break;
}
//找到棋盤格角點
if(found)
{
if(camcal.calibrationPattern == cameraCalibrate::CHESSBOARD)
{
Mat viewGray;
cvtColor(view, viewGray, COLOR_BGR2GRAY);
//亞畫素級角點檢測
cornerSubPix(viewGray,pointBuf,Size(11,11),Size(-1,-1),
TermCriteria(TermCriteria::EPS+TermCriteria::COUNT,30,0.1));
}
if(mode == CAPTURING && (!camcal.inputCapture.isOpened()
|| clock() - prevTimestamp > camcal.delay*1e-3*CLOCKS_PER_SEC))
{
imagePoints.push_back(pointBuf);
prevTimestamp = clock();
blinkOutput = camcal.inputCapture.isOpened();
}
//棋盤格角點繪製
drawChessboardCorners( view, camcal.boardSize, Mat(pointBuf), found );
}
//提示資訊
string msg = (mode == CAPTURING) ? "100/100" :
mode == CALIBRATED ? "Calibrated" : "Press 'g' to start";
int baseLine = 0;
Size textSize = getTextSize(msg, 1, 1, 1, &baseLine);
Point textOrigin(view.cols - 2*textSize.width - 10, view.rows - 2*baseLine - 10);
if( mode == CAPTURING )
{
if(camcal.showUndistorsed)
msg = format( "%d/%d Undist", (int)imagePoints.size(), camcal.nrFrames );
else
msg = format( "%d/%d", (int)imagePoints.size(), camcal.nrFrames );
}
putText( view, msg, textOrigin, 1, 1, mode == CALIBRATED ? GREEN : RED);
//影象反轉
if( blinkOutput )
bitwise_not(view, view);
if( mode == CALIBRATED && camcal.showUndistorsed )
{
Mat temp = view.clone();
undistort(temp, view, cameraMatrix, distCoeffs);
}
//顯示找到角點的影象
imshow("Image View", view);
char key = (char)waitKey(!camcal.inputCapture.isOpened() ? 50 : camcal.delay);
if( key == ESC_KEY )
break;
if( key == 'u' && mode == CALIBRATED )
camcal.showUndistorsed = !camcal.showUndistorsed;
if( camcal.inputCapture.isOpened() && key == 'g' )
{
mode = CAPTURING;
imagePoints.clear();
}
}
//顯示校正後影象
if( camcal.inputType == cameraCalibrate::IMAGE_LIST && camcal.showUndistorsed )
{
Mat view, rview, map1, map2;
initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(),
getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0),
imageSize, CV_16SC2, map1, map2);
for(size_t i = 0; i < camcal.imageList.size(); i++ )
{
view = imread(camcal.imageList[i], IMREAD_COLOR);
if(view.empty())
continue;
remap(view, rview, map1, map2, INTER_LINEAR);
imshow("Image View", rview);
char c = (char)waitKey();
if( c == ESC_KEY || c == 'q' || c == 'Q' )
break;
}
}
return 0;
}