C++/opencv 直接线性变换 相机标定

头文件

#pragma once
#include <iostream>
#include <math.h>
#include <vector>

#include <opencv2\opencv.hpp>

#include <Eigen/core>
#include <eigen/dense>

using namespace std;
using namespace Eigen;

cpp文件

#include "LinerCalibrate.h"


//计算旋转矩阵
MatrixXd calRotationMatrix(int Ax, int Ay, int Az)
{
	MatrixXd  R(3, 3);
	R(0, 0) = cos(Ay) * cos(Az) - sin(Ay)*sin(Ax)*sin(Az);
	R(0, 1) = cos(Ax)*sin(Az);
	R(0, 2) = sin(Ay)*cos(Az) + cos(Ay)*sin(Ax)*sin(Az);
	R(1, 0) = -cos(Ay)*sin(Az) - sin(Ay)*sin(Ax)*cos(Az);
	R(1, 1) = cos(Ax)*cos(Az);
	R(1, 2) = -sin(Ay)*sin(Az) + cos(Ay)*sin(Ax)*cos(Az);
	R(2, 0) = -sin(Ay)*cos(Ax);
	R(2, 1) = -sin(Ax);
	R(2, 2) = cos(Ay)*cos(Ax);
	return R;
}
//求解线性参数
MatrixXd solve_liner_parameters(MatrixXd &Points3D, MatrixXd &Points2D)
{
	MatrixXd U = Points2D.transpose();
	U.resize(12, 1);
	MatrixXd K(12, 11);
	for (int i = 0, j = 0; i < K.rows(); i++)
	{

		if (i % 2 == 0)
		{
			K(i, 0) = Points3D(j, 0);
			K(i, 1) = Points3D(j, 1);
			K(i, 2) = Points3D(j, 2);
			K(i, 3) = 1;

			K(i, 4) = 0;
			K(i, 5) = 0;
			K(i, 6) = 0;
			K(i, 7) = 0;

			K(i, 8) = (-1) *  Points3D(j, 0) * U(i, 0);
			K(i, 9) = (-1) *  Points3D(j, 1) * U(i, 0);
			K(i, 10) = (-1) *  Points3D(j, 2) * U(i, 0);

		}
		else if (i % 2 == 1)
		{
			K(i, 0) = 0;
			K(i, 1) = 0;
			K(i, 2) = 0;
			K(i, 3) = 0;

			K(i, 4) = Points3D(j, 0);
			K(i, 5) = Points3D(j, 1);
			K(i, 6) = Points3D(j, 2);
			K(i, 7) = 1;

			K(i, 8) = (-1) *  Points3D(j, 0) * U(i, 0);
			K(i, 9) = (-1) *  Points3D(j, 1) * U(i, 0);
			K(i, 10) = (-1) *  Points3D(j, 2) * U(i, 0);
			j++;
		}
	}

	//cout << K << endl;
	MatrixXd K_trans(11, 12);
	K_trans = K.transpose();
	MatrixXd Ktrans_k(11, 11);
	Ktrans_k = K_trans * K;
	MatrixXd Ktrans_KInverse(11, 11);
	Ktrans_KInverse = Ktrans_k.inverse();
	//cout << Ktrans_KInverse << endl;
	MatrixXd S(11, 1);
	S = Ktrans_KInverse * K_trans * U;
	//cout << S << endl;
	return S;
}



