相机标定-机器视觉基础(理论推导、Halcon和OpenCV相机标定)

article/2025/10/22 8:44:26

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

1 背景知识

        在讨论相机模型标定之前,我们应当先了解几何里面关于2D、3D空间里面几种几何变换形式。主要包括欧式变换、相似变换、仿射变换和透视变换,相机标定的过程,就是一个透视变换矩阵求解的过程。

参考来源:北京邮电大学鲁鹏老师的课件

1.1 2D平面上的变换

1.1.1 欧式变换

        所谓欧式变换,即只有平移加旋转的变换,例如在2D平面上有一个正方形,经过变换后正方形的尺寸没有发生改变,但中心点会发生改变,并且偏转了一定的角度。自由度为三个,即xy方向的平移和旋转的角度theta。

1.1.2 相似变换

        所谓的相似变换,即在欧式变换的基础上,附加一个均匀伸缩变换。经过变换后,在相似变换的基础上对原有的尺寸进行了放缩。但保证线与线之间的角度、长度的比值和面积的比值不变。自由度为四个:即xy方向的平移和旋转的角度再加一个放缩系数。

 1.1.3 仿射变换

        所谓的仿射变换,即在相似变换的基础上再增加了两个自由度。由上图的相似变换矩阵可以得知,决定矩阵数值的值主要有s、θ、X0、Y0。我们可以看到s、θ两个参数决定了矩阵里面的四个数值,假设这四个参数完全由a、b、c、d四个独立的变量进行控制,即仿射变换一共有六个自由度。变换前后线与线之间的平行性、平行线段长度的比值和面积的比值不变。

1.1.3 透视变换

        所谓的透视变换,即在仿射变换的基础上再次增加两个自由度,由仿射变换的矩阵我们可以看到,其第三行两个数值都为0,假设其不为0,分别为V1、V2。因此,透视变换一共有八个自由度,变换前后只有四共线的交比保持不变,即交比不变性。

1.2 3D空间上的变换

1.2.1 欧式变换

        所谓欧式变换,即只有平移加旋转的变换。当其在三维空间里面时,旋转共有绕三个轴xyz的旋转,平移也是发生在三维空间。同时在此基础上附加一个放缩系数s,其一共有七个自由度,变换前后不变量:点变换到点、线变换到线;保持点的共线性、线的共面性;保持直线与直线、直线与平面、平面与平面的平行性不变;保持线的夹角不变。

三维空间旋转平移变换可参考:机器人学导论

 1.2.2 仿射变换

        三维空间的仿射变换,在上面欧式变换的基础上进一步增加自由度。由欧式变换的上图可知,其中R旋转矩阵由绕三个XYZ轴旋转的角度决定的。R矩阵是一个3×3的矩阵,当里面九个参数互相独立时,就是三维空间的仿射变换。其一共有12个自由度,变换前后的不变量:保持无穷远平面不变(无穷远点变换到无穷远点),保持直线与直线、直线与平面、平面与平面的平行性不变。

 1.2.3 透视变换

        三维空间的透视变换,可以看到上面仿射变换矩阵主要由矩阵A、向量t、向量0和1组成。因为A为一个3×3的矩阵,所以向量0是一个三维向量。如果这个向量不为0,为三个独立的数值构成的向量。则透视变换矩阵在仿射变换矩阵的基础上再次增加了三个自由度,其一共有十五个自由度,变换前后的不变量有:点变换到点、线变换到线,保持点的共线性和线的共面性。

        综上所述,经过透视变换后,线的平行性不再保持,这也引申出影消点和影消线的概念,即在实际空间中,互相平行的铁轨,变换到图像里,会相交于一点。由这些点组成的线就是影消线。

基于影消线和影消点,可以实现三维重建,这里不再赘述。

鲁鹏老师三维重建课程之单视图重建https://blog.csdn.net/beyond951/article/details/122265206?spm=1001.2014.3001.5501

2 相机内外参模型推导

