视觉SLAM前端(间接法)—— 特殊数据结构与用法

目录
  • Mat 类
  • Point2d/Point3d 类
  • Vector2d/Vector3d 类
  • Sophus::SE3d/SO3d 类
Mat类

  Mat类是opencv中图像存储矩阵,常常与cv::imread()函数一起使用,注意的是,Mat矩阵不能与Eigen库中的矩阵进行任何数学运算,需要时必须进行转换。Mat类也存放一些固定的参数,如相机内参等等,对Mat类一个最重要操作便是访问矩阵内的元素。

1.利用Mat.ptr访问

 cv::Mat image = cv::Mat(400, 600, CV_8UC1); 
 //创建一个Mat类的image矩阵
double d=image.ptr<unsigned short>(int(y))[int(x)];
//访问(x,y)处的元素

2.利用Mat.at访问

 cv::Mat image = cv::Mat(400, 600, CV_8UC1); 
 //创建一个Mat类的image矩阵
double d=image.at<double>(y, x);
//访问(x,y)处的元素

注意:(x,y)是图像的像素坐标系,与一般的坐标系原点不同,在图像的左上角。对于矩阵便是:第x行,第y列的元素

3.Mat矩阵的手动输入元素

cv::Mat y=(Mat_<double>(1,3)<<3,2,1);
//定义一个1×3的矩阵,并且输入数据
Point2d/Point3d 类

   cv::Point2d; cv::Point3d是opencv中的一种存储二维/三维点的一种数据结构,常常用与容器配合使用,用于存储图像的特征点等等。

1.Keypoint转换为Point2d类

for(Dmatch m:matches){
vector<Point2d> pts_2=
(keypoints[matches[i].queryIdx].pt)
}

keypoints[i].pt返回的是一个point类

2.Point类访问元

vector<Point2d> pts_2=
(keypoints[matches[i].queryIdx].pt)
double x= pts_2.x;
double y= pts_2.y;

3.Point类的数学运算

  Point类可之间进行加减运算,乘除运算转换为cv::Vec3d类。

//求解特征点的质心
Point3f p1, p2;     //质心坐标
	int N = pts1.size(); 
	 //pts1为point3f类型
	for (int i = 0; i < N; i++) {
		p1 += pts1[i]; //加法运算
		p2 += pts2[i];
	}
	p1 = Point3f(Vec3f(p1) / N);
	p2 = Point3f(Vec3f(p2) / N);
	//向量的乘法运算要转换为Vec3f类型
Vector2d/Vector3d 类

  Vector2d/Vector3d是Eigen库中的向量,也常常用于图像相关的运算,其灵活性比cv中的point类要高,更加"数学化"。
1.运算性质
  Vector2d/3本质是Eigen库的矩阵,实际运算过程严格按照矩阵运算即可。常常也用于存储图像的特征向量,特征点等,一般与容器配合使用。

2.赋值与遍历(手写输入数据)

Eigen::Vector3d xyz;
xyz <<
 1 ,
 2 ,
 3;
Eigen::Vector3d t(1,2,3);

//创建一个向量,两种方式都可以,第一种不能之间赋值
double x =xyz(0 ,0);
double y =xyz(1 ,0);
double z =xyz(2 ,0);
//访问相应的元素

注意:手写赋值与Mat类不同,遍历是必须严格按照矩阵的行与列进行遍历。

3.Eigen与Point类的互相转换

//Point to eigen
//若pts为定义好的 vector<Point3d> pts_3d l类型并且已经赋值	
	vector<Eigen::Vector3d> pts3_eigen;

	for (int i = 0; i < pts_3d.size(); i++)
	{
		pts3_eigen.push_back(
		Eigen::Vector3d(pts_3d[i].x, pts_3d[i].y, pts_3d[i].z)
		);
	}
//eigen to Point
vector<cv::Point3d> point3;
	for (int i = 0; i < pts3_eigen.size(); i++)
	{
		point3.push_back(
		cv::Point3d(pts3_eigen[i](0, 0), pts3_eigen[i](1, 0), pts3_eigen[i](2, 0)));
	}
Sophus::SE3d/SO3d类

  李群李代数最直接的用法就是表达为位姿,如何对特征点进行变换,值得注意的是,此时的特征点必须是Eigen的Vector类型。
1.变换

	Eigen::Matrix3d R = Eigen::AngleAxisd(M_PI / 2, Eigen::Vector3d(0, 1, 0)).toRotationMatrix();
	//沿着y轴旋转90°

	Eigen::Vector3d t(1, 0, 0);
	//沿着x轴平移一个单位

	Sophus::SE3d T(R, t);
	Eigen::Vector3d v(0, 1, 0);
	Eigen::Vector3d v_after = T * v;
	cout << "变换前的向量:\n" << v << endl;
	cout << "变换后的向量:\n" << v_after<< endl;

注:
1.以李群表示的位姿对某个Vector点变换后的数据类型还是Vector。
2.凡是在图像层次的运算都用cv里面的结构,凡是涉及其他的数学运算都用Eigen里面的结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值