c# - 使用Eigen矩阵库进行C++代码转换

标签 c# c++ eigen

我有以下代码,我正在使用Eigen从C++转换为C#。

template <typename PointT> inline unsigned int
pcl::SamplingSurfaceNormal<PointT>::computeMeanAndCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                                                                    Eigen::Matrix3f &covariance_matrix,
                                                                    Eigen::Vector4f &centroid)
{
    // 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文档中,我找不到在2D矩阵上调用someMatix3f.coeffRef(x)someMatrix3f.coeff(x)意味着什么。这些运算符(operator)做什么?

注意,我看过文档(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 th元素,与存储顺序无关。是的,对于原始代码而言,使用IMO的coeffRef(i,j)更有意义。

出现这种情况的原因(我在这里猜测。ggael和chtz可能能够确认/驳斥)是因为Eigen使用了大量的表达式模板来确定何时以及如何评估表达式的各个部分。有些依赖于矩阵的存储顺序,有些则没有。在不依赖于存储顺序(例如标量*矩阵)能够“短路”的情况下,该表达式会减少编译器为了决定如何评估给定表达式而必须执行的步骤,从而减少了编译时间。如果我们明确声明coeffRef,那么我们告诉编译器我们正在谈论的是带有存储的具体对象,而不是表达式。

关于c# - 使用Eigen矩阵库进行C++代码转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60248458/

相关文章:

c++ - 如何将 Eigen 库添加到 C++ 项目中

c++ - 从 Eigen 中的 bool 矩阵采样

c# - 显示消息对话框的方法

c# - 为什么 HttpRequestValidationException 有 500 个 http 错误代码而不是 400?

c# - 在 MonoDevelop 中获得漂亮的小部件尺寸 (Gtk#)

c++ - 包含标准库时不使用预编译头文件

c++ - 在 windows(W32) 上安装 opencv 以与代码块一起使用

c# - 如何编写与 ViewModel 类绑定(bind)的嵌套类?

c++ - 无论如何传递函数作为模板参数?

c++ - 创建矩阵?