2.1 相机外参

        在三维空间中,准确描述执行器的状态,需要包括执行器的位置信息和姿态信息。齐次变换矩阵在机器人学中描述一个坐标系到另一个坐标系变换关系的矩阵,包括位姿的旋转分量和平移分量。

         相机小孔成像模型

        如图上图所示,显示了针孔相机成像的透视投影模型。世界点P通过透镜的光学中心投射到像面上的点P',点位于光学中心后面距离(焦距)f处。基于该投影模型,可以描述物体在世界坐标系中的点映射到图像平面和相应的相机参数。

        世界坐标系变换到相机坐标系

       如图上图所示,先确定点 P是在世界坐标系WCS中,为确定世界坐标系映射到图像坐标系的关系,需要先转换成相机坐标系CCS。定义CCS,使其x轴和y轴分别平行于图像的c轴和r轴,z轴垂直于图像平面。其可以用位姿进行描述,也可以用齐次变换矩阵cwH表示。因此,相机坐标系点Pc(Xc,Yc,Zc)可由世界坐标系Pw(Xw,Yw,Zw)变换得到:

 2.2 相机内参

        假设成像面位于光心前面距离为f的位置,如下图所示。

        接下来,将相机坐标系CCS的点(Xc,Yc,Zc)投影到图像坐标系。对于针孔相机模型,投影为透视投影,由此可得:

        对于远心相机模型,透视为平行投影,此时,没有焦距,f近似于无穷远,由此可得:

 (1)畸变矫正

        相机在加工过程中,由于各类非线性因素的影响,会存在一定的误差,从而造成镜头畸变。导致视觉系统获取的图像与实际图像之间产生差别。不同相机产生的畸变情况也会有差异,在制造装配过程中产生的误差,造成图像径向畸变比较严重。

        坐标点投影到成像面后,畸变会造成成像面上的点qc(u,v)偏移至qc'(u',v')。其效果图如下图所示,如果没有畸变存在的情况下,成像面上P‘应投影在点P和光学中心延长线与成像面的交点处。相机畸变的存在造成P在不同的位置。相机畸变是一种可以单独在图像平面上建模的变换,畸变可以用出发模型或多项式模型来建模。

        除法模型使用一个参数k来模拟径向变形。基于除法模型,通过下面的方程表示相机的畸变模型。

        这些方程可以通过解析的方法进行反求,如果采用除法模型,则会得到下列方程,将未有畸变的坐标转化为畸变的坐标,其解析解如下:

        参数k用来模拟径向变形的大小。如果k为负,则扭曲为桶形,而k为正,则扭曲为枕形。其变形如图所示。

        多项式模型使用三个参数(K1,K2,K3)来模拟径向畸变,两个参数(P1,P2)来模拟扭转变形。下面的多项式模型可以将失真的像平面坐标转换为未失真的像平面坐标。

        该模型不能用解析法进行反求。因此,失真图像平面坐标必须从未失真图像平面坐标数值计算出来。综上考虑,本文采用多项式模型对相机获取的图像进行矫正,最终可以得到5个畸变参数K1,K2,K3,P1,P2。

编程代码实现

基于Halcon标定

        基于halcon标定主要是采集完图像后运用halcon的标定助手对相机内外参进行标定。采集到的图像如下图所示:

标定后的内外参为:

标定后的外参为:

基于OpenCV标定

用于标定的图像:

标定的程序代码:

