基于opencv的相机标定C++代码

这篇具有很好参考价值的文章主要介绍了基于opencv的相机标定C++代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、准备

事先需要把标定图片放在images目录下:

基于opencv的相机标定C++代码

 calibdata.txt的内容是标定图片的路径+图片文件名称:

基于opencv的相机标定C++代码

希望对大家有帮助!!!(目前我使用的VS是2019版本,opencv4_1_2)。

二、代码

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

using namespace std;
using namespace cv;

int main()
{
	string dir = "E:\\myProgame\\CameraCalibration\\CameraCalibration\\"; // 存储标定图片路径的txt文件所在路径
	ifstream fin(dir + "calibdata.txt");                                  // 读取标定图片的路径,以输入方式打开文件
	if (!fin) 
	{
		cerr << "没有找到文件" << endl;
		return -1;
	}
	ofstream fout(dir + "calibration_result.txt");     // 输出结果保存在此文本文件下,以输出方式打开文件

	cout << "1、开始提取角点……" << endl;             // points_all_images
	int image_nums = 0;                                // 有效图片数量统计
	int points_per_row = 9;                            // 标定版每行的内点数
	int points_per_col = 6;                            // 标定版每列的内点数
	Size image_size;                                   // 图片尺寸
	Size corner_size(points_per_row, points_per_col);  // 标定板每行每列角点个数,共9*6个角点
	vector<Point2f> points_per_image;                  // 缓存每幅图检测到的角点
	vector<vector<Point2f>> points_all_images;         // 保存检测到的所有角点
	string image_file_name;			                   // 声明一个文件名的字符串
	Mat image_raw, image_gray;                         // 彩色图,灰度图
	while (getline(fin, image_file_name))
	{
		image_raw = imread(image_file_name);                                             // 按照RGB图像读取数据
		cvtColor(image_raw, image_gray, COLOR_BGR2GRAY);                                 // 将BGR图转化为灰度图
		bool success = findChessboardCorners(image_gray, corner_size, points_per_image); // 角点检测
		if (!success)
		{
			cout << "角点提取失败" << endl;
			exit(1);  // 非正常执行导致退出程序
		}
		else
		{
			find4QuadCornerSubpix(image_gray, points_per_image, Size(5, 5)); // 亚像素角点,也可使用cornerSubPix()
			points_all_images.push_back(points_per_image);                   // 保存亚像素角点
		}
		if (image_nums == 0)
		{
			cout << "channels = " << image_raw.channels() << endl;  // 图像的通道数
			cout << "image type = " << image_raw.type() << endl;    // 数据类型,CV_8UC3
			image_size.width = image_raw.cols;                      // 图像的宽,对应着列数(x)
			image_size.height = image_raw.rows;                     // 图像的高,对应着行数(y)
			cout << "image width = " << image_size.width << endl;   // 打印图像宽
			cout << "image height = " << image_size.height << endl; // 打印图像高
		}
		image_nums++;
	}
	cout << "image_nums = " << image_nums << endl;     // 输出图像数目

	cout << "2、开始计算角点3D坐标……" << endl;     // points3D_all_images
	Size block_size(10, 10);                         // 每个小方格实际大小10mm,(w,h)
	vector<Point3f> points3D_per_image;              // 初始化角点三维坐标,从左到右,从上到下
	Point3f point3D;                                 // 3D点(x,y,z)
	for (int i = 0; i < corner_size.height; i++)     // 第i行---y
	{
		for (int j = 0; j < corner_size.width; j++)  // 第j列---x
		{
			point3D = Point3f(block_size.width * j, block_size.height * i, 0);
			points3D_per_image.push_back(point3D);
		}
	}
	vector<vector<Point3f>> points3D_all_images(image_nums, points3D_per_image); // 保存所有图像角点的三维坐标
	int point_counts = corner_size.area();                                       // 每张图片上角点个数

	cout << "3、开始标定相机……" << endl;           // calibrateCamera
	Mat cameraMat(3, 3, CV_32FC1, Scalar::all(0));   // 内参矩阵3*3
	Mat distCoeffs(1, 5, CV_32FC1, Scalar::all(0));  // 畸变矩阵1*5,既考虑径向畸变,又考虑切向
	vector<Mat> rotationMat;                         // 旋转矩阵
	vector<Mat> translationMat;                      // 平移矩阵
	calibrateCamera(points3D_all_images, points_all_images, image_size, cameraMat, distCoeffs, rotationMat, translationMat, 0); // 标定

	cout << "4、开始对标定结果进行评价……" << endl; // projectPoints
	double total_err = 0.0;                          // 所有图像平均误差总和
	double err = 0.0;                                // 每幅图像的平均误差
	vector<Point2f> points_reproject;                // 重投影点
	fout << "计算每幅图像的标定误差:" << endl;
	for (int i = 0; i < image_nums; i++)
	{
		points_per_image = points_all_images[i];         // 第i张图像提取角点
		points3D_per_image = points3D_all_images[i];     // 第i张图像中角点的3D坐标
		projectPoints(points3D_per_image, rotationMat[i], translationMat[i], cameraMat, distCoeffs, points_reproject); // 重投影
		Mat detect_points_Mat(1, points_per_image.size(), CV_32FC2);  // 变为1*S的矩阵,2通道保存提取角点的像素坐标
		Mat points_reproj_Mat(1, points_reproject.size(), CV_32FC2);  // 变为1*S的矩阵,2通道保存投影角点的像素坐标
		for (int j = 0; j < points_per_image.size(); j++)
		{
			detect_points_Mat.at<Vec2f>(0, j) = Vec2f(points_per_image[j].x, points_per_image[j].y);
			points_reproj_Mat.at<Vec2f>(0, j) = Vec2f(points_reproject[j].x, points_reproject[j].y);
		}
		err = norm(points_reproj_Mat, detect_points_Mat, NormTypes::NORM_L2);  // 计算两者之间的误差
		total_err += err /= point_counts;
		fout << "第" << i + 1 << "幅图像的平均误差为: " << err << "像素" << endl;  
	}
	fout << "总体平均误差为: " << total_err / image_nums << "像素" << endl << endl;

	cout << "5、将标定结果写入文件……" << endl;
	fout << "相机内参数矩阵:" << endl << cameraMat << endl << endl;
	fout << "相机的畸变系数:" << endl << distCoeffs << endl << endl;
	Mat rotate_Mat = Mat(3, 3, CV_32FC1, Scalar::all(0)); // 保存旋转矩阵
	for (int i = 0; i < image_nums; i++)
	{
		Rodrigues(rotationMat[i], rotate_Mat);  // 将旋转向量通过罗德里格斯公式转换为旋转矩阵
		fout << "第" << i + 1 << "幅图像的旋转矩阵为:" << endl << rotate_Mat << endl << endl;
		fout << "第" << i + 1 << "幅图像的平移向量为:" << endl << translationMat[i] << endl << endl;
	}
	fout << endl;
	fout.close();

	return 0;
}

