This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Block and functions taking Eigen types

Tags: None
(comma "," separated)
linello
Registered Member
Posts
56
Karma
0
OS
Hi, I'm wondering why the following function

Code: Select all
template <typename Derived, typename Derived2 >
Derived conv2d(const DenseBase<Derived>& I, const DenseBase<Derived2> &kernel )
{
    Derived O;
    int col=0,row=0;
    int KSizeX = kernel.rows();
    int KSizeY = kernel.cols();
   
    int limitRow = I.rows()-KSizeX;
    int limitCol = I.cols()-KSizeY;
    typedef typename Derived::Scalar Scalar;
    //Scalar accum=0.0;
    //int i=0,j=0;
    //Scalar weightSum = kernel.sum();
    for ( row = KSizeX; row < limitRow; row++ )
    {
      for ( col = KSizeY; col < limitCol; col++ )
      {   
      //cerr << static_cast<Derived2>(I.block(row,col,KSizeX,KSizeY)) << endl << endl;
      O.coeffRef(row,col) = (static_cast<Derived2>(I.block(row,col,KSizeX,KSizeY)).cwiseProduct(kernel) ).sum();
      }
    }
    return O;
}


returns me the following error in compilation phase for the block method.

Code: Select all
 In function ‘Derived conv2d(const Eigen::DenseBase<Derived>&, const Eigen::DenseBase<OtherDerived>&) [with Derived = Eigen::Matrix<float, -0x00000000000000001, -0x00000000000000001>, Derived2 = Eigen::Matrix<float, 3, 3>]’:
testConvolution.cpp:120:23:   instantiated from here
testConvolution.cpp:81:7: error: no matching function for call to ‘Eigen::Matrix<float, 3, 3>::cwiseProduct(const Eigen::DenseBase<Eigen::Matrix<float, 3, 3> >&)’


I want to cast the 3x3 block of a dynamic size matrix to a fixed size 3x3 and then compute the cwiseProduct with another 3x3 fixed size matrix, but it seems not possible.

What am I doing wrong?
linello
Registered Member
Posts
56
Karma
0
OS
Solution:

The following code implements a solution but I think a lot of temporaries are involved...

Code: Select all
template <typename Derived, typename Derived2 >
Derived conv2d(const MatrixBase<Derived>& I, const MatrixBase<Derived2> &kernel )
{
    Derived O(I.rows(),I.cols());
   
    typedef typename Derived::Scalar Scalar;
    typedef typename Derived2::Scalar Scalar2;
   
    int col=0,row=0;
    int KSizeX = kernel.rows();
    int KSizeY = kernel.cols();
   
    int limitRow = I.rows()-KSizeX;
    int limitCol = I.cols()-KSizeY;
   
    Derived2 block ;
   
    for ( row = KSizeX; row < limitRow; row++ )
    {
      for ( col = KSizeY; col < limitCol; col++ )
      {   
      //cerr << static_cast<Derived2>(I.block(row,col,KSizeX,KSizeY)) << endl << endl;
      block = static_cast<Derived2>( I.block(row, col,KSizeX,KSizeY ) );
      Scalar b=(block.cwiseProduct(block)).sum();
      O.coeffRef(row,col) = b;
      }
    }
    return O;
}


Maybe is useful for others like me...
jitseniesen
Registered Member
Posts
204
Karma
2
In the first program, the arguments of conv2d() are declared as DenseBase. This does not work because you cannot mix matrices and arrays in the same expression. Specifically, you cannot take the componentwise product of a matrix with an array. If 'mat' is a matrix (that is, of a subclass of MatrixBase), then "mat.cwiseProduct(other)" compiles only if 'other' is also of a subclass of MatrixBase. In your program, 'kernel' is of type DenseBase, which is not a subclass of MatrixBase, so the program does not compile.

In the second program, the arguments are declared as MatrixBase, so the componentwise product is between two matrices, and everything works. In fact, you can get rid of the casts and temporaries in the body of the double for loop and simply write:

O.coeffRef(row,col) = I.block(row,col,KSizeX,KSizeY).cwiseProduct(kernel).sum();


Bookmarks



Who is online

Registered users: bartoloni, Bing [Bot], Google [Bot], Yahoo [Bot]