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

article/2025/9/22 3:15:47

使用Opencv实现张正友法相机标定之前,有几个问题事先要确认一下,那就是相机为什么需要标定,标定需要的输入和输出分别是哪些?

 

相机标定的目的:获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的选择和平移矩阵),内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像。

相机标定的输入:标定图像上所有内角点的图像坐标,标定板图像上所有内角点的空间三维坐标(一般情况下假定图像位于Z=0平面上)。

相机标定的输出:摄像机的内参、外参系数。

 

这三个基础的问题就决定了使用Opencv实现张正友法标定相机的标定流程、标定结果评价以及使用标定结果矫正原始图像的完整流程:

 

1. 准备标定图片

2. 对每一张标定图片,提取角点信息

3. 对每一张标定图片,进一步提取亚像素角点信息

4. 在棋盘标定图上绘制找到的内角点(非必须,仅为了显示)

5. 相机标定

6. 对标定结果进行评价

7. 查看标定效果——利用标定结果对棋盘图进行矫正

 

1. 准备标定图片

 

标定图片需要使用标定板在不同位置、不同角度、不同姿态下拍摄,最少需要3张,以10~20张为宜。标定板需要是黑白相间的矩形构成的棋盘图,制作精度要求较高,如下图所示:

 

 

 

2.对每一张标定图片,提取角点信息

 

需要使用findChessboardCorners函数提取角点,这里的角点专指的是标定板上的内角点,这些角点与标定板的边缘不接触。

 findChessboardCorners函数原型:

 

//! finds checkerboard pattern of the specified size in the image
CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize,OutputArray corners,int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE );

 

第一个参数Image,传入拍摄的棋盘图Mat图像,必须是8位的灰度或者彩色图像;

第二个参数patternSize,每个棋盘图上内角点的行列数,一般情况下,行列数不要相同,便于后续标定程序识别标定板的方向;

第三个参数corners,用于存储检测到的内角点图像坐标位置,一般用元素是Point2f的向量来表示:vector<Point2f> image_points_buf;

第四个参数flage:用于定义棋盘图上内角点查找的不同处理方式,有默认值。

 

 

 

3. 对每一张标定图片,进一步提取亚像素角点信息

 

 

 

为了提高标定精度,需要在初步提取的角点信息上进一步提取亚像素信息,降低相机标定偏差,常用的方法是cornerSubPix,另一个方法是使用find4QuadCornerSubpix函数,这个方法是专门用来获取棋盘图上内角点的精确位置的,或许在相机标定的这个特殊场合下它的检测精度会比cornerSubPix更高?

cornerSubPix函数原型:

 

//! adjusts the corner locations with sub-pixel accuracy to maximize the certain cornerness criteria
CV_EXPORTS_W void cornerSubPix( InputArray image, InputOutputArray corners,Size winSize, Size zeroZone,TermCriteria criteria );

 

第一个参数image,输入的Mat矩阵,最好是8位灰度图像,检测效率更高;

 

第二个参数corners,初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据,一般用元素是Pointf2f/Point2d的向量来表示:vector<Point2f/Point2d> iamgePointsBuf;

第三个参数winSize,大小为搜索窗口的一半;

第四个参数zeroZone,死区的一半尺寸,死区为不对搜索区的中央位置做求和运算的区域。它是用来避免自相关矩阵出现某些可能的奇异性。当值为(-1,-1)时表示没有死区;

第五个参数criteria,定义求角点的迭代过程的终止条件,可以为迭代次数和角点精度两者的组合;

find4QuadCornerSubpix函数原型:

 

//! finds subpixel-accurate positions of the chessboard corners
CV_EXPORTS bool find4QuadCornerSubpix(InputArray img, InputOutputArray corners, Size region_size);

 

第一个参数img,输入的Mat矩阵,最好是8位灰度图像,检测效率更高;

 

 

第二个参数corners,初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据,一般用元素是Pointf2f/Point2d的向量来表示:vector<Point2f/Point2d> iamgePointsBuf;

