本文基于:张正友相机标定Opencv实现以及标定流程&&标定结果评价&&图像矫正流程解析(附标定程序和棋盘图)
这篇博客写得虽然很详细,但是其代码和结果有些明显的不当之处,所以本文进行了更为详细准确的介绍,若有问题欢迎指正。
一.本程序基于以下配置:
- Visual Studio 2015
- OpenCV 3.1.0
开发环境配置参考:OpenCV3.1.0+VS2013开发环境配置
二.本程序准备工作:
本程序使用的标定板是10行14列棋盘格图案,示意图如下:
在不同视角拍摄这样的照片14张,依次命名为chess1、chess2、…、chess14,并将其放在当前.cpp文件目录下面,如下图所示:
其中calibdata文本文档的内容如下:
三.完整源程序如下:
#include"opencv2/core/core.hpp"
#include"opencv2/imgproc/imgproc.hpp"
#include"opencv2/calib3d/calib3d.hpp"
#include"opencv2/highgui/highgui.hpp"
#include<iostream>
#include<fstream>
using namespace std;
using namespace cv;
int main()
{
ifstream fin("calibdata.txt");//标定所用图像文件的路径
ofstream fout("calibration_result.txt");//保存标定结果
//读取每一幅图像,从中提取出内角点,然后对角点进行亚像素精确化
cout<<"开始提取特征点..........";
int image_count = 0;//图像的数量
Size image_size;//图像的尺寸
Size board_size = Size(13,9);//标定板上每行、列的内角点数,一般地,行列数不要相同
vector<Point2f> image_points_buf;//用于存储检测到的内角点图像坐标位置
vector<vector<Point2f>> image_points_seq;//保存检测到的所有角点
string filename;//图像名
int count = 0;//保存角点数
while(getline(fin,filename))//从文本文档中依次读取待标定图片名
{
image_count++;
cout<<"image_count = "<<image_count<<endl;
Mat imageInput = imread(filename);//依次读取当前目录下图片
if(image_count == 1)//读入第一张图片时获取图像宽高信息
{
image_size.width = imageInput.cols;
image_size.height = imageInput.rows;
cout<<"image_size.width = "<<image_size.width<<endl;
cout<<"image_size.height = "<<image_size.height<<endl;
}
//提取标定板的内角点,输入必须是8位的灰度或者彩色图像
if(0 == findChessboardCorners(imageInput,board_size,image_points_buf))
{
cout<<"Cannot find chessboard corners!\n";
exit(1);
}
else
{
Mat view_gray;
cvtColor(imageInput,view_gray,CV_RGB2GRAY);//转灰度图
//find4QuadCornerSubpix(view_gray,image_points_buf,Size(5,5));
//亚像素精确化方法一
//image_points_buf初始化的角点坐标向量,同时作为亚像素坐标位置的输出,浮点型数
cornerSubPix(view_gray,image_points_buf,Size(