1,在自己的项目下创建文件夹sample->left

2,创建两个txt文件,caliberation_result.txt,filename.txt

3,将拍的标定图名称写到filename.txt中

我这里就用了前五5张标定图,最好多用一些

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <fstream>
#include <vector>using namespace cv;
using namespace std;void main(char* args)
{//保存文件名称std::vector<std::string>  filenames;//需要更改的参数//左相机标定,指定左相机图片路径,以及标定结果保存文件string infilename = "sample/left/filename.txt";        //如果是右相机把left改为rightstring outfilename = "sample/left/caliberation_result.txt";//标定所用图片文件的路径,每一行保存一个标定图片的路径  ifstream 是从硬盘读到内存ifstream fin(infilename);//保存标定的结果  ofstream 是从内存写到硬盘ofstream fout(outfilename);/*1.读取毎一幅图像,从中提取出角点,然后对角点进行亚像素精确化、获取每个角点在像素坐标系中的坐标像素坐标系的原点位于图像的左上角*/std::cout << "开始提取角点......" << std::endl;;//图像数量int imageCount = 0;//图像尺寸cv::Size imageSize;//标定板上每行每列的角点数cv::Size boardSize = cv::Size(12, 9); //缓存每幅图像上检测到的角点std::vector<Point2f>  imagePointsBuf;//保存检测到的所有角点std::vector<std::vector<Point2f>> imagePointsSeq;char filename[100];if (fin.is_open()){//读取完毕?while (!fin.eof()){//一次读取一行fin.getline(filename, sizeof(filename) / sizeof(char));//保存文件名filenames.push_back(filename);//读取图片Mat imageInput = cv::imread(filename);//cvtColor(imageInput,imageInput,COLOR_RGB2GRAY);/* imshow("原属图",imageInput);waitKey(0);*///读入第一张图片时获取图宽高信息if (imageCount == 0){imageSize.width = imageInput.cols;imageSize.height = imageInput.rows;std::cout << "imageSize.width = " << imageSize.width << std::endl;std::cout << "imageSize.height = " << imageSize.height << std::endl;}//imshow("显示图",imageInput);imageCount++;std::cout << "imageCount = " << imageCount << std::endl;//提取每一张图片的角点if (cv::findChessboardCorners(imageInput, boardSize, imagePointsBuf) == 0){//找不到角点std::cout << "Can not find chessboard corners!" << std::endl;exit(1);}else{//cout <<"我出现了吗?"<<endl;Mat viewGray;//转换为灰度图片cv::cvtColor(imageInput, viewGray, cv::COLOR_BGR2GRAY);//亚像素精确化   对粗提取的角点进行精确化cv::find4QuadCornerSubpix(viewGray, imagePointsBuf, cv::Size(5, 5));//保存亚像素点imagePointsSeq.push_back(imagePointsBuf);//在图像上显示角点位置cv::drawChessboardCorners(viewGray, boardSize, imagePointsBuf, true);//显示图片//cv::imshow("Camera Calibration", viewGray);cv::imwrite("test.jpg", viewGray);//等待0.5s//waitKey(500);}}//计算每张图片上的角点数 54int cornerNum = boardSize.width * boardSize.height;//角点总数int total = imagePointsSeq.size() * cornerNum;std::cout << "total = " << total << std::endl;for (int i = 0; i < total; i++){int num = i / cornerNum;int p = i % cornerNum;//cornerNum是每幅图片的角点个数,此判断语句是为了输出,便于调试if (p == 0){std::cout << "\n第 " << num + 1 << "张图片的数据 -->: " << std::endl;}//输出所有的角点std::cout << p + 1 << ":(" << imagePointsSeq[num][p].x;std::cout << imagePointsSeq[num][p].y << ")\t";if ((p + 1) % 3 == 0){std::cout << std::endl;}}std::cout << "角点提取完成!" << std::endl;/*2.摄像机标定 世界坐标系原点位于标定板左上角(第一个方格的左上角)*/std::cout << "开始标定" << std::endl;//棋盘三维信息,设置棋盘在世界坐标系的坐标//实际测量得到标定板上每个棋盘格的大小cv::Size squareSize = cv::Size(26, 26);//毎幅图片角点数量std::vector<int> pointCounts;//保存标定板上角点的三维坐标std::vector<std::vector<cv::Point3f>> objectPoints;//摄像机内参数矩阵 M=[fx γ u0,0 fy v0,0 0 1]cv::Mat cameraMatrix = cv::Mat(3, 3, CV_64F, Scalar::all(0));//摄像机的5个畸变系数k1,k2,p1,p2,k3cv::Mat distCoeffs = cv::Mat(1, 5, CV_64F, Scalar::all(0));//每幅图片的旋转向量std::vector<cv::Mat> tvecsMat;//每幅图片的平移向量std::vector<cv::Mat> rvecsMat;//初始化标定板上角点的三维坐标int i, j, t;for (t = 0; t < imageCount; t++){std::vector<cv::Point3f> tempPointSet;//行数for (i = 0; i < boardSize.height; i++){//列数for (j = 0; j < boardSize.width; j++){cv::Point3f realPoint;//假设标定板放在世界坐标系中z=0的平面上。realPoint.x = i * squareSize.width;realPoint.y = j * squareSize.height;realPoint.z = 0;tempPointSet.push_back(realPoint);}}objectPoints.push_back(tempPointSet);}//初始化每幅图像中的角点数量,假定每幅图像中都可以看到完整的标定板for (i = 0; i < imageCount; i++){pointCounts.push_back(boardSize.width * boardSize.height);}//开始标定cv::calibrateCamera(objectPoints, imagePointsSeq, imageSize, cameraMatrix, distCoeffs, rvecsMat, tvecsMat);std::cout << "标定完成" << std::endl;//对标定结果进行评价std::cout << "开始评价标定结果......" << std::endl;//所有图像的平均误差的总和double totalErr = 0.0;//每幅图像的平均误差double err = 0.0;//保存重新计算得到的投影点std::vector<cv::Point2f> imagePoints2;std::cout << "每幅图像的标定误差:" << std::endl;fout << "每幅图像的标定误差:" << std::endl;for (i = 0; i < imageCount; i++){std::vector<cv::Point3f> tempPointSet = objectPoints[i];//通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点imagePoints2(在像素坐标系下的点坐标)cv::projectPoints(tempPointSet, rvecsMat[i], tvecsMat[i], cameraMatrix, distCoeffs, imagePoints2);//计算新的投影点和旧的投影点之间的误差std::vector<cv::Point2f> tempImagePoint = imagePointsSeq[i];cv::Mat tempImagePointMat = cv::Mat(1, tempImagePoint.size(), CV_32FC2);cv::Mat imagePoints2Mat = cv::Mat(1, imagePoints2.size(), CV_32FC2);for (int j = 0; j < tempImagePoint.size(); j++){imagePoints2Mat.at<cv::Vec2f>(0, j) = cv::Vec2f(imagePoints2[j].x, imagePoints2[j].y);tempImagePointMat.at<cv::Vec2f>(0, j) = cv::Vec2f(tempImagePoint[j].x, tempImagePoint[j].y);}//Calculates an absolute difference norm or a relative difference norm.err = cv::norm(imagePoints2Mat, tempImagePointMat, NORM_L2);totalErr += err /= pointCounts[i];std::cout << "  第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;fout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;}//每张图像的平均总误差std::cout << "  总体平均误差:" << totalErr / imageCount << "像素" << std::endl;fout << "总体平均误差:" << totalErr / imageCount << "像素" << std::endl;std::cout << "评价完成!" << std::endl;//保存标定结果std::cout << "开始保存标定结果....." << std::endl;//保存每张图像的旋转矩阵cv::Mat rotationMatrix = cv::Mat(3, 3, CV_32FC1, Scalar::all(0));fout << "相机内参数矩阵:" << std::endl;fout << cameraMatrix << std::endl << std::endl;fout << "畸变系数:" << std::endl;fout << distCoeffs << std::endl << std::endl;for (int i = 0; i < imageCount; i++){fout << "第" << i + 1 << "幅图像的旋转向量:" << std::endl;fout << tvecsMat[i] << std::endl;//将旋转向量转换为相对应的旋转矩阵cv::Rodrigues(tvecsMat[i], rotationMatrix);fout << "第" << i + 1 << "幅图像的旋转矩阵:" << std::endl;fout << rotationMatrix << std::endl;fout << "第" << i + 1 << "幅图像的平移向量:" << std::endl;fout << rvecsMat[i] << std::endl;}std::cout << "保存完成" << std::endl;/************************************************************************显示定标结果*************************************************************************/cv::Mat mapx = cv::Mat(imageSize, CV_32FC1);cv::Mat mapy = cv::Mat(imageSize, CV_32FC1);cv::Mat R = cv::Mat::eye(3, 3, CV_32F);std::cout << "显示矫正图像" << endl;initUndistortRectifyMap(cameraMatrix, distCoeffs, R, cameraMatrix, imageSize, CV_32FC1, mapx, mapy);Mat test11 = imread("5.jpg");Mat newTest = test11.clone();remap(test11, newTest, mapx, mapy, INTER_LINEAR);imshow("原始图像", test11);imshow("矫正后图像", newTest);imwrite("revise.jpg", newTest);waitKey(0);//释放资源fin.close();fout.close();system("pause");}
}
    cv::Size boardSize = cv::Size(12, 9);  这里要根据自己的标定板动态的改变 ,我用的是 13*10的