第三个参数region_size,角点搜索窗口的尺寸;

在其中一个标定的棋盘图上分别运行cornerSubPix和find4QuadCornerSubpix寻找亚像素角点,两者定位到的亚像素角点坐标分别为:

 

   cornerSubPix:                                                 find4QuadCornerSubpix:

                       

 

虽然有一定差距,但偏差基本都控制在0.5个像素之内。

 

 

4. 在棋盘标定图上绘制找到的内角点(非必须,仅为了显示)

 

 

drawChessboardCorners函数用于绘制被成功标定的角点,函数原型:

 

 

//! draws the checkerboard pattern (found or partly found) in the image
CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize,InputArray corners, bool patternWasFound );

 

第一个参数image,8位灰度或者彩色图像;

第二个参数patternSize,每张标定棋盘上内角点的行列数;

第三个参数corners,初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据,一般用元素是Pointf2f/Point2d的向量来表示:vector<Point2f/Point2d> iamgePointsBuf;

第四个参数patternWasFound,标志位,用来指示定义的棋盘内角点是否被完整的探测到,true表示别完整的探测到,函数会用直线依次连接所有的内角点,作为一个整体,false表示有未被探测到的内角点,这时候函数会以(红色)圆圈标记处检测到的内角点;

以下是drawChessboardCorners函数中第四个参数patternWasFound设置为true和false时内角点的绘制效果:

patternWasFound=ture时,依次连接各个内角点:

 


 

patternWasFound=false时,以(红色)圆圈标记处角点位置:

 

 

 

5. 相机标定

 

 

获取到棋盘标定图的内角点图像坐标之后,就可以使用calibrateCamera函数进行标定,计算相机内参和外参系数,

calibrateCamera函数原型:

 

//! finds intrinsic and extrinsic camera parameters from several fews of a known calibration pattern.
CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints,InputArrayOfArrays imagePoints,Size imageSize,CV_OUT InputOutputArray cameraMatrix,CV_OUT InputOutputArray distCoeffs,OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,int flags=0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON) );

 

第一个参数objectPoints,为世界坐标系中的三维点。在使用时,应该输入一个三维坐标点的向量的向量,即vector<vector<Point3f>> object_points。需要依据棋盘上单个黑白矩阵的大小,计算出(初始化)每一个内角点的世界坐标。

 

第二个参数imagePoints,为每一个内角点对应的图像坐标点。和objectPoints一样,应该输入vector<vector<Point2f>> image_points_seq形式的变量;

第三个参数imageSize,为图像的像素尺寸大小,在计算相机的内参和畸变矩阵时需要使用到该参数;

第四个参数cameraMatrix为相机的内参矩阵。输入一个Mat cameraMatrix即可,如Mat cameraMatrix=Mat(3,3,CV_32FC1,Scalar::all(0));

第五个参数distCoeffs为畸变矩阵。输入一个Mat distCoeffs=Mat(1,5,CV_32FC1,Scalar::all(0))即可;

第六个参数rvecs为旋转向量;应该输入一个Mat类型的vector,即vector<Mat>rvecs;

第七个参数tvecs为位移向量,和rvecs一样,应该为vector<Mat> tvecs;

第八个参数flags为标定时所采用的算法。有如下几个参数:

CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,在cameraMatrix矩阵中应该有fx,fy,u0,v0的估计值。否则的话,将初始化(u0,v0)图像的中心点,使用最小二乘估算出fx,fy。 
CV_CALIB_FIX_PRINCIPAL_POINT:在进行优化时会固定光轴点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置,光轴点将保持在中心或者某个输入的值。 
CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只将fy作为可变量,进行优化计算。当CV_CALIB_USE_INTRINSIC_GUESS没有被设置,fx和fy将会被忽略。只有fx/fy的比值在计算中会被用到。 
CV_CALIB_ZERO_TANGENT_DIST:设定切向畸变参数(p1,p2)为零。 
CV_CALIB_FIX_K1,…,CV_CALIB_FIX_K6:对应的径向畸变在优化中保持不变。 
CV_CALIB_RATIONAL_MODEL:计算k4,k5,k6三个畸变参数。如果没有设置,则只计算其它5个畸变参数。

