2
votes

I am using OpenCV for some time and now I hit the point where I need a multiplication of this type:

Define a matrix T, which contains elements of the type Vec3d1 . Matrix T has the size: M X N. Matrix T has to be multiplied with a Vector Phi, which has the size: N X 1, containing doubles as values. Each element of the result has to be the result of a matrix multiplication of both matrices.

I don't want to do a component-wise multiplication, but a "real" matrix multiplication, e.g. multiplying the first element of T2 with the first element of matrix J, then multiplying the second element of matrix T3 with the second element of matrix J. Do this until you completed the first row of T and then sum up the results. The result is a M X 1.

For example, if T would be a 3 X 2 matrix and Phi a 2 X 1 matrix, then the calculation should be T_11 * phi_11 + T_12 * phi_21 for the first value of the result. Currently I'm using two for loops which are slow:

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);
}

More generally: Is it possible to efficiently multiply matrices containing Vec3ds and doubles in OpenCV?


1. three dimensional vector containing doubles.

2. coordinate: 1,1

3. coordinate: 1,2

1
Don't try to "help" the compiler, mMatrixT.at(i, j) is just fine (i.e., do not explicitly give the template parameter if it has already been deduced) - Brandlingo
Your matrix T seems to have the size MxNx3. Then you want to multiply this T with the vector phi of size Nx1. But in the next sentence you state that there is a matrix matrix multiplication involved. But there are no two matrices. (Except matrix J which appears out of nowhere) Please elaborate. Btw "real" matrix multiplication involving two 2D matrices with fitting dimensions can be done simply by using A * B. - Brandlingo
Thank you, this seems to reduce a lot of allocations, but it still does not hit a suitable performance. A good improvement though :). - Thomas Kosch
@MatthäusBrandl You're right, I was mixing matrix J and Phi. In this case matrix J and matrix Phi are both the same. I know that two matrices containing double values can be simply multiplied using the star operator. Now I have a matrix T containing vec3d values and a matrix Phi which contains regular double values. Now I want to multiply the vectors from T with the scalar values from Phi, so that the resulting vectors from each multiplication sum up with each row of matrix T. Sorry for confusing you mixing up matrices. - Thomas Kosch
what should be the result? what's the matrix multiplication of a 1xn matrix of Vec3d with a nx1 matrix of type double? should that be the sum of double_i * Vec3d_i? I don't think you can use matrix multiplication directly there because 3-channeled matrices aren't defined mathematically for matrix multiplication with single channel matrices. - Micka

1 Answers

0
votes

I still don't know what kind of result you expect, but maybe try this:

Assuming that you have a MxN matrix of Vec3d and a Nx1 Matrix of type double, your result will be a Mx1 matrix of type Vec3d:

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;
    }

EDIT:

ah sorry, didnt read to the end that your provided code works but is too slow... well, I expect that there is no optimization for that because mathematically this isnt defined. What you can do is to convert your Vec3d mat to a Mx(3*N) matrix and convert your Nx1 mat to a (3*N)x1 mat (3 times the same value before the next value) and use the OpenCV matrix product directly. But probably that's not faster because of the 3* bigger size of both matrices ;)

EDIT: will be a different result, since each element will be the sum of the Vec3d elements...