Skip to content

Latest commit

 

History

History
411 lines (353 loc) · 12.6 KB

appendix2_2.md

File metadata and controls

411 lines (353 loc) · 12.6 KB

常用函数(2)

以下代码为平时测试所用代码,实现并不严谨,仅供参考!

  • 计算模型分辨率

resolution.h

#include <pcl/io/pcd_io.h>
#include <pcl/search/kdtree.h>

// This function by Tommaso Cavallari and Federico Tombari, taken from the tutorial
// http://pointclouds.org/documentation/tutorials/correspondence_grouping.php
double computeCloudResolution(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr& cloud)
{
	double resolution = 0.0;
	int numberOfPoints = 0;
	int nres;
	std::vector<int> indices(2);
	std::vector<float> squaredDistances(2);
	pcl::search::KdTree<pcl::PointXYZ> tree;
	tree.setInputCloud(cloud);

	for (size_t i = 0; i < cloud->size(); ++i)
	{
		if (!pcl_isfinite((*cloud)[i].x))
			continue;

		// Considering the second neighbor since the first is the point itself.
		nres = tree.nearestKSearch(i, 2, indices, squaredDistances);
		if (nres == 2)
		{
			resolution += sqrt(squaredDistances[1]);
			++numberOfPoints;
		}
	}
	if (numberOfPoints != 0)
		resolution /= numberOfPoints;

	return resolution;
}
  • 计算旋转平移矩阵

getTransformation.h

#ifndef _GET_TRANSFORMATION_
#define _GET_TRANSFORMATION_

#include <pcl/point_types.h>
#include <pcl/common/distances.h>
#include <boost/random.hpp>
#include <pcl/registration/transformation_estimation.h>
#include <pcl/registration/transformation_estimation_3point.h>
#include <pcl/search/pcl_search.h>

int getTransform(pcl::PointCloud<pcl::PointXYZ>::Ptr& src, pcl::PointCloud<pcl::PointXYZ>::Ptr& tar,
	double resolution,
	pcl::Correspondences &correspondences, Eigen::Matrix4f & transform)
{
	int cor_size = correspondences.size();
	if (cor_size < 3)
	{
		pcl::console::print_error("matching less 3");
		return (-1);
	}

	float fitness_score = FLT_MAX;
	boost::mt19937 gen;
	boost::uniform_int<> dist(0, cor_size - 1);
	boost::variate_generator<boost::mt19937&, boost::uniform_int<>> die(gen, dist);
	pcl::registration::TransformationEstimation<pcl::PointXYZ, pcl::PointXYZ, float>::Ptr transformationEstimation(new pcl::registration::TransformationEstimation3Point <pcl::PointXYZ, pcl::PointXYZ>);
	pcl::search::KdTree<pcl::PointXYZ> tree;
	tree.setInputCloud(tar);
	//	float max_inlier_dist_sqr_ = 0.0064;
	for (int i = 0; i < 10000; ++i)
	{
		int cor1, cor2, cor3;
		cor1 = die();
		while (true)
		{
			cor2 = die();
			if (cor2 != cor1)
				break;
		}
		while (true)
		{
			cor3 = die();
			if (cor3 != cor1 && cor3 != cor2)
				break;
		}

		pcl::Correspondences correspondences_temp;
		correspondences_temp.push_back(correspondences[cor1]);
		correspondences_temp.push_back(correspondences[cor2]);
		correspondences_temp.push_back(correspondences[cor3]);
		Eigen::Matrix4f transform_temp;
		transformationEstimation->estimateRigidTransformation(*src, *tar, correspondences_temp, transform_temp);

		// 先看三个对应点变换后是否匹配
		pcl::PointCloud<pcl::PointXYZ> src_temp;
		pcl::PointCloud<pcl::PointXYZ> tar_temp;
		src_temp.push_back(src->points[correspondences[cor1].index_query]);
		tar_temp.push_back(tar->points[correspondences[cor1].index_match]);
		src_temp.push_back(src->points[correspondences[cor2].index_query]);
		tar_temp.push_back(tar->points[correspondences[cor2].index_match]);
		src_temp.push_back(src->points[correspondences[cor3].index_query]);
		tar_temp.push_back(tar->points[correspondences[cor3].index_match]);

		pcl::PointCloud<pcl::PointXYZ> src_transformed;
		pcl::transformPointCloud(src_temp, src_transformed, transform_temp);
		float mse = 0.f;
		for (int k = 0; k < 3; ++k)
		{
			mse += pcl::squaredEuclideanDistance(src_transformed.points[k], tar_temp.points[k]);
		}
		mse /= 3;
		if (mse > 2* resolution) 
			continue;

		// 整体变换、得出评价
		pcl::PointCloud<pcl::PointXYZ> match_transformed;
		pcl::transformPointCloud(*src, match_transformed, transform_temp);

		std::vector <int> ids;
		std::vector <float> dists_sqr;
		float score = 0.f;
		for (int k = 0; k < match_transformed.size(); ++k)
		{
			tree.nearestKSearch(src->points[k], 1, ids, dists_sqr);
			score += dists_sqr[0];
			//			score += (dists_sqr[0] < max_inlier_dist_sqr_ ? dists_sqr[0] : max_inlier_dist_sqr_);
		}
		score /= match_transformed.size();
		//		score /= (max_inlier_dist_sqr_ * match_transformed.size());

		if (score < fitness_score)
		{
			fitness_score = score;
			transform = transform_temp;
		}

	}
	return 0;
}