第九个参数criteria是最优迭代终止条件设定。

在使用该函数进行标定运算之前,需要对棋盘上每一个内角点的空间坐标系的位置坐标进行初始化,标定的结果是生成相机的内参矩阵cameraMatrix、相机的5个畸变系数distCoeffs,另外每张图像都会生成属于自己的平移向量和旋转向量。

 

 

6. 对标定结果进行评价

 

 

对标定结果进行评价的方法是通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到空间三维点在图像上新的投影点的坐标,计算投影坐标和亚像素角点坐标之间的偏差,偏差越小,标定结果越好。

对空间三维坐标点进行反向投影的函数是projectPoints,函数原型是:

 

//! projects points from the model coordinate space to the image coordinates. Also computes derivatives of the image coordinates w.r.t the intrinsic and extrinsic camera parameters
CV_EXPORTS_W void projectPoints( InputArray objectPoints,InputArray rvec, InputArray tvec,InputArray cameraMatrix, InputArray distCoeffs,OutputArray imagePoints,OutputArray jacobian=noArray(),double aspectRatio=0 );

 

第一个参数objectPoints,为相机坐标系中的三维点坐标;

 

第二个参数rvec为旋转向量,每一张图像都有自己的选择向量;

第三个参数tvec为位移向量,每一张图像都有自己的平移向量;

第四个参数cameraMatrix为求得的相机的内参数矩阵;

第五个参数distCoeffs为相机的畸变矩阵;

第六个参数iamgePoints为每一个内角点对应的图像上的坐标点;

第七个参数jacobian是雅可比行列式;

第八个参数aspectRatio是跟相机传感器的感光单元有关的可选参数,如果设置为非0,则函数默认感光单元的dx/dy是固定的,会依此对雅可比矩阵进行调整;

下边显示了某一张标定图片上的亚像素角点坐标和根据标定结果把空间三维坐标点映射回图像坐标点的对比:

 

find4QuadCornerSubpix查找到的亚像素点坐标:                           projectPoints映射的坐标:

                                                     

 

以下是每一幅图像上24个内角点的平均误差统计数据:

 

 

7. 查看标定效果——利用标定结果对棋盘图进行矫正

 

 

利用求得的相机的内参和外参数据,可以对图像进行畸变的矫正,这里有两种方法可以达到矫正的目的,分别说明一下。

方法一:使用initUndistortRectifyMap和remap两个函数配合实现。

initUndistortRectifyMap用来计算畸变映射,remap把求得的映射应用到图像上。

initUndistortRectifyMap的函数原型:

 

//! initializes maps for cv::remap() to correct lens distortion and optionally rectify the image
CV_EXPORTS_W void initUndistortRectifyMap( InputArray cameraMatrix, InputArray distCoeffs,InputArray R, InputArray newCameraMatrix,Size size, int m1type, OutputArray map1, OutputArray map2 );

 

第一个参数cameraMatrix为之前求得的相机的内参矩阵;

第二个参数distCoeffs为之前求得的相机畸变矩阵;

第三个参数R,可选的输入,是第一和第二相机坐标之间的旋转矩阵;

第四个参数newCameraMatrix,输入的校正后的3X3摄像机矩阵;

第五个参数size,摄像机采集的无失真的图像尺寸;

第六个参数m1type,定义map1的数据类型,可以是CV_32FC1或者CV_16SC2;

第七个参数map1和第八个参数map2,输出的X/Y坐标重映射参数;

 

remap函数原型:

 

//! warps the image using the precomputed maps. The maps are stored in either floating-point or integer fixed-point format
CV_EXPORTS_W void remap( InputArray src, OutputArray dst,InputArray map1, InputArray map2,int interpolation, int borderMode=BORDER_CONSTANT,const Scalar& borderValue=Scalar());

 

