1 程序环境

系统环境:Windows 10;
编译器:Visual Studio 2015;
Opencv版本:Opencv4.1.2版本;

2 原理

主要为张正友标定法,利用棋盘格进行标定,原理参考:https://www.cnblogs.com/zyly/p/9366080.html.

3 程序源码

#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 cv;
using namespace std;/*计算标定板上模块的实际物理坐标*/
void calobjectPoints(vector<Point3f>& obj, Size &boardSize, int squareSize)
{for (int i = 0; i < boardSize.height; ++i)for (int j = 0; j < boardSize.width; ++j)obj.push_back(Point3f((float)(j*squareSize), (float)(i*squareSize), 0.f));
}void main()
{Size boardSize = Size(8, 6);  // 标定棋盘格的内角点尺寸(如7x7)float squareSize = 30.0;  // 标定板上黑白格子的实际边长(mm)int nrFrames = 18;       // 用于标定的图像数目string outputFileName;  // 输出文件的名称vector<string> imageList;Size imageSize;/****************将存放标定图像的路径读入到imageList(1/2)向量中****************/char name[100];for (int i = 1; i <= nrFrames; i++){sprintf_s(name, "../Picture/%d%s", i, ".bmp");imageList.push_back(name);}cout << "imageList.size:" << imageList.size() << endl;/****************标定前的准备工作:获取objectPoints和imagePoints*********************///1 首先根据squareSize(棋盘格的实际边长,比如20mm)和boardSize(棋盘格的角点数,比如5x5),利用for循环得到角点的世界坐标objectPoints(Z坐标假设为0)//2 利用for循环和findChessboardCorners()函数得到与角点世界坐标向量objectPoints对应的图像像素坐标向量imagePointsvector<vector<Point2f> > imagePoints;//各个图像找到的角点的集合vector<vector<Point3f> > objectPoints(1);//暂时先定义一维的objectPoints1,等确定了imagePoints的维数之后再进行扩容calobjectPoints(objectPoints[0], boardSize, squareSize);//数据初始化,否则标定函数会报错bool displayCorners1 = true;//可通过改变变量displayCorners1的值来确定是否展示获取角点后的图像for (int i = 0; i<imageList.size(); i++){Mat src1 = imread(imageList[i], 1);imageSize = src1.size();vector<Point2f> pointBuf1;//2读取角点并进行亚像素,并提取角点bool found1 = findChessboardCorners(src1, boardSize, pointBuf1);//使用不同方法进行棋盘格查找,不同方法标定结果差别很小//若是圆盘标定板,使用如下函数//bool found1 = findCirclesGrid(src1, boardSize, pointBuf1);if (found1){Mat grayimage1;cvtColor(src1, grayimage1, COLOR_BGR2GRAY);//亚像素角点检测,输出 pointBuf1cornerSubPix(grayimage1, pointBuf1, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.1));imagePoints.push_back(pointBuf1);if (displayCorners1){Mat MidImage1 = src1.clone();//画角点drawChessboardCorners(MidImage1, boardSize, Mat(pointBuf1), found1);imshow("相机角点获取情况", MidImage1);waitKey(300);}}}destroyWindow("相机角点获取情况");//利用resize()函数对objectPoints向量进行扩容objectPoints.resize(imagePoints.size(), objectPoints[0]);/********************************进行相机标定******************************************///通过calibrateCamera()函数进行相机标定//主要为了得到相机的内参矩阵cameraMatrix、畸变系数矩阵distCoeffs//另外可以通过函数返回的重投影误差大小评价相机标定的精度如何//这里得到的相机外参矩阵不重要Mat cameraMatrix = Mat::eye(3, 3, CV_64F);Mat distCoeffs = Mat::zeros(5, 1, CV_64F);//畸变系数的顺序是[k1,k2,p1,p2,k3]vector<Mat> rvecs, tvecs;/*calibrateCamera()输入参数 objectPoints  角点的实际物理坐标imagePoints   角点的图像坐标imageSize     图像的大小输出参数cameraMatrix  相机的内参矩阵distCoeffs    相机的畸变参数,畸变系数的顺序是[k1,k2,p1,p2,k3]rvecs         旋转矢量(外参数)tvecs         平移矢量(外参数)*///如果我们不需要K3,在初始化K3为O之后,可以使用标志CV_CALIB_FIX_K3,这样,标定函数不会改变K3的值//一般地,K3应设置为0,除非使用鱼眼镜头(参考《learning opencv》第十一章)//返回的distCoeffs1向量的长度由标志位flag决定,当flag设置为CV_CALIB_RATIONAL_MODEL时返回所有畸变参数(8个)//当设置成其他flag时都返回5维的畸变系数,即[k1,k2,p1,p2,k3]std::cout << "正在进行相机标定..." << endl;double re_project_err1 = calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs,CALIB_FIX_K3);//checkRange()函数---用于检查矩阵中的每一个元素的有效性bool ok1 = checkRange(cameraMatrix) && checkRange(distCoeffs);if (ok1){cout << "相机标定成功!" << endl;cout << "相机标定的重投影误差:" << re_project_err1 << endl;cout<<"相机内参矩阵:"<<endl<<cameraMatrix<<endl;cout<<"相机畸变系数矩阵:"<<endl<<distCoeffs<<endl;}bool showUndistorsed = true;if(showUndistorsed==true){for(int i=0;i<imageList.size();i++){Mat temp=imread(imageList[i],1);;//利用undistort()函数得到经过畸变矫正的图像Mat undistort_view;undistort(temp, undistort_view, cameraMatrix, distCoeffs);imshow("原畸变图像",temp);imshow("畸变矫正图像",undistort_view);waitKey(300);}waitKey(0);destroyAllWindows();}return;
}