#endif
  • 旋转平移矩阵评估

参考论文: Mian A, Bennamoun M, Owens R. A novel representation and feature matching algorithm for automatic pairwise registration of range images[J]. International Journal of Computer Vision, 66(1), 19–40.

evaluation.h

#include <iostream>
#include <pcl/common/transforms.h>
#include <pcl/registration/transformation_estimation_svd.h>

using namespace std;

//compute ideal ratation and translation matrix
Eigen::Matrix4f createIdealTransformationMatrix(float tx, float ty, float tz, float rx, float ry, float rz)
{
	////rotating and translating point cloud
	////m and m1 are both the unit matrixes
	Eigen::Matrix4f m = Eigen::Matrix4f::Identity();
	Eigen::Matrix4f m1 = Eigen::Matrix4f::Identity();
	//tx,ty,tz are translation values of x ,y and z axis
	m1(0, 3) = tx;
	m1(1, 3) = ty;
	m1(2, 3) = tz;
	//cout << "m1" << endl << m1 << endl;
	m = m * m1;   //apply the translation
	//cout << "m" << endl << m << endl;
	//rotating the point cloud along the x axis
	m1 = Eigen::Matrix4f::Identity();
	rx = rx / 180.0 * M_PI;
	m1(1, 1) = cos(rx);
	m1(1, 2) = -sin(rx);
	m1(2, 1) = sin(rx);
	m1(2, 2) = cos(rx);
	//cout << "m1" << endl << m1 << endl;
	m = m * m1;   //apply the rotation along x axis
	//cout << "m" << endl << m << endl;
	//rotating the point cloud along the y axis
	m1 = Eigen::Matrix4f::Identity();
	ry = ry / 180.0 * M_PI;
	m1(0, 0) = cos(ry);
	m1(0, 2) = sin(ry);
	m1(2, 0) = -sin(ry);
	m1(2, 2) = cos(ry);
	//cout << "m1" << endl << m1 << endl;
	m = m * m1;   //apply the rotation along y axis
	//cout << "m" << endl << m << endl;
	//rotating the point cloud along the z axis
	m1 = Eigen::Matrix4f::Identity();
	rz = rz / 180.0 * M_PI;
	m1(0, 0) = cos(rz);
	m1(0, 1) = -sin(rz);
	m1(1, 0) = sin(rz);
	m1(1, 1) = cos(rz);
	//cout << "m1" << endl << m1 << endl;
	m = m * m1;   //apply the rotation along y axis
	//cout << "m" << endl << m << endl;

	return m;
}