结果:
畸变图

矫正图

参考下面这位大牛写的文章
https://www.cnblogs.com/zyly/p/9366080.html#_label0_3

关于张正友的更多原理博客我收集了几个还不错的:
https://blog.csdn.net/heroacool/article/details/50286677 (原文)

https://blog.csdn.net/next_voyager/article/details/86623229

https://blog.csdn.net/u010368556/article/details/79254673?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

https://blog.csdn.net/weixin_36340947/article/details/78246174?utm_medium=distribute.wap_relevant.none-task-blog-baidulandingword-2

张正友畸变矫正C++代码相关推荐

  1. 张正友标定论文的解读和C++代码编写

    1.概述 张正友标定相机内参是非常经典的标定算法,现在代码已经被集成到MATLAB和opencv里面.不过因为算法涉及到基础的相机坐标系.图像坐标系.公式推导,以及优化算法,故根据张正友论文进行分模块 ...

  2. 张正友相机标定(全流程,含畸变,matlab源代码解析)

    张正友标定的具体原理很多文章已经介绍,这里主要结合源代码对其中的基本原理及本人遇到的问题进行介绍.(仅介绍基本原理供本人复习,同时方便他人,如有问题,请及时指正勿喷) 1. 标定基本思路介绍 相机标定 ...

  3. 相机标定(二)-畸变校正,张正友标定法

    >>>文章索引<<< 相机标定(一)-原理及内参.外参 相机标定(二)-畸变校正,张正友标定法 相机标定(三)-相机成像模型 1 一些基本的方程推导 1.1 预定义 ...

  4. 标定代码:张正友标定法(matlab工具箱自编程序)(matlab)

    张正友标定法原理 张正友标定法,一般采用二维棋盘格标定板. 标定板制作链接:棋盘格 张正友标定法推导过程

  5. 张正友相机标定Opencv实现以及标定流程标定结果评价图像矫正流程解析(附标定程序和棋盘图)

    from:https://blog.csdn.net/dcrmg/article/details/52939318 使用Opencv实现张正友法相机标定之前,有几个问题事先要确认一下,那就是相机为什么 ...

  6. 计算机视觉——张正友棋盘格标定法

    文章目录 环境 前言 一.实验原理 1.相机标定 2.张正友标定法 3.步骤 二.实验过程 1.实验步骤 2.结果展示 3.分析 三.问题和总结 环境 win10,64位,python2.7,编译器: ...

  7. 工业相机标定(张正友标定法)

    目录 相机标定的概念 a. 相机标定的定义 b. 相机标定的目的 相机标定的过程 a. 标定板选择 b. 标定板摆放及拍摄 c. 标定板角点提取 张正友标定法 a. 反解相机矩阵 b.反解畸变系数 使 ...

  8. 【三维重建】相机标定:张正友标定法

    系列文章目录 本系列开始于2022.12.25,开始记录三维重建项目课题研究时的学习笔记,其中主要分为以下几部分组成: 一.相机成像及坐标系之间的转换关系 二.相机标定:张正友标定法 三.特征检测与匹 ...

  9. 单目相机标定实现--张正友标定法

    文章目录 一:相机坐标系,像素平面坐标系,世界坐标系,归一化坐标系介绍 1:概述 公式 二:实现 1:整体流程 4:求出每张图像的单应性矩阵并用LMA优化 5:求解理想无畸变情况下的摄像机的内参数和外 ...

