#include "mainwindow.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow) {
ui->setupUi(this);
Mat src_img = imread(openFilePath().toStdString().c_str());
// 保存检测到的所有角点
vector<vector<Point2f>> image_points_seq;
// 标定板上每行、列的角点数
Size board_size = Size(6, 9);
image_points_seq.push_back(getAngle(src_img, board_size)); //保存亚像素角点
// 获取内参
Mat cameraMatrix, distCoeffs;
getCameraParameter(src_img, cameraMatrix, distCoeffs, image_points_seq, board_size);
// 畸变矫正
correctCamera(src_img, cameraMatrix, distCoeffs);
}
MainWindow::~MainWindow() {
delete ui;
}
// 函数说明:检测棋盘格的角点,将角点保存下来。
// 输入棋盘格图片,输入图片的行列(-1)
// 输出保存角点的vector
//****************************************
vector<Point2f> MainWindow::getAngle(Mat &imageInput, Size board_size, bool draw) {
// 缓存每幅图像上检测到的角点
vector<Point2f> image_points_buf;
/* 提取角点 */
if (0 == findChessboardCorners(imageInput, board_size, image_points_buf)) {
cout << "can not find chessboard corners!\n"; //找不到角点
exit(1);
} else {
Mat view_gray;
cvtColor(imageInput, view_gray, COLOR_RGB2GRAY);
/* 亚像素精确化 */
//find4QuadCornerSubpix(view_gray, image_points_buf, Size(11, 11)); //对粗提取的角点进行精确化
cornerSubPix(view_gray, image_points_buf, Size(11, 11), Size(-1, -1),
TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.01));
if(draw) {
/* 在图像上显示角点位置 */
drawChessboardCorners(view_gray, board_size, image_points_buf, true); //用于在图片中标记角点
imshow("Camera Calibration", view_gray); //显示图片
waitKey(500);//暂停0.5S
}
return image_points_buf;
}
}
// 函数说明: 获取相机参数
// 输入:角点
// 输出:内参数矩阵 5个畸变系数
void MainWindow::getCameraParameter(Mat &imageInput, Mat &cameraMatrix, Mat &distCoeffs, vector<vector<Point2f>> image_points_seq, Size board_size) {
// 摄像机内参数矩阵
cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));
// 摄像机的5个畸变系数:k1,k2,p1,p2,k3
distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0));
Size square_size = Size(14.2222, 12);
// 保存标定板上角点的三维坐标
vector<vector<Point3f>> object_points;
// 每幅图像的旋转向量
vector<Mat> tvecsMat;
// 每幅图像的平移向量
vector<Mat> rvecsMat;
vector<Point3f> realPoint;
for (int i = 0; i < board_size.height; i++) {
for (int j = 0; j < board_size.width; j++) {
Point3f tempPoint;
/* 假设标定板放在世界坐标系中z=0的平面上 */
tempPoint.x = i * square_size.width;
tempPoint.y = j * square_size.height;
tempPoint.z = 0;
realPoint.push_back(tempPoint);
}
}
object_points.push_back(realPoint);
printf("#objectPoints: %ld\n", sizeof(object_points[0]));
cout << object_points[0] << endl;
printf("#image_points: %ld\n", sizeof(image_points_seq[0]));
printf("#image size\n");
// calibrateCamera() 求解摄像机的内在参数和外在参数
calibrateCamera(object_points, image_points_seq, imageInput.size(), cameraMatrix, distCoeffs, rvecsMat, tvecsMat,
CALIB_FIX_K3);
cout << "tvecsMat:\n" << tvecsMat[0] << endl;
cout << "rvecsMat:\n" << rvecsMat[0] << endl;
cout << "#cameraMatrix:\n" << cameraMatrix << endl;
cout << "#distCoeffs:\n" << distCoeffs << endl;
}
// 函数说明:畸变矫正
// 输入:内参和畸变参数
// 输出:
void MainWindow::correctCamera(Mat &imageInput, Mat cameraMatrix, Mat distCoeffs, bool draw) {
Mat cb_final;
Mat mapx = Mat(imageInput.size(), CV_32FC1);
Mat mapy = Mat(imageInput.size(), CV_32FC1);
Mat R = Mat::eye(3, 3, CV_32F);
// 计算畸变参数
initUndistortRectifyMap(cameraMatrix, distCoeffs, R, Mat(), imageInput.size(), CV_32FC1,
mapx, mapy);
remap(imageInput, cb_final, mapx, mapy, INTER_LINEAR);
undistort(imageInput, cb_final, cameraMatrix, distCoeffs);
if(draw) {
imshow("Camera finish", cb_final); //显示图片
}
}
// 函数说明:打开读取路径
QString MainWindow::openFilePath(QString path) {
return QFileDialog::getOpenFileName(this, QString("open File"),
QString(path),
QString("File(*.*)"));
}