void Cam_Calib()
{Creat_CalibImg_Path();vector<string> Img_Vec;char dir[64];char fileNames[64];ofstream fout(calibrationResult);  //保存标定结果的文件// 利用dir命令将当前目录下的.bmp文件名写入names.txtsprintf(dir, "%s%s%s%s%s%s", "dir ", chess_boardImage_path, "*.bmp", " /a /b >", chess_boardImage_path, "names.txt");system(dir);char name[64] = "";// 打开文件读取其中的文件名sprintf(fileNames, "%s%s", chess_boardImage_path, "names.txt");FILE* fp = fopen(fileNames, "r");if (NULL == fp){printf("error,cannot open the name list");}while (fgets(name, 64, fp) != NULL){char subname[64];sscanf(name, "%[^\n]%s", subname);string image_name;stringstream stream;stream << subname;image_name = stream.str();Img_Vec.push_back(image_name.substr(0, image_name.length() - 4));}//角点提取cout << "角点提取………………" << endl;vector<Mat>  image_Seq;                  //检测到角点图片vector<vector<Point2f>>  corners_Seq;    //保存检测到的所有角点int Num = Img_Vec.size();for (int i = 0; i < Num; i++){cout << "图像 #" << Img_Vec[i] << "..." << endl;string imageFileName;imageFileName = Img_Vec[i];     //图像的文件名imageFileName += ".bmp";       //图像的文件名.bmpMat image = imread(chess_boardImage_path + imageFileName);vector<Point2f> corners1 = Api.Get_Conners(image, Conner_Size, chess_boardCorner_path + Img_Vec[i], 0);if (corners1.size() == Conner_Size.width*Conner_Size.height){corners_Seq.push_back(corners1);image_Seq.push_back(image);cout << "Frame corner #" << Img_Vec[i] << "success" << endl;}else{cout << "can not find chessboard corners!\n";}}if (image_Seq.size() <= 0)  return;cout << "共提取" << image_Seq.size() << "张图像角点!\n";//摄像机标定cout << "开始标定………………" << endl;vector<vector<Point3f>>  object_Points = Api.Get_CalibCoord_Points(Real_Size, image_Seq.size(), Conner_Size);calibrateCamera(object_Points, corners_Seq, image_Seq[0].size(), intrinsic_matrix, distortion_coeffs, rotation_vectors, translation_vectors, CV_CALIB_FIX_K3, cv::TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 50, 1e-6));  //CV_CALIB_FIX_K3cout << "标定完成!\n";cout << "每幅图像的标定误差:" << endl;double total_err = 0.0;                   //所有图像的平均误差的总和	for (int i = 0; i < image_Seq.size(); i++){double err = Api.Calib_Error(object_Points[i], corners_Seq[i], intrinsic_matrix, distortion_coeffs, rotation_vectors[i], translation_vectors[i]);total_err += err /= object_Points[i].size();cout << "图 " << Img_Vec[i] << " 的平均误差:" << err << "像素" << endl;fout << "图 " << Img_Vec[i] << " 的平均误差:" << err << "像素" << endl;}cout << "总体平均误差:" << total_err / image_Seq.size() << "像素" << endl;fout << "总体平均误差:" << total_err / image_Seq.size() << "像素" << endl << endl;cout << "评价完成!" << endl;//保存标定结果cout << "开始保存标定结果………………" << endl;Mat rotation_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); //保存每幅图像的旋转矩阵fout << "相机内参数矩阵:" << endl;fout << intrinsic_matrix << endl;fout << "畸变系数:\n";fout << distortion_coeffs << endl;File_Help.SaveCameraParams(calibration_file_path, intrinsic_matrix, distortion_coeffs);for (int i = 0; i < image_Seq.size(); i++){fout << "图 " << Img_Vec[i] << " 的旋转向量:" << endl;fout << rotation_vectors[i] << endl;//将旋转向量转换为相对应的旋转矩阵Rodrigues(rotation_vectors[i], rotation_matrix);fout << "图 " << Img_Vec[i] << " 的旋转矩阵:" << endl;fout << rotation_matrix << endl;fout << "图 " << Img_Vec[i] << " 的平移向量:" << endl;fout << translation_vectors[i] << endl;File_Help.Save_RT_Params(".\\image\\source\\" + Img_Vec[i] + ".xml", rotation_matrix, translation_vectors[i]);}cout << "完成保存...." << endl;fout << endl;cout << "保存矫正图像....." << endl;for (int i = 0; i < image_Seq.size(); i++){Mat Correted_Img = Api.Correct_Img(image_Seq[i], intrinsic_matrix, distortion_coeffs);imwrite(chess_boardCorner_path + Img_Vec[i] + "_d.bmp", Correted_Img);}cout << "保存结束....." << endl;
}

标定结果:

 标定结果影响因素:


http://chatgpt.dhexx.cn/article/jTdy6PES.shtml

相关文章

计算机视觉——相机标定

