Riccardo Giubilato Riccardo Giubilato - 2 months ago 12
C++ Question

Can't assign values to cv::Mat inside function

I need to create a

Mat
object of type
CV_32FC2
to store coordinate points contained in a
KeyPoint
structure. I want to do it inside a function for clarity.

void myfun(vector<KeyPoint>& k){
Mat p1_dist(1, k.size(), CV_32FC2);

for(int i=0; i<k.size(); i++){
p1_dist.at<double>(0, i)[0] = k1[i].pt.x;
p1_dist.at<double>(0, i)[1] = k1[i].pt.y;
}
}


The compiler underlines the "p1_dist" inside the for loop asking for a pointer to that Mat.
If I write that piece of code inside the main function the error won't happen.
Can you help me pointing out the issue?

Answer

First you need to return the matrix you create. To conform to OpenCV, you can pass a reference to Mat:

void myfun(const vector<KeyPoint>& k, Mat& p1_dist){ ... }

Then you need to access the data values with the correct template. If you need a CV_32FC2 matrix, i.e. a matrix of float with 2 channels, you need to access it with: p1_dist.at<Vec2f>(row, col)[channel], i.e.:

p1_dist.at<Vec2f>(0, i)[0] = k[i].pt.x;
p1_dist.at<Vec2f>(0, i)[1] = k[i].pt.y;

It's usually clearer to use the Mat_<Tp> when you already know the type of the matrix. The equivalent for CV_32FC2 would be Mat2f:

void myfun(const vector<KeyPoint>& k, Mat2f& p1_dist){  
    ...
    p1_dist(0, i)[0] = k[i].pt.x;
    p1_dist(0, i)[1] = k[i].pt.y;
    ...  
}

Putting all together:

#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

void myfun(const vector<KeyPoint>& k, Mat2f& p1){
    p1 = Mat2f(1, k.size()); // Set proper size

    for(size_t i=0; i<k.size(); i++){
       p1(0, i)[0] = k[i].pt.x;
       p1(0, i)[1] = k[i].pt.y;
    }
}

int main()
{
    vector<KeyPoint> k = ...;
    Mat2f p1_dist;
    myfun(k, p1_dist);   

    // Use p1_dist

    return 0;
}