摄像机标定

单目标定

过程

  1. 读取每幅图像(可以只有1张),从中提取角点,然后对角点进行亚像素精确化。
  2. 摄像机单目标定
  3. 矫正图片

用到的数据

  • Size boardSize: 棋盘格的大小,为内角点在列和行的数量
  • vector<vector<Point2f>> cornersOfAllImgs:
    所有图片的角点, 每张图片的角点是棋盘格内角点在图片上的对应像素点
  • Size squareSize = Size(60,60): 每个棋盘格的实际大小,单位为mm
  • vector<vector<Point3f>> objRealPoint: 棋盘角点的实际坐标(世界坐标系下的坐标,以左上方的角点为(0,0)点)

要计算的数据

  • Mat cameraMat = Mat(3,3,CV_32FC1.Scalar::all(0)): 内参数矩阵
  • Mat distcoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0)): 畸变系数
  • vector<Mat> tvecsMat: 所有图片的旋转向量
  • vector<Mat> rvecsMat: 所有图片的平移向量
    其中,cameraMat 和 distcoeffs用于矫正图片

代码

if (findChessboardCorners(img, 
			boardSize, 
			corners)
			== 0) 
		{
			//若找不到角点
			cout << filename << "找不到角点" << endl;
			exit(1);
		}
		else {
			Mat imgGray;
			cvtColor(img, imgGray, CV_RGB2GRAY);

			/*亚像素精确化
			corners: 初始的角点坐标向量,同时作为亚像素坐标的输出
			Size(5,5): 搜索窗口大小
			(-1,-1): 表示没有死区
			TermCriteria: 角点迭代过程的终止条件,可以为迭代次数和角点精度的组合
			*/
			cornerSubPix(
				imgGray, 
				corners, Size(5, 5), 
				Size(-1, -1), 
				TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));

			cornersOfAllImgs.push_back(corners);

			/*再图像上画角点位置*/
			drawChessboardCorners(imgGray, 
				boardSize, 
				corners, 
				false);

			imshow("Camera Calibration", imgGray);
			waitKey(1);
		}
/*开始标定
	输入参数:
		cornerPoints: 世界坐标系中角点的三维坐标
		cornersOfAllImgs: 每一个内角点对应的图像亚像素坐标点
		imgSize: 图像尺寸
	输出参数:
		cameraMat: 内参数矩阵
		discoeffs: 畸变系数
		rvecsMat: 旋转向量
		tvecsMat: 位移向量
	附加参数:
		0: 标定时选用的算法
	*/
	calibrateCamera(
		cornerPoints, 
		cornersOfAllImgs, 
		imgSize, 
		cameraMat, 
		distcoeffs, 
		rvecsMat, 
		tvecsMat, 
		0);
for (int i = 0; i < imgCount; ++i) {
		//用initUndistortRectifyMap函数和remap函数来矫正函数
		initUndistortRectifyMap(cameraMat, distcoeffs, R, cameraMat, imgSize, CV_32FC1, mapx, mapy);
		Mat imgSrc = imread(filenames[i]);
		Mat imgDst = imgSrc.clone();
		remap(imgSrc, imgDst, mapx, mapy, INTER_LINEAR);

		//不使用转换矩阵的方式,使用undistort函数实现
		//undistort(imgSrc, imgDst, cameraMat, distcoeffs);

		/*保存矫正后的图片*/
		strStm.clear();
		undistortImgFilename.clear();
		strStm << "img\\";
		strStm << i + 1;
		strStm >> undistortImgFilename;
		undistortImgFilename += "_d.jpg";
		imwrite(undistortImgFilename, imgDst);
		
	}

双目标定

过程

  1. 先用单目标定得到左右相机的内参数矩阵和畸变系数
  2. 双目标定摄像头
  3. 矫正图片

用到的数据

  • Size mgSize: 摄象头分辨率
  • Size boardSize: 内角点在列和行上的数量
  • squareSize: 棋盘格大小
  • vector<vector<Point2f>> cornersOfAllImagesL
    vector<vector<Point2f>> cornersOfAllImagesR
    左右相机的所有图片的角点
  • vector<Point2f> objRealSize: 内角点的实际坐标(世界坐标系)
  • 左右相机的内参数矩阵和畸变系数

要计算的数据

  • Mat R, T, E, F: 分别为R旋转矢量 T平移矢量 E本征矩阵 F基础矩阵
  • Mat Rl, Rr, Pl, Pr, Q: 校正旋转矩阵R,投影矩阵P,重投影矩阵Q

代码

 //标定摄像头
    double rms = stereoCalibrate(objRealPoint, imagePointL, imagePointR,
        cameraMatL, distcoeffL,
        cameraMatR, distcoeffR,
        Size(imageWidth, imageHeight), R, T, E, F, CALIB_USE_INTRINSIC_GUESS,
        TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, 1e-5));

    cout << "Stereo Calibration done with RMS error = " << rms << endl;

    stereoRectify(cameraMatL, distcoeffL, cameraMatR, distcoeffR, imageSize, R, T, Rl, 
        Rr, Pl, Pr, Q, CALIB_ZERO_DISPARITY, -1, imageSize, &validROIL,&validROIR);
//摄像机校正映射, 比单目的多了Rl,Pl和Rr,Pr
    initUndistortRectifyMap(cameraMatL, distcoeffL, Rl, Pl, imgSize, CV_32FC1, mapLx, mapLy);
    initUndistortRectifyMap(cameraMatR, distcoeffR, Rr, Pr, imgSize, CV_32FC1, mapRx, mapRy);

    Mat rectifyImageL, rectifyImageR;
    cvtColor(grayImageL, rectifyImageL, CV_GRAY2BGR);
    cvtColor(grayImageR, rectifyImageR, CV_GRAY2BGR);
    
    //经过remap之后,左右相机的图像已经共面并且行对准了
    Mat rectifyImageL2, rectifyImageR2;
    remap(rectifyImageL, rectifyImageL2, mapLx, mapLy, INTER_LINEAR);
    remap(rectifyImageR, rectifyImageR2, mapRx, mapRy, INTER_LINEAR);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值