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.
source to share
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
.
source to share
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
source to share