//求解相机内外参
void solve_exter_matrix(MatrixXd & S, MatrixXd & InterMatrix, MatrixXd & ExternalMatrix)
{
	MatrixXd S1(1, 3);
	S1 << S(0, 0), S(1, 0), S(2, 0);
	MatrixXd S2(1, 3);
	S2 << S(4, 0), S(5, 0), S(6, 0);
	MatrixXd S3(1, 3);
	S3 << S(8, 0), S(9, 0), S(10, 0);
	double s3 = sqrt(pow(S(8, 0), 2) + pow(S(9, 0), 2) + pow(S(10, 0), 2));
	double m34 = 1.0 / s3;
	cout << "m34的值为" << m34 << endl;
	MatrixXd M(11, 1);
	M = S / m34;
	double u0 = m34 * m34 * (S1(0, 0) * S3(0, 0) + S1(0, 1) * S3(0, 1) + S1(0, 2) * S3(0, 2));
	double v0 = m34 * m34 * (S2(0, 0) * S3(0, 0) + S2(0, 1) * S3(0, 1) + S2(0, 2) * S3(0, 2));
	double fu = m34 * m34 * sqrt(pow((S1(1) * S3(2) - S1(2) * S3(1)), 2)
		+ pow((S1(2) * S3(0) - S1(0) * S3(2)), 2)
		+ pow((S1(0) * S3(1) - S1(1) * S3(0)), 2));

	double fv = m34 * m34 * sqrt(pow((S2(1) * S3(2) - S2(2) * S3(1)), 2)
		+ pow((S2(2) * S3(0) - S2(0) * S3(2)), 2)
		+ pow((S2(0) * S3(1) - S2(1) * S3(0)), 2));

	MatrixXd R1(1, 3);
	R1 = (S1 - u0 * S3) * m34 / fu;
	MatrixXd R2(1, 3);
	R2 = (S2 - v0 * S3) * m34 / fv;
	MatrixXd R3(1, 3);
	R3 = m34 * S3;
	double tz = m34;
	double tx = (S(3, 0) - u0) * m34 / fu;
	double ty = (S(7, 0) - v0) * m34 / fv;
	
	InterMatrix << fu, 0, u0, 0,
		0, fv, v0, 0,
		0, 0, 1, 0;
	cout << "相机的内参矩阵为:" << endl << InterMatrix << endl;
	
	ExternalMatrix << R1(0), R1(1), R1(2), tx,
		R2(0), R2(1), R2(2), ty,
		R3(0), R3(1), R3(2), tz,
		0, 0, 0, 1;
	cout << "相机的外参矩阵为:" << endl << ExternalMatrix << endl;
}

//计算投影矩阵
MatrixXd cal_project_matrix(MatrixXd & InterMatrix, MatrixXd & ExternalMatrix)
{
	MatrixXd ProjectMatrix = InterMatrix * ExternalMatrix;
	cout << "投影矩阵" << ProjectMatrix << endl;
	return ProjectMatrix;
}

//计算理想像点
MatrixXd cal_reproject_points(MatrixXd & Points3D, MatrixXd & ProjectMatrix)
{
	MatrixXd CalPoint_2D(3, 6);
	//计算重投影坐标
	for (int i = 0; i < Points3D.rows(); i++)
	{
		MatrixXd Xw(4, 1);
		Xw << Points3D(i, 0),
			Points3D(i, 1),
			Points3D(i, 2),
			1;
		CalPoint_2D.col(i) = ProjectMatrix * Xw;
	}

	for (int i = 0; i < CalPoint_2D.cols(); i++)
	{
		double zc = CalPoint_2D.col(i)(2);
		CalPoint_2D.col(i) = CalPoint_2D.col(i) / zc;
	}
	MatrixXd IdealPoint_2D = (CalPoint_2D.transpose()).block<6, 2>(0, 0);
	cout << "重投影坐标点为:" << endl << IdealPoint_2D << endl;
	return IdealPoint_2D;
}

//计算理想像点和实际像点偏差
MatrixXd cal_deviation(MatrixXd & Points2D, MatrixXd &IdealPoint_2D)
{
	MatrixXd point_deviation = Points2D - IdealPoint_2D;
	cout << "理想点和实际点之间的偏差为:" << endl << point_deviation << endl;
	return point_deviation;
}


//求解像差系数
void solve_aberration_coefficients(MatrixXd & Points2D, MatrixXd & IdealPoint_2D, MatrixXd  & InterMatrix, MatrixXd & Coefficient, MatrixXd & D)
{
	MatrixXd  Error = Points2D - IdealPoint_2D;
	//cout << "投影偏差:" << endl << Error << endl;
	double u0 = InterMatrix(0, 2);
	double v0 = InterMatrix(1, 2);
	double fu = InterMatrix(0, 0);
	double fv = InterMatrix(1, 1);
	
	for (int i = 0, j = 0; i < 12; i++)
	{
		double xd = (IdealPoint_2D(j, 0) - u0) / fu;
		double yd = (IdealPoint_2D(j, 1) - v0) / fv;
		if (i % 2 == 0)
		{
			D(i, 0) = xd * (xd * xd + yd * yd);
			D(i, 1) = xd * xd + yd * yd;
			D(i, 2) = 0;
			D(i, 3) = xd * xd;
			D(i, 4) = xd * yd;
		}
		else
		{
			D(i, 0) = yd * (xd * xd + yd * yd);
			D(i, 1) = 0;
			D(i, 2) = xd * xd + yd * yd;
			D(i, 3) = xd * yd;
			D(i, 4) = yd * yd;
			j++;
		}
	}
	MatrixXd projectError = Error.transpose();
	projectError.resize(12, 1);
	MatrixXd D_trans(5, 12);
	D_trans = D.transpose();
	MatrixXd Dtrans_D(5, 5);
	Dtrans_D = D_trans * D;
	MatrixXd Dtrans_DInverse(5, 5);
	Dtrans_DInverse = Dtrans_D.inverse();
	Coefficient = Dtrans_DInverse * D_trans * projectError;
	cout << "像差系数:" << endl << Coefficient << endl;	
}

