使用特征矩阵库的 C++ 代码翻译
C++ Code Translation with Eigen Matrix Library
我将以下代码从使用 Eigen 的 C++ 翻译成 C#。
template <typename PointT> inline unsigned int
pcl::SamplingSurfaceNormal<PointT>::computeMeanAndCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
Eigen::Matrix3f &covariance_matrix,
Eigen::Vector4f ¢roid)
{
// create the buffer on the stack which is much faster than using cloud.points[indices[i]] and centroid as a buffer
Eigen::Matrix<float, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<float, 1, 9, Eigen::RowMajor>::Zero ();
std::size_t point_count = 0;
for (std::size_t i = 0; i < cloud.points.size (); i++)
{
if (!isFinite (cloud[i]))
{
continue;
}
++point_count;
accu [0] += cloud[i].x * cloud[i].x;
accu [1] += cloud[i].x * cloud[i].y;
accu [2] += cloud[i].x * cloud[i].z;
accu [3] += cloud[i].y * cloud[i].y; // 4
accu [4] += cloud[i].y * cloud[i].z; // 5
accu [5] += cloud[i].z * cloud[i].z; // 8
accu [6] += cloud[i].x;
accu [7] += cloud[i].y;
accu [8] += cloud[i].z;
}
accu /= static_cast<float> (point_count);
centroid[0] = accu[6]; centroid[1] = accu[7]; centroid[2] = accu[8];
centroid[3] = 0;
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));
}
在 Eigens 文档中,我可以找到 NO WHERE 在二维矩阵上调用 someMatix3f.coeffRef(x)
或 someMatrix3f.coeff(x)
是什么意思。这些运营商是做什么的?
注意,我看过文档 (https://eigen.tuxfamily.org/dox/classEigen_1_1PlainObjectBase.html#a72e84dc1bb573ad8ecc9109fbbc1b63b),即使我是数学博士,这对我来说也毫无意义。
我尝试使用 MathNET.Numerics
进行翻译,这个方法是
private int ComputeMeanAndCovarianceMatrix(
PointCloud cloud,
Matrix<float> covariance_matrix,
MathNet.Numerics.LinearAlgebra.Vector<float> centroid)
{
int point_count = 0;
Matrix<float> accu = Matrix<float>.Build.DenseOfRowMajor(1, 9, Enumerable.Repeat(0.0f, 9));
for (int i = 0; i < cloud.Vertices.Length; ++i)
{
//if (!isFinite(cloud.Vertices[i].Point.))
//{
// continue;
//}
++point_count;
accu[0, 0] += cloud.Vertices[i].Point.X * cloud.Vertices[i].Point.X;
accu[0, 1] += cloud.Vertices[i].Point.X * cloud.Vertices[i].Point.Y;
accu[0, 2] += cloud.Vertices[i].Point.X * cloud.Vertices[i].Point.Z;
accu[0, 3] += cloud.Vertices[i].Point.Y * cloud.Vertices[i].Point.Y; // 4
accu[0, 4] += cloud.Vertices[i].Point.Y * cloud.Vertices[i].Point.Z; // 5
accu[0, 5] += cloud.Vertices[i].Point.Z * cloud.Vertices[i].Point.Z; // 8
accu[0, 6] += cloud.Vertices[i].Point.X;
accu[0, 7] += cloud.Vertices[i].Point.Y;
accu[0, 8] += cloud.Vertices[i].Point.Z;
}
accu /= point_count;
centroid[0] = accu[0, 6];
centroid[1] = accu[0, 7];
centroid[2] = accu[0, 8];
centroid[3] = 0;
covariance_matrix[0, 0] = accu[0, 0] - accu[0, 6] * accu[0, 6];
covariance_matrix[0, 1] = accu[0, 1] - accu[0, 6] * accu[0, 7];
covariance_matrix[0, 2] = accu[0, 2] - accu[0, 6] * accu[0, 8];
covariance_matrix[1, 1] = accu[0, 3] - accu[0, 7] * accu[0, 7];
covariance_matrix[1, 2] = accu[0, 4] - accu[0, 7] * accu[0, 8];
covariance_matrix[2, 2] = accu[0, 5] - accu[0, 8] * accu[0, 8];
covariance_matrix[1, 0] = covariance_matrix[0, 1];
covariance_matrix[2, 0] = covariance_matrix[0, 2];
covariance_matrix[2, 1] = covariance_matrix[1, 2];
return point_count;
}
看对了吗?
coeffRef
只是提供对底层数据数组的访问。因此,您对 covariance_matrix[i, j]
的翻译应该是等价的。请注意,表达式 covariance_matrix.coeffRef(k)
仅给出数据数组中的第 k
个元素,与存储顺序无关。是的,如果原始代码使用 coeffRef(i,j)
、IMO.
会更有意义
之所以会出现这种情况(我在这里猜测。ggael 和 chtz 可能能够 confirm/refute)是因为 Eigen 使用大量表达式模板来确定何时以及如何评估部分表达式。有些依赖于矩阵的存储顺序,有些则不是。在它不依赖于存储顺序(例如标量 * 矩阵)能够 "short circuit" 的情况下,表达式减少了编译器为决定如何评估给定表达式而必须经历的步骤数量,可以减少编译时间.如果我们明确声明 coeffRef
,那么我们会告诉编译器我们正在谈论一个具有存储空间的具体对象,而不是表达式。
我将以下代码从使用 Eigen 的 C++ 翻译成 C#。
template <typename PointT> inline unsigned int
pcl::SamplingSurfaceNormal<PointT>::computeMeanAndCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
Eigen::Matrix3f &covariance_matrix,
Eigen::Vector4f ¢roid)
{
// create the buffer on the stack which is much faster than using cloud.points[indices[i]] and centroid as a buffer
Eigen::Matrix<float, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<float, 1, 9, Eigen::RowMajor>::Zero ();
std::size_t point_count = 0;
for (std::size_t i = 0; i < cloud.points.size (); i++)
{
if (!isFinite (cloud[i]))
{
continue;
}
++point_count;
accu [0] += cloud[i].x * cloud[i].x;
accu [1] += cloud[i].x * cloud[i].y;
accu [2] += cloud[i].x * cloud[i].z;
accu [3] += cloud[i].y * cloud[i].y; // 4
accu [4] += cloud[i].y * cloud[i].z; // 5
accu [5] += cloud[i].z * cloud[i].z; // 8
accu [6] += cloud[i].x;
accu [7] += cloud[i].y;
accu [8] += cloud[i].z;
}
accu /= static_cast<float> (point_count);
centroid[0] = accu[6]; centroid[1] = accu[7]; centroid[2] = accu[8];
centroid[3] = 0;
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));
}
在 Eigens 文档中,我可以找到 NO WHERE 在二维矩阵上调用 someMatix3f.coeffRef(x)
或 someMatrix3f.coeff(x)
是什么意思。这些运营商是做什么的?
注意,我看过文档 (https://eigen.tuxfamily.org/dox/classEigen_1_1PlainObjectBase.html#a72e84dc1bb573ad8ecc9109fbbc1b63b),即使我是数学博士,这对我来说也毫无意义。
我尝试使用 MathNET.Numerics
进行翻译,这个方法是
private int ComputeMeanAndCovarianceMatrix(
PointCloud cloud,
Matrix<float> covariance_matrix,
MathNet.Numerics.LinearAlgebra.Vector<float> centroid)
{
int point_count = 0;
Matrix<float> accu = Matrix<float>.Build.DenseOfRowMajor(1, 9, Enumerable.Repeat(0.0f, 9));
for (int i = 0; i < cloud.Vertices.Length; ++i)
{
//if (!isFinite(cloud.Vertices[i].Point.))
//{
// continue;
//}
++point_count;
accu[0, 0] += cloud.Vertices[i].Point.X * cloud.Vertices[i].Point.X;
accu[0, 1] += cloud.Vertices[i].Point.X * cloud.Vertices[i].Point.Y;
accu[0, 2] += cloud.Vertices[i].Point.X * cloud.Vertices[i].Point.Z;
accu[0, 3] += cloud.Vertices[i].Point.Y * cloud.Vertices[i].Point.Y; // 4
accu[0, 4] += cloud.Vertices[i].Point.Y * cloud.Vertices[i].Point.Z; // 5
accu[0, 5] += cloud.Vertices[i].Point.Z * cloud.Vertices[i].Point.Z; // 8
accu[0, 6] += cloud.Vertices[i].Point.X;
accu[0, 7] += cloud.Vertices[i].Point.Y;
accu[0, 8] += cloud.Vertices[i].Point.Z;
}
accu /= point_count;
centroid[0] = accu[0, 6];
centroid[1] = accu[0, 7];
centroid[2] = accu[0, 8];
centroid[3] = 0;
covariance_matrix[0, 0] = accu[0, 0] - accu[0, 6] * accu[0, 6];
covariance_matrix[0, 1] = accu[0, 1] - accu[0, 6] * accu[0, 7];
covariance_matrix[0, 2] = accu[0, 2] - accu[0, 6] * accu[0, 8];
covariance_matrix[1, 1] = accu[0, 3] - accu[0, 7] * accu[0, 7];
covariance_matrix[1, 2] = accu[0, 4] - accu[0, 7] * accu[0, 8];
covariance_matrix[2, 2] = accu[0, 5] - accu[0, 8] * accu[0, 8];
covariance_matrix[1, 0] = covariance_matrix[0, 1];
covariance_matrix[2, 0] = covariance_matrix[0, 2];
covariance_matrix[2, 1] = covariance_matrix[1, 2];
return point_count;
}
看对了吗?
coeffRef
只是提供对底层数据数组的访问。因此,您对 covariance_matrix[i, j]
的翻译应该是等价的。请注意,表达式 covariance_matrix.coeffRef(k)
仅给出数据数组中的第 k
个元素,与存储顺序无关。是的,如果原始代码使用 coeffRef(i,j)
、IMO.
之所以会出现这种情况(我在这里猜测。ggael 和 chtz 可能能够 confirm/refute)是因为 Eigen 使用大量表达式模板来确定何时以及如何评估部分表达式。有些依赖于矩阵的存储顺序,有些则不是。在它不依赖于存储顺序(例如标量 * 矩阵)能够 "short circuit" 的情况下,表达式减少了编译器为决定如何评估给定表达式而必须经历的步骤数量,可以减少编译时间.如果我们明确声明 coeffRef
,那么我们会告诉编译器我们正在谈论一个具有存储空间的具体对象,而不是表达式。