第一个参数src,输入参数,代表畸变的原始图像;

 

第二个参数dst,矫正后的输出图像,跟输入图像具有相同的类型和大小;

第三个参数map1和第四个参数map2,X坐标和Y坐标的映射;

第五个参数interpolation,定义图像的插值方式;

第六个参数borderMode,定义边界填充方式;

 

方法二:使用undistort函数实现

undistort函数原型:

 

//! corrects lens distortion for the given camera matrix and distortion coefficients
CV_EXPORTS_W void undistort( InputArray src, OutputArray dst,InputArray cameraMatrix,InputArray distCoeffs,InputArray newCameraMatrix=noArray() );

 

第一个参数src,输入参数,代表畸变的原始图像;

 

 

第二个参数dst,矫正后的输出图像,跟输入图像具有相同的类型和大小;

第三个参数cameraMatrix为之前求得的相机的内参矩阵;

第四个参数distCoeffs为之前求得的相机畸变矩阵;

第五个参数newCameraMatrix,默认跟cameraMatrix保持一致;

方法一相比方法二执行效率更高一些,推荐使用。

 

以下是使用某一张标定图使用方法一和方法二进行矫正的效果图对比。

原始标定图像:

 

方法一,使用initUndistortRectifyMap和remap实现矫正效果:

 

方法二,使用undistort函数实现矫正效果:

 

两个方法从矫正效果上看,结果是一致的。

 

以下是完整的工程代码:

 

 

