十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
pcl中features模块又基于惯性矩和偏心率的描述子,也可以求取点云的AABB和OBB包围盒,在计算的过程中法线一些问题,特此记录。
针对惯性矩和偏心率这两个数据的应用场景还不明确,因此暂时不做讨论,主要讨论求取OBB时的代码。
templatevoid
pcl::MomentOfInertiaEstimation::computeOBB ()
{obb_min_point_.x = std::numeric_limits::max ();
obb_min_point_.y = std::numeric_limits::max ();
obb_min_point_.z = std::numeric_limits::max ();
obb_max_point_.x = std::numeric_limits::min ();
obb_max_point_.y = std::numeric_limits::min ();
obb_max_point_.z = std::numeric_limits::min ();
unsigned int number_of_points = static_cast(indices_->size ());
for (unsigned int i_point = 0; i_point< number_of_points; i_point++)
{float x = (input_->points[(*indices_)[i_point]].x - mean_value_ (0)) * major_axis_ (0) +
(input_->points[(*indices_)[i_point]].y - mean_value_ (1)) * major_axis_ (1) +
(input_->points[(*indices_)[i_point]].z - mean_value_ (2)) * major_axis_ (2);
float y = (input_->points[(*indices_)[i_point]].x - mean_value_ (0)) * middle_axis_ (0) +
(input_->points[(*indices_)[i_point]].y - mean_value_ (1)) * middle_axis_ (1) +
(input_->points[(*indices_)[i_point]].z - mean_value_ (2)) * middle_axis_ (2);
float z = (input_->points[(*indices_)[i_point]].x - mean_value_ (0)) * minor_axis_ (0) +
(input_->points[(*indices_)[i_point]].y - mean_value_ (1)) * minor_axis_ (1) +
(input_->points[(*indices_)[i_point]].z - mean_value_ (2)) * minor_axis_ (2);
if (x<= obb_min_point_.x) obb_min_point_.x = x;
if (y<= obb_min_point_.y) obb_min_point_.y = y;
if (z<= obb_min_point_.z) obb_min_point_.z = z;
if (x >= obb_max_point_.x) obb_max_point_.x = x;
if (y >= obb_max_point_.y) obb_max_point_.y = y;
if (z >= obb_max_point_.z) obb_max_point_.z = z;
}
obb_rotational_matrix_<< major_axis_ (0), middle_axis_ (0), minor_axis_ (0),
major_axis_ (1), middle_axis_ (1), minor_axis_ (1),
major_axis_ (2), middle_axis_ (2), minor_axis_ (2);
Eigen::Vector3f shift (
(obb_max_point_.x + obb_min_point_.x) / 2.0f,
(obb_max_point_.y + obb_min_point_.y) / 2.0f,
(obb_max_point_.z + obb_min_point_.z) / 2.0f);
obb_min_point_.x -= shift (0);
obb_min_point_.y -= shift (1);
obb_min_point_.z -= shift (2);
obb_max_point_.x -= shift (0);
obb_max_point_.y -= shift (1);
obb_max_point_.z -= shift (2);
obb_position_ = mean_value_ + obb_rotational_matrix_ * shift;
}
如上所示,OBB求取的过程就是将点云转换到以中心为坐标原点,PCA计算的三个特征向量为轴方向的局部坐标系中,然后求取相应的AABB包围盒的过程,但是在文中最后一段
Eigen::Vector3f shift (
(obb_max_point_.x + obb_min_point_.x) / 2.0f,
(obb_max_point_.y + obb_min_point_.y) / 2.0f,
(obb_max_point_.z + obb_min_point_.z) / 2.0f);
obb_min_point_.x -= shift (0);
obb_min_point_.y -= shift (1);
obb_min_point_.z -= shift (2);
obb_max_point_.x -= shift (0);
obb_max_point_.y -= shift (1);
obb_max_point_.z -= shift (2);
obb_position_ = mean_value_ + obb_rotational_matrix_ * shift;
第一点:
shift是包围盒的在局部坐标系中的中心坐标,
obb_rotational_matrix_ 是将局部坐标系转为全局坐标的旋转矩阵,平移矩阵就是中心点坐标。
obb_position_ 就是OBB包围盒中心的全局坐标
注意:这里局部坐标系和全局坐标系的转换关系要注意,对点云计算协方差阵,得到的特征向量矩阵是列向量组成的,obb_rotational_matrix_ 就是列向量组成的;
分析:
全局坐标->局部坐标
RP=Pt,此时的R是特征向量作为行向量组成的,这与得到的特征向量矩阵是转置的关系
局部坐标->全局坐标
RtPt=P,此时Rt是R的逆,这才是正确的,但是由于R的转置*R=单位阵,因此使用转置取代求逆操作,也就是说,此时的Rt是特征向量作为列组成的。所以出现obb_position_ = mean_value_ + obb_rotational_matrix_ * shift;
obb_position_ 就是OBB包围盒中心的全局坐标。
第二点:
obb_min_point_.x -= shift (0);
obb_min_point_.y -= shift (1);
obb_min_point_.z -= shift (2);
obb_max_point_.x -= shift (0);
obb_max_point_.y -= shift (1);
obb_max_point_.z -= shift (2);
obb_min_point_和obb_max_point_减去包围盒中心点坐标是什么意思?
经过测试发现,减去中心点坐标之后,包围盒的坐标是存在问题的
如上图所示,两个黑色框中的点就是获取的包围盒的最小点和大点,这里明显可以看出,这两点和显示的OBB包围盒没有关系,是有问题的。
因此绘制正确的OBB包围盒时,采用的是给定包围盒中心的坐标和包围盒的宽度和长度的方法进行绘制。
欢迎留言。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