相机标定 1. 相机标定1.1相机内外参数&#xff08;重点&#xff09;1.2 为什么要做相机标定 2. 相机标定的意义3. 相机成像模型3.1 像素坐标系3.2 图像坐标系3.3 相机坐标系3.4 世界坐标系 4.坐标系转换4.1 世界坐标到相机坐标4.2 相机坐标到图像坐标4.3 像素坐标到世界坐标的变…

相机标定、双目相机标定(原理)、三维重建效果展示

1.相机标定的目的&#xff1a; &#xff08;1&#xff09;通过单目相机标定分别求出左右相机的内参数和外参数。 &#xff08;2&#xff09;矫正由于镜头畸变造成的图片的变形&#xff0c;例如&#xff0c;现实中的直线&#xff0c;拍摄成图像后会外凸或内凹&#xff0c;进行相…

相机标定(Camera calibration)原理及步骤

这已经是我第三次找资料看关于相机标定的原理和步骤&#xff0c;以及如何用几何模型&#xff0c;我想十分有必要留下这些资料备以后使用。这属于笔记总结。 1.为什么要相机标定&#xff1f; 在图像测量过程以及机器视觉应用中&#xff0c;为确定空间物体表面某点的三维几何位置…

计算机视觉—— 相机标定

目录 简介 一、相机模型 1.坐标系 2.坐标系变化 3.相机畸变模型 二、相机标定原理 三、张正友黑白棋盘格标定 2.1.算法思想 2.2.求解内参和外参的积 2.3.求解内参矩阵 2.4.求解外参矩阵 2.5.得到相机畸变矫正参数 2.6.L-M算法参数优化 三、实验 3.1 实验要求…

相机标定的原理及实现

本文参考文档&#xff1a; 原理部分&#xff1a;https://blog.csdn.net/honyniu/article/details/51004397 代码部分&#xff1a;https://www.cnblogs.com/wildbloom/p/8320351.html &#xff1b;https://blog.csdn.net/firemicrocosm/article/details/48594897# 1、相机标定的…

计算机视觉-相机标定(Camera Calibration)

1.相机标定基本原理 1.1 简介 在图像测量过程以及机器视觉应用中&#xff0c;为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系&#xff0c;必须建立摄像机成像的几何模型,这些几何模型参数就是摄像机参数。在大多数条件下这些参数必须通过实验与计算才…

相机标定(Camera calibration)原理、步骤

这已经是我第三次找资料看关于相机标定的原理和步骤&#xff0c;以及如何用几何模型&#xff0c;我想十分有必要留下这些资料备以后使用。这属于笔记总结。 1.为什么要相机标定&#xff1f; 在图像测量过程以及机器视觉应用中&#xff0c;为确定空间物体表面某点的三维几何位置…

采用Matlab的Filter Designer设计低通滤波器并对信号进行低通滤波

今天在使用Filter Designer设计低通滤波器进行低通滤波发现滤波总是得不到理想中的结果&#xff0c;经过一番折腾后终于解决了问题&#xff0c;特写博文供大家学习参考。 1、找到工具箱中的Filter Designer并打开&#xff1a; 2、按照如下图所示设计参数&#xff0c;注意Fs最好…

利用Matlab filterDesigner 工具生成FIR滤波器函数,并调用实现低通滤波

本文使用的开发环境为&#xff1a;Win10 Matlab2018a 版本。 在matlab命令窗口输入&#xff1a;filterDesigner命令&#xff0c;即可打开filterDesigner设计工具。 按照下图调整FIR低通滤波器的参数&#xff1a; 我们设计的是采样频率100Hz&#xff0c;截止频率10Hz的8阶FIR低…

matlab由滤波的系数得到传输函数 设计带通滤波器 design fdatool设计IIR带通滤波器

写在前面的话&#xff1a; 由滤波器系数得到传输函数&#xff1a; 使用matlab fdatool设计滤波器&#xff0c;得到幅频响应&#xff0c;得到滤波器系数&#xff0c;由系数如何得到滤波器的参数&#xff1f; 我的方法是 使用&#xff1a;点击Filt-Export to simulink Model, …

带通滤波器的设计