#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 main() 
{ifstream fin("calibdata.txt"); /* 标定所用图像文件的路径 */ofstream fout("caliberation_result.txt");  /* 保存标定结果的文件 */	//读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化	cout<<"开始提取角点………………";int image_count=0;  /* 图像数量 */Size image_size;  /* 图像的尺寸 */Size board_size = Size(4,6);    /* 标定板上每行、列的角点数 */vector<Point2f> image_points_buf;  /* 缓存每幅图像上检测到的角点 */vector<vector<Point2f>> image_points_seq; /* 保存检测到的所有角点 */string filename;int count= -1 ;//用于存储角点个数。while (getline(fin,filename)){image_count++;		// 用于观察检验输出cout<<"image_count = "<<image_count<<endl;		/* 输出检验*/cout<<"-->count = "<<count;		Mat imageInput=imread(filename);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;}/* 提取角点 */if (0 == findChessboardCorners(imageInput,board_size,image_points_buf)){			cout<<"can not find chessboard corners!\n"; //找不到角点exit(1);} else {Mat view_gray;cvtColor(imageInput,view_gray,CV_RGB2GRAY);/* 亚像素精确化 */find4QuadCornerSubpix(view_gray,image_points_buf,Size(5,5)); //对粗提取的角点进行精确化//cornerSubPix(view_gray,image_points_buf,Size(5,5),Size(-1,-1),TermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,0.1));image_points_seq.push_back(image_points_buf);  //保存亚像素角点/* 在图像上显示角点位置 */drawChessboardCorners(view_gray,board_size,image_points_buf,false); //用于在图片中标记角点imshow("Camera Calibration",view_gray);//显示图片waitKey(500);//暂停0.5S		}}int total = image_points_seq.size();cout<<"total = "<<total<<endl;int CornerNum=board_size.width*board_size.height;  //每张图片上总的角点数for (int ii=0 ; ii<total ;ii++){if (0 == ii%CornerNum)// 24 是每幅图片的角点个数。此判断语句是为了输出 图片号,便于控制台观看 {	int i = -1;i = ii/CornerNum;int j=i+1;cout<<"--> 第 "<<j <<"图片的数据 --> : "<<endl;}if (0 == ii%3)	// 此判断语句,格式化输出,便于控制台查看{cout<<endl;}else{cout.width(10);}//输出所有的角点cout<<" -->"<<image_points_seq[ii][0].x;cout<<" -->"<<image_points_seq[ii][0].y;}	cout<<"角点提取完成!\n";//以下是摄像机标定cout<<"开始标定………………";/*棋盘三维信息*/Size square_size = Size(10,10);  /* 实际测量得到的标定板上每个棋盘格的大小 */vector<vector<Point3f>> object_points; /* 保存标定板上角点的三维坐标 *//*内外参数*/Mat cameraMatrix=Mat(3,3,CV_32FC1,Scalar::all(0)); /* 摄像机内参数矩阵 */vector<int> point_counts;  // 每幅图像中角点的数量Mat distCoeffs=Mat(1,5,CV_32FC1,Scalar::all(0)); /* 摄像机的5个畸变系数:k1,k2,p1,p2,k3 */vector<Mat> tvecsMat;  /* 每幅图像的平移向量 */vector<Mat> rvecsMat; /* 每幅图像的旋转向量 *//* 初始化标定板上角点的三维坐标 */int i,j,t;for (t=0;t<image_count;t++) {vector<Point3f> tempPointSet;for (i=0;i<board_size.height;i++) {for (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;tempPointSet.push_back(realPoint);}}object_points.push_back(tempPointSet);}/* 初始化每幅图像中的角点数量,假定每幅图像中都可以看到完整的标定板 */for (i=0;i<image_count;i++){point_counts.push_back(board_size.width*board_size.height);}	/* 开始标定 */calibrateCamera(object_points,image_points_seq,image_size,cameraMatrix,distCoeffs,rvecsMat,tvecsMat,0);cout<<"标定完成!\n";//对标定结果进行评价cout<<"开始评价标定结果………………\n";double total_err = 0.0; /* 所有图像的平均误差的总和 */double err = 0.0; /* 每幅图像的平均误差 */vector<Point2f> image_points2; /* 保存重新计算得到的投影点 */cout<<"\t每幅图像的标定误差:\n";fout<<"每幅图像的标定误差:\n";for (i=0;i<image_count;i++){vector<Point3f> tempPointSet=object_points[i];/* 通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点 */projectPoints(tempPointSet,rvecsMat[i],tvecsMat[i],cameraMatrix,distCoeffs,image_points2);/* 计算新的投影点和旧的投影点之间的误差*/vector<Point2f> tempImagePoint = image_points_seq[i];Mat tempImagePointMat = Mat(1,tempImagePoint.size(),CV_32FC2);Mat image_points2Mat = Mat(1,image_points2.size(), CV_32FC2);for (int j = 0 ; j < tempImagePoint.size(); j++){image_points2Mat.at<Vec2f>(0,j) = Vec2f(image_points2[j].x, image_points2[j].y);tempImagePointMat.at<Vec2f>(0,j) = Vec2f(tempImagePoint[j].x, tempImagePoint[j].y);}err = norm(image_points2Mat, tempImagePointMat, NORM_L2);total_err += err/=  point_counts[i];   std::cout<<"第"<<i+1<<"幅图像的平均误差:"<<err<<"像素"<<endl;   fout<<"第"<<i+1<<"幅图像的平均误差:"<<err<<"像素"<<endl;   }   std::cout<<"总体平均误差:"<<total_err/image_count<<"像素"<<endl;   fout<<"总体平均误差:"<<total_err/image_count<<"像素"<<endl<<endl;   std::cout<<"评价完成!"<<endl;  //保存定标结果  	std::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;   }   std::cout<<"完成保存"<<endl; fout<<endl;/************************************************************************  显示定标结果  *************************************************************************/Mat mapx = Mat(image_size,CV_32FC1);Mat mapy = Mat(image_size,CV_32FC1);Mat R = Mat::eye(3,3,CV_32F);std::cout<<"保存矫正图像"<<endl;string imageFileName;std::stringstream StrStm;for (int i = 0 ; i != image_count ; i++){std::cout<<"Frame #"<<i+1<<"..."<<endl;initUndistortRectifyMap(cameraMatrix,distCoeffs,R,cameraMatrix,image_size,CV_32FC1,mapx,mapy);		StrStm.clear();imageFileName.clear();string filePath="chess";StrStm<<i+1;StrStm>>imageFileName;filePath+=imageFileName;filePath+=".bmp";Mat imageSource = imread(filePath);Mat newimage = imageSource.clone();//另一种不需要转换矩阵的方式//undistort(imageSource,newimage,cameraMatrix,distCoeffs);remap(imageSource,newimage,mapx, mapy, INTER_LINEAR);		StrStm.clear();filePath.clear();StrStm<<i+1;StrStm>>imageFileName;imageFileName += "_d.jpg";imwrite(imageFileName,newimage);}std::cout<<"保存结束"<<endl;	return ;
}

 

 

