【问题标题】:OpenCV: Matrix multiplication with a matrix containing Vec3d and a matrix containing doublesOpenCV:矩阵乘法与包含 Vec3d 的矩阵和包含双精度数的矩阵
【发布时间】:2015-12-30 17:24:49
【问题描述】:

我使用 OpenCV 有一段时间了,现在我需要这种类型的乘法:

定义一个矩阵T,其中包含Vec3d1 类型的元素。矩阵T 的大小为:M X N。矩阵T 必须乘以向量Phi,其大小为:N X 1,包含doubles 作为值。结果的每个元素都必须是两个矩阵的矩阵相乘的结果。

我不想做一个组件乘法,而是一个“真正的”矩阵乘法,例如将T2 的第一个元素与矩阵J 的第一个元素相乘,然后将矩阵T3 的第二个元素与矩阵的第二个元素相乘J。这样做直到完成T 的第一行,然后总结结果。结果是 M X 1。

例如,如果T 是一个 3 X 2 矩阵,Phi 是一个 2 X 1 矩阵,那么计算结果的第一个值应该是 T_11 * phi_11 + T_12 * phi_21。目前我正在使用两个缓慢的 for 循环:

for (int i = 0; i<M; ++i){
    cv::Mat summedResult = cv::Mat(3, 1, CV_64F, double(0));
    for (uint32 j = 0; j<N; ++j){
        summedResult = summedResult + 
        (cv::Mat(mMatrixT.at<cv::Vec3d>(i, j)) * mMatrixPhi.at<double>(j));
    }
    // The result matrix contains values of type Vec3d again
    mResultMatrix.at<cv::Vec3d>(i) = cv::Vec3d(summedResult);
}

更一般地说:是否可以在 OpenCV 中有效地将包含 Vec3dsdoubles 的矩阵相乘?


1.包含双精度的三维向量。

2。坐标:1,1

3。坐标:1,2

【问题讨论】:

  • 不要试图“帮助”编译器,mMatrixT.at(i, j) 就可以了(即,如果模板参数已经推导出来,就不要显式给出)
  • 您的矩阵 T 的大小似乎为 MxNx3。然后你想将此 T 与大小为 Nx1 的 vector phi 相乘。但是在下一句中,您声明涉及矩阵矩阵乘法。但是没有两个矩阵。 (除了突然出现的矩阵J)请详细说明。顺便说一句,涉及两个具有拟合尺寸的二维矩阵的“真实”矩阵乘法可以简单地通过使用A * B 来完成。
  • 谢谢,这似乎减少了很多分配,但仍然没有达到合适的性能。虽然是一个很好的改进:)。
  • @MatthäusBrandl 没错,我正在混合矩阵 J 和 Phi。在这种情况下,矩阵 J 和矩阵 Phi 都是相同的。我知道两个包含双精度值的矩阵可以使用星号运算符简单地相乘。现在我有一个包含 vec3d 值的矩阵 T 和一个包含常规双精度值的矩阵 Phi。现在我想将 T 中的向量与 Phi 中的标量值相乘,以便每次乘法的结果向量与矩阵 T 的每一行相加。抱歉让您混淆了矩阵。
  • 结果应该是什么? Vec3d 的 1xn 矩阵与 double 类型的 nx1 矩阵的矩阵乘法是什么?那应该是 double_i * Vec3d_i 的总和吗?我不认为你可以在那里直接使用矩阵乘法,因为 3 通道矩阵没有在数学上定义为与单通道矩阵的矩阵乘法。

标签: c++ opencv matrix


【解决方案1】:

我仍然不知道你期望什么样的结果,但不妨试试这个:

假设你有一个 Vec3d 的 MxN 矩阵和一个 double 类型的 Nx1 矩阵,你的结果将是一个 Vec3d 类型的 Mx1 矩阵:

for (int i = 0; i<M; ++i)
    {
        cv::Vec3d summedResult; // here this must be a Vec3d instead of a matrix, if I assume the right result expection
        for (uint32 j = 0; j<N; ++j)
        {
            summedResult = summedResult + (mMatrixT.at<cv::Vec3d>(i, j) * mMatrixPhi.at<double>(j));
        }
        // The result matrix contains values of type Vec3d again
        mResultMatrix.at<cv::Vec3d>(i) = summedResult;
    }

编辑:

抱歉,最后没有读到您提供的代码可以工作,但是太慢了……好吧,我希望没有对此进行优化,因为从数学上讲,这没有定义。您可以做的是将您的 Vec3d 垫子转换为 Mx(3*N) 矩阵并将您的 Nx1 垫子转换为 (3*N)x1 垫子(下一个值之前相同值的 3 倍)并使用 OpenCV 矩阵产品直接地。但这可能不会更快,因为两个矩阵的大小都大了 3* ;)

编辑:将是不同的结果,因为每个元素都是 Vec3d 元素的总和...

【讨论】:

  • 谢谢。我会试一试:)。
  • @ThomasKosch 这也是我的猜测,也许您可​​以重构您的计算以使用数学(明确)定义的计算。否则,您可能会尝试使用 3D 矩阵而不是 2D 向量矩阵。排列矩阵维度,以便在进行点积或矩阵积时访问连续内存。
  • @Micka 和 OP 一样:不要帮助编译器,让它尽可能推导出模板参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 2017-03-11
相关资源
最近更新 更多