//修正像差
MatrixXd corrected_aberration(MatrixXd & Points2D, MatrixXd & Coefficient, MatrixXd & D)
{
	MatrixXd  calError = D * Coefficient;
	//cout << "计算的像差:" << endl << calError << endl;

	MatrixXd U = Points2D.transpose();
	U.resize(12, 1);
	MatrixXd correctPoint_2D = U - calError;
	correctPoint_2D.resize(2, 6);
	MatrixXd correct_Point_2D = correctPoint_2D.transpose();

	cout << "修正后的像点:" << endl << correct_Point_2D << endl;
	return correct_Point_2D;
}



int main()
{
	//数据仿真
	//定义像机内参
	double fx = 718.856;
	double fy = 718.856;
	double cx = 607.1928;
	double cy = 185.2157;
	MatrixXd intrinsicMatrix(3, 4);
	intrinsicMatrix << fx, 0, cx, 0,
		0, fy, cy, 0,
		0, 0, 1, 0;
	
	//定义平移矩阵	
	MatrixXd TransMatrix(3, 1);
	TransMatrix << 2, 3, 15;
	MatrixXd TransRight(3, 1);
	TransRight << 3, 4, 25;
	//计算旋转矩阵
	MatrixXd RotationMattix = calRotationMatrix(4, 3, 25);
	
	//得到像机外参
	MatrixXd LExternalMatrix(4, 4);
	LExternalMatrix << RotationMattix, TransMatrix,
		0, 0, 0, 1;

	//获取3D点坐标
	MatrixXd Points3D(6, 3);
	Points3D << 15.0805898011000, - 240.498051047000, -106.236122549000,
		30.6387916207000, - 239.755541086000, - 101.758614182000,
		-29.3889399618000, - 235.353872180000, - 103.475697339000,
		-13.9720272273000, - 232.428580523000, - 108.193732798000,
		-40.6951531768000, - 127.180248499000, - 93.5706794262000,
		-13.8775017112000, - 204.104274511000, - 95.9943234921000;
	cout << "空间点坐标" << endl << Points3D << endl;
	//计算投影矩阵
	MatrixXd LProjectMatrix(3, 4);
	LProjectMatrix = cal_project_matrix(intrinsicMatrix, LExternalMatrix);
	//计算对应的图像点坐标
	MatrixXd Points2D(6, 2);
	Points2D = cal_reproject_points(Points3D, LProjectMatrix);
	cout << "图像点坐标" << endl << Points2D << endl;
	//对应图像点坐标
	//MatrixXd Points2D(6, 2);
	//Points2D << 785,	759,
	//			855,	781,
	//			466,	781,
	//			588,	798,
	//			368,	1608,
	//			564,	1017;
	//
	
	
	double max_deviation = 10;
	int i = 0;//迭代次数
	while (max_deviation > 10e-8) //
	{

		//求解线性参数
		MatrixXd S = solve_liner_parameters(Points3D, Points2D);

		//求解相机内外参
		MatrixXd InterMatrix(3, 4);
		MatrixXd ExternalMatrix(4, 4);
		
		solve_exter_matrix(S, InterMatrix, ExternalMatrix);
		//计算投影矩阵
		MatrixXd ProjectMatrix(3, 4);
		ProjectMatrix = cal_project_matrix(InterMatrix, ExternalMatrix);

		//计算理想像点
		MatrixXd IdealPoint_2D(6, 2);
		IdealPoint_2D = cal_reproject_points(Points3D, ProjectMatrix);
		//计算理想像点和实际像点偏差
		MatrixXd point_deviation = cal_deviation(Points2D, IdealPoint_2D);
		max_deviation = point_deviation.maxCoeff();
		//cout << "最大的偏差:" << endl << max_deviation << endl;
		//求解像差系数
		MatrixXd Coefficient(5, 1);
		MatrixXd D(12, 5);
		solve_aberration_coefficients(Points2D, IdealPoint_2D, InterMatrix, Coefficient, D);


		//修正像点
		MatrixXd correct_Point_2D = corrected_aberration(Points2D, Coefficient, D);

		//作为下一步理想像点
		Points2D = correct_Point_2D;

		i++;

	}


	cout << "迭代次数:" << i << endl;
	system("pause");
	return 0;

}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值