[转]opencv中标定函数calibrateCamera

本文介绍相机标定的基本原理,包括三维点到二维点的投影公式、畸变模型及参数含义,并提供OpenCV中calibrateCamera函数的具体用法示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

世界坐标系的三维点投影到成像坐标系中的二维点的投影公式如下:

其中(X,Y,Z)为世界坐标系中的三维点;

u,v)为成像面坐标系中的二维点;

A为相机的内参数矩阵:(cx,cy)为主光轴点,一般为图像的中心;fxfy为焦距;

[R|t]为相机的外参数矩阵:R为旋转矩阵,t为位移矩阵;

上述公式的简单推理过程如下

考虑到镜头畸变

其中,k1,k2,k3,k4,k5k6为径向畸变,p1p2为轴向畸变。在opencv中,畸变矩阵的参数为(k1,k2,p1,p2[,k3[,k4,k5,k6]]])

Opencv中的标定模块常用的标定函数:

double calibrateCamera(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints,Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags=0)


其中

objectPoints为世界坐标系中的点。在使用时,应该输入一个三维点的vectorvector,即vector<vector<Point3f>> objectPoints

imagePoints为其对应的图像点。和objectPoints一样,应该输入std::vector<std::vector<cv::Point2f>> imagePoints型的变量。

imageSize为图像的大小,在计算相机的内参数和畸变矩阵需要用到;

cameraMatrix为内参数矩阵。输入一个cv::Mat cameraMatrix即可。

distCoeffs为畸变矩阵。输入一个cv::Mat distCoeffs即可。

rvecs为旋转向量;应该输入一个cv::Matvector,即vector<cv::Mat> rvecs因为每个vector<Point3f>会得到一个rvecs。

tvecs为位移向量;和rvecs一样,也应该为vector<cv::Mat> tvecs。

flags为标定是所采用的算法。可如下某个或者某几个参数:

CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,在cameraMatrix矩阵中应该有fx,fy,cx,cy的估计值。否则的话,将初始化(cx,cy)图像的中心点,使用最小二乘估算出fxfy如果内参数矩阵和畸变居中已知的时候,应该标定模块中的solvePnP()函数计算外参数矩阵。

CV_CALIB_FIX_PRINCIPAL_POINT:在进行优化时会固定光轴点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置,光轴点将保持在中心或者某个输入的值。

CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只将fy作为可变量,进行优化计算。当CV_CALIB_USE_INTRINSIC_GUESS没有被设置,fxfy将会被忽略。只有fx/fy的比值在计算中会被用到。

CV_CALIB_ZERO_TANGENT_DIST:设定切向畸变参数(p1,p2)为零。

CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6:对应的径向畸变在优化中保持不变。如果设置了CV_CALIB_USE_INTRINSIC_GUESS参数,

CV_CALIB_RATIONAL_MODEL:计算k4k5k6三个畸变参数。如果没有设置,则只计算其它5个畸变参数。

在使用calibrateCamera标定前,一般使用findChessboardCorners()函数获得棋盘标定板的角点位置。

还需要注意的是,在目前的opencv版本中(opencv2.4),当需要计算获得内参数矩阵时,即不使用CV_CALIB_USE_INTRINSIC_GUESS参数时,要求输入的objectPoints的为平面标定模式,即Z轴都为零。否则会出错。

如果对calibrateCamera的详细算法感兴趣,可以阅读张正友的标定算法A Flexible New Technique for Camera Calibration。可以从google scholar上搜索下载。

calibrateCamera的使用例子:

        int cols = 10;
	int rows = 7;
	float distance = 30;	//间距30mm

	cv::Size patternSize(cols,rows);
	std::vector<cv::Point2f> corners;
	std::vector<std::vector<cv::Point2f>> cornersVect;
	std::vector<cv::Point3f> worldPoints;
	std::vector<std::vector<cv::Point3f>> worldPointsVect;

	for (int i=0;i<cols;i++)
	{
		for (int j=0;j<rows;j++)
		{
			worldPoints.push_back(cv::Point3f(i*distance,j*distance,0));
		}
	}
	
	bool find=cv::findChessboardCorners(image,patternSize,corners);
	cv::drawChessboardCorners(image,patternSize,corners,find);
	cv::Mat cameraMatirx,distCoeffs;
	std::vector<cv::Mat> rvecs,tvecs,rvecs2,tvecs2;
	if (find)
	{	
		cornersVect.push_back(corners);
		worldPointsVect.push_back(worldPoints);
		cv::calibrateCamera(worldPointsVect,cornersVect,image.size(),cameraMatirx,distCoeffs,rvecs,tvecs);
	}



### OpenCV 中 `calibrateCamera` 函数详解 #### 使用方法与参数说明 `cv.calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs[, rvecs[, tvecs[, flags[, criteria]]]])` - **objectPoints**: 世界坐标系中的三维点位置,通常是一个棋盘格的角点。对于每一张图片,提供一组对应的物体空间坐标。 - **imagePoints**: 图像平面内的二维点位置,即上述对象点投影后的图像坐标。 - **imageSize**: 输入图像大小 (宽度, 高度),用于初始化内参矩阵。 - **cameraMatrix**: 输出相机内参矩阵 \([fx\;0\;cx;\;0\;fy\;cy;\;0\;0\;1]\) ,其中 \(f\) 是焦距,\(c\) 表示主点偏移量。 - **distCoeffs**: 输出畸变系数向量 `(k1,k2,p1,p2[,k3[,k4,k5,k6[,s1,s2,s3,s4[,τx,τy]]]])`. - **rvecs/tvecs**: 可选输出旋和平移矢量数组,描述了从世界坐标到摄像机坐标的换关系[^3]。 其他可选项还包括: - **flags**: 指定细化过程使用的标志位组合;默认情况下采用零切比雪夫多项式模型进行优化。 - **criteria**: 终止条件结构体,定义迭代算法何时停止计算最佳拟合解。 #### 示例代码展示 下面给出一段简单的 Python 代码片段来演示如何利用 OpenCV 进行基本的单目摄像头校正操作: ```python import cv2 as cv import numpy as np # 假设我们已经获取到了一系列棋盘格模式下的 object points 和 image points 数据集 objp = np.zeros((6*9,3), np.float32) objp[:,:2] = np.mgrid[0:9,0:6].T.reshape(-1,2) # 存储所有拍摄的照片中检测出来的 corner pixels 的列表 imgpoints = [] # 2d points in image plane. objpoints = [] # 3d point in real world space. for fname in images: img = cv.imread(fname) gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY) ret,corners = cv.findChessboardCorners(gray,(9,6)) if ret==True: objpoints.append(objp) refined_corners = cv.cornerSubPix( gray, corners, winSize=(11,11), zeroZone=(-1,-1), criteria=( cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001 ) ) imgpoints.append(refined_corners) ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera( objpoints, imgpoints, gray.shape[::-1], None, None ) ``` 这段程序首先准备好了所需的物方和图方特征点集合,接着调用了 `cv.findChessboardCorners()` 来定位棋盘格上的角点,并通过 `cv.cornerSubPix()` 提升其精度至亚像素级别。最后一步则是执行实际的相机标定工作——这正是由 `cv.calibrateCamera()` 完成的任务[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值