拍摄图像示例

基于opencv的相机标定C++代码

 标定结果保存在一个txt文件中:

基于opencv的相机标定C++代码

三、核心函数解析

1、角点检测函数

bool success = findChessboardCorners(image_gray, corner_size, points_per_image);

    输入:灰度图像image_gray;角点个数大小corner_size,如Size(9,6);

    输出:所有角点在图像上的像素坐标points_per_image

2、提取亚像素角点坐标

find4QuadCornerSubpix(image_gray, points_per_image, Size(5, 5)); 

    输入:灰度图像image_gray;角点像素坐标points_per_image

    输出:角点亚像素坐标points_per_image

3、标定相机

calibrateCamera(points3D_all_images, points_all_images, image_size, camera_K, distCoeffs, rotationMat, translationMat, 0);

    输入:
    * points3D_all_images: 真实三维坐标,格式vector<vector<cv::Point3f>>
    * points_all_images: 提取的角点,格式vector<vector<Point2f>>
    * image_size: 图像尺寸

    输出:
    * camera_K : 内参矩阵K,格式Mat(3,3)
    * distCoeffs: 畸变参数,径向畸变k1,k2,切向畸变p1,p2,径向畸变k3,格式Mat(1,5)
    * rotationMat: 每个图片的旋转向量,格式vector<Mat>
    * translationMat: 每个图片的平移向量,格式vector<Mat>

4、重投影

projectPoints(points3D_per_image, rotationMat[i], translationMat[i], camera_K, distCoeffs, points_reproj);

    输入:图像中角点的真实世界坐标points3D_per_image,格式vector<Point3f>

    输出:重投影后像素点坐标points_reproj,格式vector<Point2f>

    重投影公式:

 基于opencv的相机标定C++代码

四、标定相机原理

    参考:相机标定(六)—— 张正友标定法__归尘_的博客-CSDN博客_张正友标定法

    参考:Camera Calibration and 3D Reconstruction — OpenCV 2.4.13.7 documentation

