Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matrix multiplication

Tags:

c++

c

opencv

I have a question which might be for beginners.

I want to multiply a 20x2 matrix by a 2x2 matrix in c++.

I tried it with openCV but I get an error which is

Bad argument (Unknown array type) in cvarrToMat


Here is the code that I used in openCV in order to check the problem if it was with my code or the problem in the openCV but it still not working, I can compile with out error, but when I test the code I get the problem " Bad argument (Unknown array type) in cvarrToMat"

#include <stdio.h>
#include <stdlib.h>
//#include "/usr/include/opencv/cv.h"
#include <cv.h>
#include <cvaux.h>
#include <highgui.h>
#include <math.h>
#include <iostream>

  int main()
{


double a[] = {1, 2, 3, 4};
CvMat Ma;
cvInitMatHeader(&Ma, 2, 2, CV_32FC1, a);


double b[] ={0, -1, 1, 0};

CvMat Mb;
cvInitMatHeader(&Mb, 2, 2, CV_32FC1, b);

CvMat Mc;
CvMat Mc1;
cvMatMul(&Ma, &Mb, &Mc);

return 0;
}
like image 905
Mario Avatar asked Dec 17 '10 00:12

Mario


People also ask

What is the matrix multiplication rule?

To perform matrix multiplication, the first matrix must have the same number of columns as the second matrix has rows. The number of rows of the resulting matrix equals the number of rows of the first matrix, and the number of columns of the resulting matrix equals the number of columns of the second matrix.


2 Answers

Comparing your code with the example in the OpenCV docs, it seems that you forgot to initialize the output matrix Mc:

double a[] = { 1, 2, 3, 4,
               5, 6, 7, 8,
               9, 10, 11, 12 };

double b[] = { 1, 5, 9,
               2, 6, 10,
               3, 7, 11,
               4, 8, 12 };

double c[9];
CvMat Ma, Mb, Mc ;

cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a);
cvInitMatHeader(&Mb, 4, 3, CV_64FC1, b);
cvInitMatHeader(&Mc, 3, 3, CV_64FC1, c);

cvMatMulAdd(&Ma, &Mb, 0, &Mc);
// the c array now contains the product of a (3x4) and b (4x3)

According to the docs, cvMatMul(&Ma, &Mb, &Mc) is the same as cvMatMulAdd(&Ma, &Mb, 0, &Mc).

like image 106
carnieri Avatar answered Sep 19 '22 11:09

carnieri


Well. The answer to this question really depends on a few things. You've said that you know how to do this by hand so to do this in code it will depend on how you represent your matrices. Now if this is a one time thing and you just need the answer to it, I would suggest a language like MATLAB that is built for this. If it is part of a larger program and you will be doing a lot of matrix multiplications that need to be efficient I recommend a high quality optimized library like boost::ublas.

If it is a one time thing and you really want to do it in C++ and you really don't want/know how to use a third party library like ublas, a (not-optimized) matrix multiplication would like like the following:

template<typename T>
struct matrix2d
{
private:
    std::vector<std::vector<T>> data;
    size_t _rows, _columns;
public:
    matrix2d(size_t rows, size_t columns)
        :_rows(rows)
        ,_columns(columns)
    {
        data.resize(_rows, std::vector<T>(_columns));
    }

    size_t rows() const { return _rows; } 
    size_t columns() const { return _columns; } 

    T& operator()(size_t row, size_t column)
    {
        return data[row][column];
    }

    const T& operator()(size_t row, size_t column) const
    {
        return data[row][column];
    }
};

template<typename T>
void mmult(const matrix2d<T>& m1, const matrix2d<T>&m2, matrix2d<T>& result)
{
    for (size_t r = 0 ; r<m1.rows() ; ++r)
        for (size_t c = 0; c<m2.columns() ; ++c)
            for (size_t n = 0; n<m1.columns() ; ++n)
                result(r, c) = m1(r, n) * m2(n, c);
}


int main()
{

    matrix2d<double> m1(20, 2);
    matrix2d<double> m2(2, 2);
    matrix2d<double> result(m1.rows(), m2.columns());
    mmult(m1, m2, result);
}
like image 29
DeusAduro Avatar answered Sep 21 '22 11:09

DeusAduro