标定图例1:

 

标定图例2:

 

标定结果1:

 

标定结果2:

 

矫正效果1:

 

矫正效果2:

 

以上程序已经是完整程序,需要棋盘标定图或者整个项目包的可以到这里下载:张正友相机标定Opencv实现(完整程序+棋盘图)。

 


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

相关文章

标定工具介绍

作者 | WenDao_Engineer 微信公众号 | 闻道工程师之家 在前面标定相关的系列文章文对标定的基本介绍、标定的实现过程以及标定所涉及的相关协议都进行了介绍&#xff0c;从今天开始我们介绍一下标定实现过程中的标定工具相关知识。 标定系统组成 我们已经知道通过CCP或者XCP…

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

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

摄像机标定和立体标定

尝试用OpenCV来实现立体视觉也有一段时间了&#xff0c;主要的参考资料就是Learning OpenCV十一、十二章和OpenCV论坛上一些前辈的讨论。过程中磕磕碰碰&#xff0c;走了不少弯路&#xff0c;终于在前不久解决了最头大的问题&#xff0c;把整个标定、校准、匹配的流程调试成功。…

相机标定——张正友棋盘格标定法

目录 为什么需要相机标定&#xff1f; 相机标定可以做什么&#xff1f; 相机标定后可以得到什么&#xff1f; 什么情况下需要借助相机标定的方法&#xff1f; 相机标定的原理 实现相机标定的方法 为什么需要相机标定&#xff1f; 一个是由于每个镜头的在生产和组装过程中的…

标定方法——张正友标定法

标定 标定是联系世界坐标与像素坐标的环节&#xff0c;目的是求出相机和投影仪的内外参数&#xff0c;对于3D成像来说至关重要 张正友标定法 通过各种方法的对比&#xff0c;为了方便&#xff0c;我们采用的是张正友标定。我们主要对张正友标定法的原理进行介绍&#xff0c;…

笔记总结-相机标定(Camera calibration)原理、步骤

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

如何实现标定?

上一篇《什么是标定》对标定进行了初步的介绍&#xff0c;让大家有了一个感性的认识。标定是一项非常复杂的工作的&#xff0c;涉及方方面面的知识非常多&#xff0c;本文将对标定具体实现的过程进行介绍。 控制器对标定的支持 在前面的文章中介绍了控制算法是在软件编程的时候…

标定的分类(一)

关于标定的分类及说明(一) 现在工业机器视觉和计算机视觉大量应用标定算法&#xff0c;但是对于初学者来说&#xff0c;存在概念模糊&#xff0c;理论理解错误的现状&#xff0c;因此&#xff0c;需要对标定进行梳理&#xff0c;防止大家在学习过程中混淆各种标定概念。话不多…

什么是标定?

标定这两个字在汽车行业里的工程师基本都听过&#xff0c;但是在其他行业里大部分人都不知道什么是标定&#xff0c;甚至都没有听说过标定。什么是标定&#xff1f;举一个常见的例子&#xff0c;家里买了电视&#xff0c;连接网络就可以看节目了&#xff0c;与其他任何环境影响…

JMS及其API介绍

Java Message Service是java ee的规范之一&#xff0c;可以用来发送异步消息&#xff0c;在某些场景下&#xff0c;可以作为不同系统&#xff0c;或者不同模块之间的集成方式。 可以类比为通过数据库来集成的方式&#xff0c;模块A完成逻辑以后&#xff0c;往数据库插…