一、滤波器&#xff1a;滤波器按照频带划分可以分为&#xff1a;低通滤波器(LPF)、高通滤波器(HPF)、带通滤波器(BPF)、带阻滤波器(BEF)。其中射频天线领域主要采用带通滤波器(BPF)。 二、带通滤波器(BPF)&#xff1a; ①&#xff1a;RF BPF&#xff1a;从天线中取出期望频带的…

【matlab图像处理】理想低通滤波器

实验原理&#xff1a; 在一幅图像中&#xff0c;低频部分对应图像变化缓慢的部分即图像大致外观和轮廓&#xff0c;高频部分对应图像变化剧烈的部分即图像细节&#xff0c;图像噪声也属于高频部分。低通滤波器的功能是让低频率通过而滤掉或衰减高频&#xff0c;效果是图像去噪平…

Matlab滤波器的设计

在IIR滤波器设计过程中&#xff0c;通常利用模拟滤波器来设计数字滤波器&#xff0c;首先要根据滤波器的性能指标设计出相应的模拟滤波器的系统传递函数G(s)&#xff0c;然后由传递函数G(s)经Z变换得到所需要的数字滤波器的离散型传递函数。常用的Z变换方法有冲激响应不变法和双…

[Matlab]巴特沃夫滤波器设计:低通、高通、带通和带阻(1)

[Matlab]巴特沃夫滤波器设计&#xff1a;低通、高通、带通和带阻-------&#xff08;1&#xff09; ​ 巴特沃斯滤波器&#xff08;Butterworth filter&#xff09;称作最大平坦滤波器。巴特沃斯滤波器的特点是通频带内的频率响应曲线最大限度平坦&#xff0c;没有纹波&#x…

基于MATLAB的Filter使用,低通、带通和高通滤波器的MATLAB程序分享

基于MATLAB的Filter使用&#xff0c;低通、带通和高通滤波器的MATLAB程序分享 完整程序如下&#xff1a; clear all close all clc %% Parameter Interface Frequence0 60; %单位&#xff1a;Hz Frequence1 130; %单位&#xff1a;Hz F…

MATLAB —— 低通滤波器设计与信号滤波

百度百科 - 简介&#xff1a; 低通滤波器是容许低于截止频率的信号通过&#xff0c; 但高于截止频率的信号不能通过的电子滤波装置。 &#xff08;1&#xff09;提取滤波器&#xff08;系数矩阵&#xff09; 打开工具&#xff1a; MATLAB - APP - Filter Designer 参数设置&am…

低通滤波-matlab低通滤波程序

本例程展示了信号处理中低通滤波的作用&#xff0c;首先生成一个高斯白噪声&#xff0c;然后对其进行低通滤波。低通滤波器的截止频率和Q值可以自己设定&#xff0c;得到低通滤波器的传输函数后&#xff0c;在经过双线性变换法得到其单位脉冲响应。滤波后对原始信号的频谱和滤波…

模拟和数字低通滤波器的MATLAB实现

转自&#xff1a;http://blog.sina.com.cn/s/blog_79ecf6980100vcrf.html 低通滤波器参数&#xff1a;Fs8000&#xff0c;fp2500&#xff0c;fs3500&#xff0c;Rp1dB&#xff0c;As30dB&#xff0c;其他滤波器可以通过与低通之间的映射关系实现。 %%模拟滤波器 %巴特沃斯——…

matlab低通滤波

低通滤波器的功能是让低频率通过而滤掉或衰减高频&#xff0c;其作用是过滤掉包含在高频中的噪声。所以低通滤波的效果是图像去噪声平滑增强&#xff0c;但同时也抑制了图像的边界&#xff0c;造成图像不同程度上的模糊。 大于大小为MN的图像&#xff0c;频率点&#xff08;u&…

基于MATLAB的filter的使用,低通、带通和高通滤波器设计

1、目的 学习MATLAB的filter函数的使用&#xff0c;通过设计低通、带通和高通滤波器对其进行仿真 2、用到的主要函数和工具 MATLAB、FDATOOL、filter、fft 3、设计 信号的产生 %% Parameter Interface Frequence0 60; %单位&#xff1a;Hz Frequenc…