//compute the error of rotation matrix and translation matrix
void computeMatrixError(float rotation, float translation, float & rotationError, float &translationError, Eigen::Matrix4f &realRtMatrix)
{
	Eigen::Matrix4f idealMatrix = Eigen::Matrix4f::Identity();
	idealMatrix = createIdealTransformationMatrix(translation, translation, translation, rotation, rotation, rotation);
	//cout << "idealMatrix:"<<endl << idealMatrix << endl;


	Eigen::Matrix3f idealRotationMatrix = Eigen::Matrix3f::Identity();
	Eigen::Vector3f iealTranslationVector = Eigen::Vector3f(0, 0, 0);

	//getting ideal rotation matrix
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			idealRotationMatrix(i, j) = idealMatrix(i, j);
		}
	}

	//getting ideal translation matrix
	for (int i = 0; i < 3; i++)
	{
		iealTranslationVector(i) = idealMatrix(i, 3);
	}
	cout << "ideal Rotation matrix:" << endl << idealRotationMatrix << endl;
	cout << "ideal Translatin vector:" << endl << iealTranslationVector << endl;

	cout << "real Matrix:" << endl << realRtMatrix << endl;

	Eigen::Matrix3f realRotationMatrix = Eigen::Matrix3f::Identity();
	Eigen::Vector3f realTranslationVector = Eigen::Vector3f(0, 0, 0);

	//getting ideal rotation matrix
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			realRotationMatrix(i, j) = realRtMatrix(i, j);
		}
	}
	//getting real translation matrix
	for (int i = 0; i < 3; i++)
	{
		realTranslationVector(i) = realRtMatrix(i, 3);
	}

	cout << "real Rotation matrix:" << endl << realRotationMatrix << endl;
	cout << "real Translatin vector:" << endl << realTranslationVector << endl;

	//compute rotation error
	Eigen::Matrix3f m = idealRotationMatrix * realRotationMatrix.inverse();
	Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> es;
	es.compute(m);
	float tr = es.eigenvalues()(0) + es.eigenvalues()(1) + es.eigenvalues()(2);
	if (tr > 3) tr = 3;
	if (tr < -3) tr = -3;
	rotationError = acos((tr - 1) / 2) * 180.0 / M_PI;

	//compute translation error
	translationError = (realTranslationVector - iealTranslationVector).norm();
}
  • 剔除边缘点

boundary_points.h

#ifndef  _BOUNDARY_POINTS_
#define _BOUNDARY_POINTS_

#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d.h>
#include <pcl/features/boundary.h>

void computeBoundaryPoints(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud,
	double resolution,
	pcl::PointCloud<pcl::PointXYZ>::Ptr &boundary_cloud)
{
	// compute normals; 
	pcl::search::Search<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
	pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_est;
	normal_est.setSearchMethod(tree);
	normal_est.setInputCloud(cloud);
	normal_est.setKSearch(50);
	normal_est.compute(*normals);
	//normal_est.setViewPoint(0,0,0); 


	//calculate boundary; 
	pcl::PointCloud<pcl::Boundary> boundary;
	pcl::BoundaryEstimation<pcl::PointXYZ, pcl::Normal, pcl::Boundary> boundary_est;
	boundary_est.setInputCloud(cloud);
	boundary_est.setInputNormals(normals);
	boundary_est.setRadiusSearch(5 * resolution);
	boundary_est.setAngleThreshold(M_PI / 4);
	boundary_est.setSearchMethod(pcl::search::KdTree<pcl::PointXYZ>::Ptr(new pcl::search::KdTree<pcl::PointXYZ>));
	boundary_est.compute(boundary);

	for (size_t i = 0; i < cloud->points.size(); ++i)
	{
		if (boundary.points[i].boundary_point == 1)
			boundary_cloud->push_back(cloud->points[i]);
	}
	std::cout << "boundary size is " << boundary_cloud->points.size() << std::endl;
}

