Computing the outer (tensor) product cv :: Mat in OpenCv

Is there a computer external product way ( z * transpose ( z ) for some z column vector ) using cv::Mat

a data structure in OpenCV?

I checked the documentation and there is no built in function there. But I am getting exceptions trying to use the standard matrix multiplication expression (*) with type vector cv::Mat

.

Here's the (pseudo) code:

cv::Mat tmp = cv::Mat::zeros(9, 1, CV_32SC1)
cv::Mat outerProduct = tmp * tmp.t();

      

The external product calculation gives exceptions. (Yes, I have the actual values ​​in the tmp matrix in my actual code, but this description gives more information about the datatype being used)

Ideally, it cv::Mat outerProduct

should end like a 9x9 matrix.

I could do this using the scaling multiplication property cv::Mat

(i.e., repeat the column vector tmp

by its dimensions, and for each column, scale the items by value in the index - as in how you can solve this kind of multiplication by hand ):

cv::Mat outerProduct = cv::repeat(tmp, 1, 9);
for (int i = 0; i < 9; i++)
{
    outerProduct.col(i) *= tmp.at<int>(i, 0);
}

      

... but it would be nice to have a better way, if there is one.

+3


source to share


2 answers


Please note that while my answer is correct, @ kaanoner's answer gives better performance.


They hide these methods where you least expect. This parameter is located in Operations on arrays and is called mulTransposed .

cv::Mat tmp = (Mat_<double>(9,1) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
cv::Mat outerProduct;
mulTransposed(tmp, outerProduct, false);

      

Third parameter aTa

. If true, the method computes a T a. If it is false, it evaluates aa T .



Output:

tmp = 
[1; 2; 3; 4; 5; 6; 7; 8; 9]
outerProduct = 
[1, 2, 3, 4, 5, 6, 7, 8, 9;
 2, 4, 6, 8, 10, 12, 14, 16, 18;
 3, 6, 9, 12, 15, 18, 21, 24, 27;
 4, 8, 12, 16, 20, 24, 28, 32, 36;
 5, 10, 15, 20, 25, 30, 35, 40, 45;
 6, 12, 18, 24, 30, 36, 42, 48, 54;
 7, 14, 21, 28, 35, 42, 49, 56, 63;
 8, 16, 24, 32, 40, 48, 56, 64, 72;
 9, 18, 27, 36, 45, 54, 63, 72, 81]

      

Looking at the source code, it turns out that it is CV_32S

not supported mulTransposed

. The types of sources and destinations are listed below:

(stype == CV_8U && dtype == CV_32F)
(stype == CV_8U && dtype == CV_64F)
(stype == CV_16U && dtype == CV_32F)
(stype == CV_16U && dtype == CV_64F)
(stype == CV_16S && dtype == CV_32F)
(stype == CV_16S && dtype == CV_64F)
(stype == CV_32F && dtype == CV_32F)
(stype == CV_32F && dtype == CV_64F)
(stype == CV_64F && dtype == CV_64F)

      

As follows from this, the destination type is always float. Even when I specify the dtype CV_16S

, I get a matrix that CV_32F

.

+8


source


In my runs, the transpose and multiply method is twice as fast as a single mulTransposed function call.



Mat descriptor; //(1 rows x 192 cols, CV_32F)
Mat outerProduct;

// calculates outer products for 10000 different descriptors in a loop
mulTransposed(descriptor, outerProduct, true); // => takes 33 secs
outerProduct = descriptor.t()*descriptor; // => takes 14 secs 

      

+3


source







All Articles