这里相机标定主要内容包括:图像的采集、相机参数获取、TOOLBOX_calib可视化描述

一、相机标定

感谢博主的代码分享,这里主要参考了一些(https://download.csdn.net/download/u011574296/9918396)

下边是详细步骤代码:

代码可以直接运行,只是有几条要求:

1、要将照片路径换成自己的,照片获取很简单,只要打印一张棋盘格,用手拿着在不同位置用摄像头拍摄就可以了

2、下边头文件很多,有些没有用,如果出现找不到头文件的问题就把相应头文件删除就行了

3、棋盘格上交点的个数要根据你的来做修改,我这里设置的是9*6的

#include <iostream>
#include <vector>
#include <iterator>
#include <tuple>
#include <set>
#include<opencv2\opencv.hpp>
#include <opencv2\imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2\stitching.hpp>
#include "opencv2/features2d/features2d.hpp"
#include <opencv2\core\ocl.hpp>
#include <opencv2/xfeatures2d.hpp>
#include<opencv2\features2d\features2d.hpp>
#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_DEPRECATE
#pragma warning(disable:4996)
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <ctime>
#include<typeinfo>
#include <io.h> using namespace cv;
using namespace std;/*
@param File_Directory 为文件夹目录
@param FileType 为需要查找的文件类型
@param FilesName 为存放文件名的容器
*/
void getFilesName(string& File_Directory, string& FileType, vector<string>& FilesName)
{string buffer = File_Directory + "\\*" + FileType;_finddata_t c_file;   // 存放文件名的结构体intptr_t hFile;hFile = _findfirst(buffer.c_str(), &c_file);   //找第一个文件命if (hFile == -1L)   // 检查文件夹目录下存在需要查找的文件printf("No %s files in current directory!\n", FileType);else{string fullFilePath;do{fullFilePath.clear();//名字fullFilePath = File_Directory + "\\" + c_file.name;cout << fullFilePath << endl;FilesName.push_back(fullFilePath);} while (_findnext(hFile, &c_file) == 0);  //如果找到下个文件的名字成功的话就返回0,否则返回-1  _findclose(hFile);}
}void m_calibration(vector<string>& FilesName, Size board_size, Size square_size, Mat& cameraMatrix, Mat& distCoeffs, vector<Mat>& rvecsMat, vector<Mat>& tvecsMat)
{ofstream fout("caliberation_result.txt");                       // 保存标定结果的文件 cout << "开始提取角点………………" << endl;int image_count = 0;                                            // 图像数量 Size image_size;                                                // 图像的尺寸 vector<Point2f> image_points;                                   // 缓存每幅图像上检测到的角点vector<vector<Point2f>> image_points_seq;                       // 保存检测到的所有角点for (int i = 0; i < FilesName.size(); i++){image_count++;// 用于观察检验输出cout << "image_count = " << image_count << endl;Mat imageInput = imread(FilesName[i]);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;}/* 提取角点 */bool ok = findChessboardCorners(imageInput, board_size, image_points, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE);if (0 == ok){cout << "第" << image_count << "张照片提取角点失败,请删除后,重新标定!" << endl; //找不到角点imshow("失败照片", imageInput);waitKey(0);}else{Mat view_gray;cout << "imageInput.channels()=" << imageInput.channels() << endl;cvtColor(imageInput, view_gray, CV_RGB2GRAY);/* 亚像素精确化 *///find4QuadCornerSubpix(view_gray, image_points, Size(5, 5)); //对粗提取的角点进行精确化cv::cornerSubPix(view_gray, image_points, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 20, 0.01));image_points_seq.push_back(image_points);  //保存亚像素角点/* 在图像上显示角点位置 */drawChessboardCorners(view_gray, board_size, image_points, true);imshow("Camera Calibration", view_gray);//显示图片waitKey(100);//暂停0.1S      }}cout << "角点提取完成!!!" << endl;/*棋盘三维信息*/vector<vector<Point3f>> object_points_seq;                     // 保存标定板上角点的三维坐标for (int t = 0; t < image_count; t++){vector<Point3f> object_points;for (int i = 0; i < board_size.height; i++){for (int j = 0; j < board_size.width; j++){Point3f realPoint;/* 假设标定板放在世界坐标系中z=0的平面上 */realPoint.x = i * square_size.width;realPoint.y = j * square_size.height;realPoint.z = 0;object_points.push_back(realPoint);}}object_points_seq.push_back(object_points);}/* 运行标定函数 */double err_first = calibrateCamera(object_points_seq, image_points_seq, image_size, cameraMatrix, distCoeffs, rvecsMat, tvecsMat, CV_CALIB_FIX_K3);fout << "重投影误差1:" << err_first << "像素" << endl << endl;cout << "标定完成!!!" << endl;cout << "开始评价标定结果………………";double total_err = 0.0;            // 所有图像的平均误差的总和 double err = 0.0;                  // 每幅图像的平均误差double totalErr = 0.0;double totalPoints = 0.0;vector<Point2f> image_points_pro;     // 保存重新计算得到的投影点for (int i = 0; i < image_count; i++){projectPoints(object_points_seq[i], rvecsMat[i], tvecsMat[i], cameraMatrix, distCoeffs, image_points_pro);   //通过得到的摄像机内外参数,对角点的空间三维坐标进行重新投影计算err = norm(Mat(image_points_seq[i]), Mat(image_points_pro), NORM_L2);totalErr += err * err;totalPoints += object_points_seq[i].size();err /= object_points_seq[i].size();//fout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;total_err += err;}fout << "重投影误差2:" << sqrt(totalErr / totalPoints) << "像素" << endl << endl;fout << "重投影误差3:" << total_err / image_count << "像素" << endl << endl;//保存定标结果   cout << "开始保存定标结果………………" << endl;Mat rotation_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); /* 保存每幅图像的旋转矩阵 */fout << "相机内参数矩阵:" << endl;fout << cameraMatrix << endl << endl;fout << "畸变系数:\n";fout << distCoeffs << endl << endl << endl;for (int i = 0; i < image_count; i++){fout << "第" << i + 1 << "幅图像的旋转向量:" << endl;fout << rvecsMat[i] << endl;/* 将旋转向量转换为相对应的旋转矩阵 */Rodrigues(rvecsMat[i], rotation_matrix);fout << "第" << i + 1 << "幅图像的旋转矩阵:" << endl;fout << rotation_matrix << endl;fout << "第" << i + 1 << "幅图像的平移向量:" << endl;fout << tvecsMat[i] << endl << endl;}cout << "定标结果完成保存!!!" << endl;fout << endl;
}void m_undistort(vector<string>& FilesName, Size image_size, Mat& cameraMatrix, Mat& distCoeffs)
{Mat mapx = Mat(image_size, CV_32FC1);   //X 坐标重映射参数Mat mapy = Mat(image_size, CV_32FC1);   //Y 坐标重映射参数Mat R = Mat::eye(3, 3, CV_32F);cout << "保存矫正图像" << endl;string imageFileName;                  //校正后图像的保存路径stringstream StrStm;string temp;for (int i = 0; i < FilesName.size(); i++){Mat imageSource = imread(FilesName[i]);Mat newimage = imageSource.clone();//方法一:使用initUndistortRectifyMap和remap两个函数配合实现//initUndistortRectifyMap(cameraMatrix,distCoeffs,R, Mat(),image_size,CV_32FC1,mapx,mapy);//    remap(imageSource,newimage,mapx, mapy, INTER_LINEAR);//方法二:不需要转换矩阵的方式,使用undistort函数实现undistort(imageSource, newimage, cameraMatrix, distCoeffs);StrStm << i + 1;StrStm >> temp;imageFileName = "矫正后图像//" + temp + "_d.jpg";imwrite(imageFileName, newimage);StrStm.clear();imageFileName.clear();}std::cout << "保存结束" << endl;
}int main()
{string File_Directory1 = "C:\\Users\\86778\\source\\repos\\opencv_contrib_0202\\chess_image";   //文件夹目录1string FileType = ".jpg";    // 需要查找的文件类型//存放文件名的容器//vector<string>FilesName1 = { "left01.jpg","left03.jpg" };vector<string>FilesName1;getFilesName(File_Directory1, FileType, FilesName1);   // 标定所用图像文件的路径//cout << FilesName1.size();Size board_size = Size(9, 6);                         // 标定板上每行、列的角点数 Size square_size = Size(30, 30);                       // 实际测量得到的标定板上每个棋盘格的物理尺寸,单位mmMat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));        // 摄像机内参数矩阵Mat distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0));          // 摄像机的5个畸变系数:k1,k2,p1,p2,k3vector<Mat> rvecsMat;                                          // 存放所有图像的旋转向量,每一副图像的旋转向量为一个matvector<Mat> tvecsMat;                                          // 存放所有图像的平移向量,每一副图像的平移向量为一个matm_calibration(FilesName1, board_size, square_size, cameraMatrix, distCoeffs, rvecsMat, tvecsMat);//m_undistort(FilesName1, image_size, cameraMatrix, distCoeffs);waitKey(0);return 0;
}

标定显示的结果:

这里只列举两张,实际上有十几张,然后会输出相机内参与畸变参数,这就是相机标定最想得到的东西

到此为止相机标定已经结束了,接下来使用matlab的TOOLBOX_calib工具箱给大家可视化展示一下

二、matlab工具箱标定+可视化

下载位置:http://www.vision.caltech.edu/bouguetj/calib_doc/download/index.html

首先把解压的TOOLBOX_calib文件夹的路径设置到MATLAB里,在主页->设置路径->选择工具箱路径,然后添加路径

然后输入指令calib_gui,选择第一项:

然后点击image name,注意路径要在你的照片目录里,然后会显示照片名

然后根据下边提示完成读取:

后边会弹出一个读取后图像的样子:

点击Extract grid corners,提取每幅图的角点,点击完成后出现如下界面,然后根据提示进行输入,第一个可以敲回车,后边输入格子的边长(数量),然后手工选取四个边界:(注意这里默认每个格子100mm长)

每个图片都要标记一次,然后点击Calibration,这样相机各个参数就计算出来了,可以再在面板上点击ShowExtrinsic,可以看到假定相机不动和假定棋盘格不动两种情况下的相机与棋盘格的空间位置关系:

比如下边是我的情况:

最后感谢另一位博主关于工具箱的使用的介绍(https://blog.csdn.net/panpan_jiang1/article/details/80414737)

相机标定示例(OpenCV /C++ /matlab工具箱TOOLBOX_calib)相关推荐

  1. 相机标定教程(使用Matlab工具箱)

    理想的相机成像模型是小孔成像,空间中的物点与像面上的像点一一对应. 但是,实际情况中,相机存在畸变,导致像面上的像点产生偏移,这就需要构建非线性相机成像模型. 通过相机标定,可以求解得到相机的内参.外 ...

  2. opencv双目相机标定-示例代码分析

      在这里我使用的是Learning OpenCV3的示例,本节使用的项目代码可以在这里下载到. 一.运行示例   在下载完整个工程以后,按照工程使用说明,下载配置Opencv,运行VS2019项目即 ...

  3. 鱼眼相机标定以及OpenCV实现

    在另一篇文章中我已经写过有关普通相机模型及其OpenCV标定实现,这篇文章将主要关注鱼眼相机模型及其OpenCV标定实现. 先看一张鱼眼相机拍摄出来的结果: 从图中可以看出很明显的畸变.对鱼眼相机标定 ...

  4. 相机标定的理解及采用opencv和matlab工具箱的标定方法

    一.相机标定的目的 确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,建立摄像机成像的几何模型,这些几何模型参数就是摄像机参数. 二.通用摄像机模型 世界坐标系.摄像机坐标系和像平面 ...

  5. matlab相机标定工具箱进行相机标定,相机标定的理解及采用opencv和matlab工具箱的标定方法...

    一.相机标定的目的 确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,建立摄像机成像的几何模型,这些几何模型参数就是摄像机参数. 二.通用摄像机模型 世界坐标系.摄像机坐标系和像平面 ...

  6. OpenCV | 双目相机标定之OpenCV获取左右相机图像+MATLAB单目标定+双目标定

    博主github:https://github.com/MichaelBeechan 博主CSDN:https://blog.csdn.net/u011344545 原本网上可以搜到很多关于双目相机标 ...

  7. 研电赛项目之双目测距,涉及matlab相机标定,opencv多线程编程,摄像头读取,行人检测、BM立体匹配等等

    1 前言 今年参加了十五届研电赛,前天刚提交了作品,还有几天就答辩了,趁这几天总结一下这一个多月的收获. 本次研电赛作品为汽车行驶防碰撞系统,主要面向大型汽车在低速行驶场景下的防碰撞问题,通过双目相机 ...

  8. MATLAB 相机标定(单目)使用工具箱TOOLBOX_calib

    环境MATLAB R2014a+windows7 64位 1.单目摄像机标定 (1)首先把解压的TOOLBOX_calib文件夹的路径设置到MATLAB里,在主页->环境->设置路径-&g ...

  9. Matlab相机标定工具箱和标定结果评价

    用来做相机标定的工具很多,不过MATLAB中的相机标定工具箱使用起来相当舒服,概括起来:简单准确高效,下面我说一下单个相机和双目相机标定的流程和标定结果怎么判断好坏: 1. 单个相机标定 第一步:打开 ...

  10. matlab相机标定_综述 | 相机标定方法

    点击上方"计算机视觉life",选择"星标" 快速获得最新干货 在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相 ...

最新文章

  1. java线程的cancel_多线程-Cancel详解
  2. 全球与中国智慧物流市场”十四五“发展状况及投资前景规划报告2021-2027年版
  3. 携程一次Redis迁移容器后Slowlog“异常”分析
  4. 特斯拉CEO马斯克再卖4套房 挂牌价6250万美元
  5. 必须掌握的八种排序(7-8)--归并排序,基数排序
  6. 干货 | Github标星近3w,热榜第一,如何用Python实现所有算法和一些神经网络模型...
  7. TOJ3649欧拉回路
  8. Python:实现password generator复杂密码生成器算法(附完整源码)
  9. 虚拟光驱安装WIN7(client mac addr: no DHCP问题)
  10. 详细设计的工具——盒图(N-S图)
  11. 大学四年,从小白到大神,全网最硬核算法学习攻略,不接受反驳
  12. 【必看】没用的旧手机还能换钱,换换回收手机回收价格表曝光
  13. 几款入夏品牌包包可以看看
  14. Google 人机验证(reCaptcha)无法显示解决方案
  15. Android获取WiFi名称/路由器AP地址总结
  16. html js打印页边距,js 设立网页打印的页眉页脚和页边距
  17. 利用闲置笔记本电脑搭建linux服务器并布置自己的网站
  18. jnz和djnz_第3章单片机指令系统_练习
  19. 视频教程-软考信息系统项目管理师考试视频辅导课程-项目管理
  20. python教育学_我去过书声琅琅教育学Python,没想到却跟想象的不一样!

热门文章

  1. 计算机媒体分类及其特点,多媒体的媒体种类有哪些?试归纳叙述多媒体关键特性以及这些特性之间的关系。...
  2. 树莓派简单入门(基本小案例)
  3. 疫情下企业面临的关键网络安全建设,去繁从简,保住核心安全
  4. openjudge 买书
  5. linux 邮件文件名 病毒,linux-qmail 病毒/垃圾邮件处理
  6. C++实践参考——动物这样叫
  7. 阿里巴巴重要开源项目汇总
  8. 柯洁将在年内和“阿尔法狗”进行终极人机大战
  9. 北京地区首届区块链黑客松-DoraHacks
  10. 设计师们必须要知道的素材网站