void eliminateBoundary(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud,
	pcl::PointCloud<pcl::PointXYZ>::Ptr &keys,
	double resolution, int rate)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr boundary_cloud(new pcl::PointCloud<pcl::PointXYZ>);
	computeBoundaryPoints(cloud, resolution, boundary_cloud);
	pcl::search::KdTree<pcl::PointXYZ> kdtree;
	kdtree.setInputCloud(boundary_cloud);

	std::vector<int> indices;
	std::vector<float> distances;
	float diff = rate * rate *resolution*resolution;
	pcl::PointCloud<pcl::PointXYZ>::Ptr keys_result(new pcl::PointCloud<pcl::PointXYZ>);
	for (size_t i = 0; i < keys->points.size(); ++i)
	{
		kdtree.nearestKSearch(keys->points[i], 1, indices, distances);
		if (distances[0] > diff)
			keys_result->push_back(keys->points[i]);
	}

	std::cout << "remove " << keys->points.size() - keys_result->points.size() << "points" << std::endl;

	keys->clear();
	keys = keys_result;
}

#endif // ! _BOUNDARY_POINTS_
  • 将点旋转平移

tranform.h

#pragma once
#include <pcl/common/transforms.h>

void MyTransformationPoint(pcl::PointXYZ &pt_in, pcl::PointXYZ &pt_out, float tx, float ty, float tz, float rx, float ry, float rz)
{
	////rotating and translating point cloud
	////m and m1 are both the unit matrixes
	Eigen::Matrix4f m = Eigen::Matrix4f::Identity();
	Eigen::Matrix4f m1 = Eigen::Matrix4f::Identity();
	//tx,ty,tz are translation values of x ,y and z axis
	m1(0, 3) = tx;
	m1(1, 3) = ty;
	m1(2, 3) = tz;
	//cout << "m1" << endl << m1 << endl;
	m = m * m1;   //apply the translation
	//cout << "m" << endl << m << endl;
	//rotating the point cloud along the x axis
	m1 = Eigen::Matrix4f::Identity();
	rx = rx / 180.0 * M_PI;
	m1(1, 1) = cos(rx);
	m1(1, 2) = -sin(rx);
	m1(2, 1) = sin(rx);
	m1(2, 2) = cos(rx);
	//cout << "m1" << endl << m1 << endl;
	m = m * m1;   //apply the rotation along x axis
	//cout << "m" << endl << m << endl;
	//rotating the point cloud along the y axis
	m1 = Eigen::Matrix4f::Identity();
	ry = ry / 180.0 * M_PI;
	m1(0, 0) = cos(ry);
	m1(0, 2) = sin(ry);
	m1(2, 0) = -sin(ry);
	m1(2, 2) = cos(ry);
	//cout << "m1" << endl << m1 << endl;
	m = m * m1;   //apply the rotation along y axis
	//cout << "m" << endl << m << endl;
	//rotating the point cloud along the z axis
	m1 = Eigen::Matrix4f::Identity();
	rz = rz / 180.0 * M_PI;
	m1(0, 0) = cos(rz);
	m1(0, 1) = -sin(rz);
	m1(1, 0) = sin(rz);
	m1(1, 1) = cos(rz);
	//cout << "m1" << endl << m1 << endl;
	m = m * m1;   //apply the rotation along y axis
	//cout << "m" << endl << m << endl;

	//pcl::transformPointCloud(src, dst, m);
	Eigen::Matrix<float, 3, 1> pt(pt_in.x, pt_in.y, pt_in.z);
	pt_out.x = static_cast<float> (m(0, 0) * pt.coeffRef(0) + m(0, 1) * pt.coeffRef(1) + m(0, 2) * pt.coeffRef(2) + m(0, 3));
	pt_out.y = static_cast<float> (m(1, 0) * pt.coeffRef(0) + m(1, 1) * pt.coeffRef(1) + m(1, 2) * pt.coeffRef(2) + m(1, 3));
	pt_out.z = static_cast<float> (m(2, 0) * pt.coeffRef(0) + m(2, 1) * pt.coeffRef(1) + m(2, 2) * pt.coeffRef(2) + m(2, 3));
}