4程序运行结果

4.1 标定过程

4.2 矫正结果

4.3 程序输出

imageList.size:18
正在进行相机标定...
相机标定成功!
相机标定的重投影误差:0.23798
相机内参矩阵:
[644.5700972013594, 0, 642.8375612362015;0, 645.8354258462127, 364.0228582907439;0, 0, 1]
相机畸变系数矩阵:
[0.002553038122538741;-0.0001313912440763992;-0.0002960299077962415;-0.001097115527929319;0]

(若能帮到读者,请关注+点赞,谢谢!)

单目标定:OpenCV4实现单目标定及矫正相关推荐

  1. 项目实战——基于计算机视觉的物体位姿定位及机械臂抓取(单目标定)

    项目实战--基于计算机视觉的物体位姿定位及机械臂抓取(单目标定) 请各位读者朋友注意,这里面很多东西涉及到我的毕设,写作辛苦,请勿滥用,转载请务必注明出处!         单目标定主要分为两个部分, ...

  2. 【研究报告】从单目深度估计到单目三维场景重建-沈春华老师-VALSE Webinar 22-13(总第279期)

    从单目深度估计到单目三维场景重建-沈春华老师-VALSE Webinar 22-13(总第279期) 报告总结 & 相关论文 论文代码 相关术语 前言 研究问题 单目深度估计 单目三维场景重建 ...

  3. 双目标定(一)单目标定与矫正的基本介绍

    1.单目相机标定 首先,任何标定都是用基于小孔模型的数学模型去近似相机模型,我们需要用fx = f/dx, fy = f/dy,图像坐标系中的光心原点坐标(和可能的缩放因子ks)这5个相机内参数,切向 ...

  4. 双目测距(一)--图像获取与单目标定

    原文: http://blog.csdn.net/chenyusiyuan/article/details/5961769 双目测距的基本原理 如上图所示,双目测距主要是利用了目标点在左右两幅视图上成 ...

  5. 任务感知单目深度估计的3D目标检测

    标题:Task-Aware Monocular Depth Estimation for 3D Object Detection 作者:Xinlong Wang1∗, Wei Yin1, Tao Ko ...

  6. MO-LTR:基于单目RGB视频的多目标定位、跟踪与重建

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 标题:MO-LTR: Multiple Object Localization, Tracking a ...

  7. Opencv单目标定flag的设定

    1. flag中的标签顺序: 在代码中的对应如下: enum{CALIB_USE_INTRINSIC_GUESS = 1 << 0,CALIB_RECOMPUTE_EXTRINSIC = ...

  8. Opencv 单目标定

    参考博客:https://blog.csdn.net/xuelabizp/article/details/50314633(该作者很慷慨的分享了代码) 多图与公式直接摘录自以上博客 参考:学习Open ...

  9. Halcon 单目标定,畸变矫正,图像坐标系转世界坐标系

    代码为Halcon代码,只有代码以及解释,默认已经理解世界坐标系(WCS)到相机坐标系(CCS)到图像坐标系(ICS)到像素坐标系(PCS)转换 *********************1. 标定内 ...

  10. cv::omni::StereoCalibrate 源码解析 (一) —— 单目标定

    cv::omni::StereoCalibrate 的代码逻辑和cv::StereoCalibrate相似. 在opencv库基础上稍微改动. //omni单目标定 输入calibrate(世界坐标系 ...

最新文章

  1. 拿haojava官方过程
  2. GT Transceiver的复位与初始化(2)CPLL复位以及QPLL复位
  3. VMprotect简介
  4. Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照
  5. linux | 网卡驱动
  6. 96. 不同的二叉搜索树
  7. 无聊的一天_一人互联网公司背后的无聊技术
  8. 漫话:如何给女朋友解释什么是2PC(二阶段提交)?
  9. 半小时让你快速入门linux掌握基础命令
  10. notepad 配置python_Notepad++配置Python开发环境的图文详解
  11. jQuery EasyUI教程之datagrid应用-1
  12. Android自定义View研究(六)--View中的原点坐标相关问题
  13. Module build failed: Error: Couldn't find preset react relative to directory
  14. orangepizero编译ch934x驱动
  15. 关于R语言多水平线性回归分析
  16. buuctf—荷兰宽带数据泄露
  17. 记一次cocos逆向
  18. “2019-04-25T16:00:00.000+000”时间格式转换 (IE兼容问题)
  19. Java基础篇--多线程之第一个线程用来计算2~100000之间的素数的个数,第二个线程用来计算100000~200000之间的素数的个数
  20. 微信小程序 pages的使用

热门文章

  1. 内蒙古计算机二级2019年三月报名时间,2019年上半年内蒙古计算机软考考试报名通知,报名时间3月1日—3月23日...
  2. C#、C++、Java、Python选择哪个好?
  3. 书论79 笪重光《书筏》
  4. 质量管理(学习总结)
  5. CryptoJS实现vue项目路由传参AES加密
  6. 吴恩达深度学习笔记【1】
  7. 我们用的信息系统安全吗?
  8. mysql 基本操作题_Mysql基础练习12题
  9. 大数据——21世纪的石油和钻石,怎么用?
  10. 【whistle配置eruda代理】生产环境在线接入eruda查看network注意事项