基于opencv的相机标定C++代码文章来源地址https://www.toymoban.com/news/detail-452802.html

到了这里,关于基于opencv的相机标定C++代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于OpenCV的单目相机标定与三维定位

           相机是产生图像数据的硬件,广泛应用于消费电子、汽车、安防等领域。围绕着相机衍生出一系列的研究与应用领域,包括传统的图像处理和基于深度学习的智能应用等。目前大火的自动驾驶中相机也是重要的硬件组成,如环视用鱼眼相机,adas用周视相机。    

    2024年02月09日
    浏览(27)
  • 普通单目相机标定——准备工作

            这里我们还是以普通相机为例(非鱼眼相机)来进行后续的相关标定操作,再回顾下相机的成像模型如下所示。         已知相机内参(fx,fy,u0,v0),畸变系数[k1,k2,k3,p1,p2],相机外参[R|T]。世界坐标系中点Pw(Xw,Yw,Zw),投影至像素坐标系点p(u,v)的计算过程如下。 1)

    2024年02月15日
    浏览(27)
  • python利用opencv进行相机标定获取参数,并根据畸变参数修正图像附有全部代码(流畅无痛版)

    今天的低价单孔摄像机(照相机)会给图像带来很多畸变。畸变主要有两 种:径向畸变和切想畸变。如下图所示,用红色直线将棋盘的两个边标注出来, 但是你会发现棋盘的边界并不和红线重合。所有我们认为应该是直线的也都凸 出来了。 在 3D 相关应用中,必须要先校正这些畸变

    2024年02月06日
    浏览(35)
  • 双目相机标定及高精度测量方法,含c++和python代码说明

    视觉测量定位中,双面相机高精度标定是一个重要的步骤。下面是关于如何进行双面相机高精度标定的说明和C++和Python代码实现。 1. 双面相机高精度标定的原理 双面相机高精度标定的目的是确定相机内部参数和外部参数。其中,内部参数包括焦距、主点和畸变系数等,外部

    2023年04月08日
    浏览(31)
  • 相机标定-机器视觉基础(理论推导、Halcon和OpenCV相机标定)

             相机标定是获得目标工件精准坐标信息的基础。首先,必须进行相机内参标定,构建一个模型消除图像畸变;其次,需要对相机和机器人的映射关系进行手眼标定,构建一个模型将图像坐标系上的点映射到世界坐标系。主要分为背景知识、相机内外参模型推导、

    2023年04月21日
    浏览(37)
  • 【相机标定】opencv python 标定相机内参时不计算 k3 畸变参数

    畸变参数 k3 通常用于描述径向畸变的更高阶效应,即在需要高精度的应用中可以用到,一般的应用中 k1, k2 足矣。 常见的应用中, orbslam3 中是否传入 k3 是可选的,而 kalibr 标定中则只需要传入 k1, k2 。但计算 k3 时的 k1, k2 不等于不计算 k3 时的 k1, k2 ,因此需要学会两种场景下

    2024年02月09日
    浏览(28)
  • OpenCV中的相机标定

          之前在https://blog.csdn.net/fengbingchun/article/details/130039337 中介绍了相机的内参和外参,这里通过OpenCV中的接口实现对内参和外参的求解。       估计相机参数的过程称为相机标定(camera calibration)。相机标定是使用已知的真实世界模式(例如棋盘)来估计相机镜头和传感器的外

    2023年04月19日
    浏览(46)
  • OpenCV实战(23)——相机标定

    我们已经了解了相机如何通过在 2D 传感器平面上投射光线来拍摄 3D 场景,生成的图像准确地表示了在捕获图像的瞬间从特定视点观察场景。然而,图像形成过程消除了与其所表示场景元素的深度有关的所有信息。为了恢复场景的 3D 结构和摄像机的 3D 姿态,我们需要对相机参

    2024年02月08日
    浏览(46)
  • opencv相机标定

      当你把摄像机放在一个特定的位置,在它的后面放一个目标图像,或者是把摄像机放到某个物体上,摄像机周围的物体是什么形状,你需要知道这些信息。 当你在计算机上处理图像时,会使用以下三个参数: 1.像素坐标(pixel):像素坐标是相机中每个点的世界坐标(x,y

    2024年02月16日
    浏览(24)
  • Opencv_棋盘格标定相机

    文章内容: 读取棋盘格图片进行标定 生成棋盘格图片 保存标定后的内容 棋盘格下载:https://gitee.com/liangbo1996/chessboard_27mm

    2024年01月19日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包