您的位置:首页 > 编程语言

opencv2 摄像机标定代码简化版 (ubuntu 16)

2017-02-14 11:49 661 查看
//用法:
//摄像头取像,找到棋盘的时候会显示,按空格捕获图像,esc退出
//捕获够10幅才能按回车开始标定
//本次试验用的是8*8方格棋盘,每个方格边长为20mm

//过程:
//函数findChessboardCorners()寻找棋盘角点粗略位置保存在corners
//函数cornerSubPix()精确化角点坐标
//把每一幅捕获的图像的corners保存在image_point,并生成对应size的object_point
//函数calibrateCamera()利用上面的image_point和object_point进行标定
//得到的intrinsic_matrix矩阵就是摄像头的内参,具体自行查阅资料

#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>

using namespace cv;
using namespace std;

void Tool::calibrate_camera(){

VideoCapture vc;
vc.open(1);
if(!vc.isOpened()){
cout << "Could not open camera\n";
return;
}

Mat frame;
Mat gray_frame;  //用于精确角点坐标
namedWindow("摄像头");
Size board_size = Size(7, 7); //棋盘行列角点数, 不是行列数!
float square_size = 20;   //方格边长 单位:mm
vector<Point2f> corners; //一幅图像的角点坐标
vector<vector<Point2f>> image_point;  //所有图像的角点坐标
vector<vector<Point3f>> object_point;  //所有图像的世界坐标的相对值
Mat intrinsic_matrix;  //内参矩阵
Mat distortion_coeffs;  //失真系数矩阵
vector<Mat> rvecs;  //旋转矩阵
vector<Mat> tvecs;  //平移矩阵
bool pattern_found;  //是否找到棋盘
stringstream ss;   //用于生成字符串

//循环播放视频, 按键捕获图像和标定
for (int key = waitKey(33); ; key = waitKey(33)) {
vc >> frame;
corners.clear();
pattern_found = findChessboardCorners(
frame, board_size, corners,
CALIB_CB_FAST_CHECK +
CALIB_CB_ADAPTIVE_THRESH +
CALIB_CB_NORMALIZE_IMAGE);

if(pattern_found){
cvtColor(frame, gray_frame, CV_BGR2GRAY);
//criteria:角点精准化迭代过程的终止条件。
//也就是当迭代次数超过criteria.maxCount,
//或者角点位置变化小于criteria.epsilon时,停止迭代过程。
TermCriteria criteria = TermCriteria(
CV_TERMCRIT_EPS + CV_TERMCRIT_ITER,
40,
0.001 );
// 亚像素级精确角点位置
cornerSubPix(gray_frame, corners, Size(11,11), Size(-1, -1), criteria);
// 画出角点
drawChessboardCorners(frame, board_size, corners, pattern_found);
if(key == 0x100020){ //space 取得一帧的角点
image_point.push_back(corners);
}
}

if(key == 0x10001b){ //esc 退出
break;
}

else if(key == 0x10000a && image_point.size() >= 10){ //enter 进行标定
//计算单幅图像对应的世界坐标的相对值,每个方块的单位取为1
vector<Point3f> object_point_1;
for(int h = 0; h < board_size.height; h++){
for(int w = 0; w < board_size.width; w++){
object_point_1.push_back(
Point3f(w * square_size, h * square_size, 0.0f)
);
}
}
object_point.resize(image_point.size(), object_point_1);
//初始化内参数矩阵  和  失真系数矩阵
intrinsic_matrix = Mat::eye(Size(3, 3), CV_32F);
distortion_coeffs = Mat::zeros(5, 1, CV_32F);
//开始标定
calibrateCamera(object_point, image_point, frame.size(),
intrinsic_matrix, distortion_coeffs, rvecs, tvecs);
cout << "内参矩阵" << intrinsic_matrix << endl
<< "失真系数矩阵" << distortion_coeffs;
break;
}
ss.str("");
ss << image_point.size();
//显示已捕获图片数量
putText(frame, ss.str(), Point(20,50),
FONT_HERSHEY_SIMPLEX, 1, Scalar(255,255,255), 3);
imshow("摄像头", frame);
}
}

int main(){
calibrate_camera();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息