最新文章

  1. Python练习2-基本聊天程序-虚拟茶会话
  2. 在Controller中使用AOP
  3. 深圳 | 腾讯 Robotics X 招聘语义视觉方向实习生和正式员工
  4. 20200715:动态规划复习day06
  5. python 科学计算设计_Python程序设计与科学计算
  6. 如何让元素支持 height:100%效果
  7. ReactJS基础(续)
  8. 出招挽留欧盟公民 英国政府推出“身份申请App”
  9. c语言编译音乐简谱,单片机音乐曲谱_单片机c语言音乐简谱代码
  10. CIO40知识星球—3年主管升职IT经理(28-30岁)
  11. css背景图与html插入img的区别,css背景图与html插入img的区别
  12. 转-零死角玩转stm32-高级篇之SDIO(4bit + DMA、支持SDHC、带协议分析)
  13. gtx1060+linux+双显卡,ubuntu14.04+GTX1060 重新安装显卡驱动
  14. 前端 H5 页面地图展示,只需要传入经纬度就可展示地图及周边生活娱乐
  15. poj1125Stockbroker Grapevine(最短路floyd)
  16. 记C#和C++混合开发的坑们
  17. 运城学院公共计算机教学部办公室,运城学院公共计算机教学部.docx
  18. 安卓学习底层开发学习方法?
  19. 使用微软官方工具下载安装Windows10系统
  20. 微型计算机的i3或i5一般指的是,英特尔i3、i5、i7分别相当于骁龙哪个层次的处理器?...

热门文章

  1. 自动采集的网站源码-自动采集发布的电影小说新闻网站程序源码
  2. 有关MAC、PHY和MII
  3. Signatures and Zero-Knowledge Proofs
  4. 游戏一直被攻击掉线卡顿是什么原因?服务器被攻击怎么办?
  5. Keep不甘做“工具人”
  6. 相关性分析和相似度计算
  7. outlook技巧-常用email账号设置
  8. Ecstore的微信账号绑定会员免登录
  9. 赛宁网安助力中国移动打造国内领先云安全能力
  10. 开发质量问题复盘总结-pua性质的标题