利用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;
}