-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add robust covariance matrix calculation to normal_3d.h #3169
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -390,6 +390,67 @@ namespace pcl | |||
} | ||||
} | ||||
|
||||
/** \brief Compute the normalized 3x3 covariance matrix and the centroid of a given set of points in a single loop. | ||||
* Normalized means that every entry has been divided by the number of valid entries in the point cloud. | ||||
* For small number of points, or if you want explicitly the sample-variance, scale the covariance matrix | ||||
* with n / (n-1), where n is the number of points used to calculate the covariance matrix and is returned by this function. | ||||
* Prior to the covariance matrix calculation the center point of the neighborhood is subtracted from all points. | ||||
* This is done to avoid numerical issues due to loss of significance. | ||||
* \note This method does not check whether the cloud is dense because it expects finite neighborhoods. | ||||
* \param[in] cloud the input point cloud | ||||
* \param[in] indices subset of points given by their indices | ||||
* \param[out] covariance_matrix the resultant 3x3 covariance matrix | ||||
* \param[out] centroid the centroid of the set of points in the cloud | ||||
* \return size of the input cloud. | ||||
* \ingroup common | ||||
*/ | ||||
inline unsigned int | ||||
computeMeanAndCovarianceMatrixDemeaned (const pcl::PointCloud<PointInT> &cloud, | ||||
const std::vector<int> &indices, | ||||
Eigen::Matrix<float, 3, 3> &covariance_matrix, | ||||
Eigen::Matrix<float, 4, 1> ¢roid) | ||||
{ | ||||
// create the buffer on the stack which is much faster than using cloud[indices[i]] and centroid as a buffer | ||||
Eigen::Matrix<float, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<float, 1, 9, Eigen::RowMajor>::Zero (); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no need to explicitly specify row/col major in a vector. Also, you're accessing all element individually in the code bellow. A There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This (and the previous There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's update both then. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need a decision first whether we'll keep both :) |
||||
size_t point_count; | ||||
PointInT center = cloud[indices[0]]; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Take a const reference the point. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The case if indices is an empty vector, e.g. no neighbors, must be considered. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add that extra logic then. My original inline comment is still applicable. |
||||
PointInT p; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Under normal circumstances |
||||
|
||||
point_count = indices.size (); | ||||
for (const int &index : indices) | ||||
{ | ||||
//const PointT& point = cloud[*iIt]; | ||||
p.x = cloud[index].x - center.x; | ||||
p.y = cloud[index].y - center.y; | ||||
p.z = cloud[index].z - center.z; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any chance this can be vectorized with? pcl/common/include/pcl/impl/point_types.hpp Line 192 in 861839f
p.getVector4fMap () = center.getVector4fMap (); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We experimented with this and also 3fMap version and there was no difference in performance. |
||||
accu [0] += p.x * p.x; | ||||
accu [1] += p.x * p.y; | ||||
accu [2] += p.x * p.z; | ||||
accu [3] += p.y * p.y; | ||||
accu [4] += p.z * p.z; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi, I think there is a bug in this line, shouldn't it rather be: |
||||
accu [5] += p.z * p.z; | ||||
accu [6] += p.x; | ||||
accu [7] += p.y; | ||||
accu [8] += p.z; | ||||
} | ||||
|
||||
accu /= static_cast<float> (point_count); | ||||
centroid[0] = accu[6] + center.x; | ||||
centroid[1] = accu[7] + center.y; | ||||
centroid[2] = accu[8] + center.z; | ||||
centroid[3] = 1; | ||||
covariance_matrix.coeffRef (0) = accu [0] - accu [6] * accu [6]; | ||||
covariance_matrix.coeffRef (1) = accu [1] - accu [6] * accu [7]; | ||||
covariance_matrix.coeffRef (2) = accu [2] - accu [6] * accu [8]; | ||||
covariance_matrix.coeffRef (4) = accu [3] - accu [7] * accu [7]; | ||||
covariance_matrix.coeffRef (5) = accu [4] - accu [7] * accu [8]; | ||||
covariance_matrix.coeffRef (8) = accu [5] - accu [8] * accu [8]; | ||||
covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1); | ||||
covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2); | ||||
covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5); | ||||
return (static_cast<unsigned int> (point_count)); | ||||
} | ||||
|
||||
protected: | ||||
/** \brief Estimate normals for all points given in <setInputCloud (), setIndices ()> using the surface in | ||||
* setSearchSurface () and the spatial locator in setSearchMethod () | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a big function. This
inline
is uncalled for.