Springboot 整合 JMS

ActiveMQ JMS 仅支持 Java 平台。 由于 JMS 是一套标准&#xff0c;所以 SpringBoot 整合 JMS 必然是整合 JMS 的某一个实现。 Apache ActiveMQ 是一个开源的消息中间件&#xff0c;完全支持 JMS 1.1 规范&#xff0c;支持多种编程语言( C、C、C#、Delphi、Erlang、AdobeFla…

1.JMS规范介绍

目录 1.什么是JMS规范 2.什么是MOM 3.MOM的特点 4.JMS和MOM的关联 5.JMS的体系结构 6.JMS常见基本概念 7.JMS 的事务性会话和非事务性会话 8.JMS消息的可靠性机制 1.什么是JMS规范 Java 消息服务&#xff08;Java Message Service&#xff09;是 java 平台中关于面向消息…

JMS 示例

JMS 开发示例。 使用weblogic8作为jms server。 1、在weblogic中配置JMS。 配置JMS connection factory 配置JMS File Store 配置JMS Server 配置JMS destination 2、创建JMS Sender package jms; import java.util.Hashtable; import javax.jms.JMSE

ActiveMQ详解一 —— JMS介绍

1. JMS概述 不同系统之间信息交换&#xff0c;有多种方式。 SUN公司提出了一种面向详细的中间件服务—— JMS&#xff0c;Java消息服务&#xff0c;是JavaEE的标准/规范之一。 JMS指出&#xff1a;消息的发送应该是异步的、非阻塞的。 也就是说&#xff0c;消息的发送者发送…

SpringBoot整合JMS

SpringBoot整合JMS 文章目录 SpringBoot整合JMS前言一、JMS、AMQP概念以及区别二、ActiveMQ安装三、SpringBoot整合ActiveMQ&#xff1a;队列模式实例1、创建demo项目2、添加依赖3、添加application配置4、添加配置文件ActiveMQConfig5、创建JMS组件文件6、发送消息控制器7、测…

JMS规范介绍

目录 1.什么是JMS规范 2.什么是MOM 3.MOM的特点 4.JMS和MOM的关联 5.JMS的体系结构 6.JMS常见基本概念 7.JMS 的事务性会话和非事务性会话 8.JMS消息的可靠性机制 1.什么是JMS规范 Java 消息服务&#xff08;Java Message Service&#xff09;是 java 平台中关于面向消息…

JMS规范

一、JMS经典模式详解 JMS即Java消息服务&#xff08;Java Message Service&#xff09;应用程序接口&#xff0c;是一个Java平台中关于面向消息中间件&#xff08;MOM&#xff0c;Message oriented Middleware&#xff09;的API&#xff0c;用于在两个应用程序之间&#xff0c…

微服务 —— 消息服务中间件 JMS

一、消息服务中间件 对于大多数应用来说&#xff0c;可采用消息服务中间件来提升系统异步通信&#xff0c;消息解耦问题。 消息的作用&#xff1a;异步处理、应用解耦、流量削峰。 异步消息中的两个概念&#xff1a;消息代理、目的地 当消息发送者发送消息&#xff0c;由消息…

JMS解析(二)——JMS简介

JMS解析&#xff08;一&#xff09;——JMS简介_踩踩踩从踩的博客-CSDN博客 前言 本篇文章会紧接着上篇文章未介绍完毕的JMS规范&#xff0c;继续消息接收、事务管理、持久化以及应用的介绍。 消息接收 消息接收分为队列接收和topic消息接收 对于队列的接收基本的consumer…

JMS(Java消息服务)(Activemq简单介绍)

是什么&#xff1f; JMS&#xff08;java消息服务&#xff09;是规范&#xff0c;它定义了一些规则&#xff0c;一些接口。具体实现由各种做这个产品的厂家或开源组织来实现。 为什么&#xff1f; 在JMS还没有诞生前&#xff0c;每个企业都会有自己的一套内部消息系统&#…