user1805103
user1805103

Reputation: 129

Copy Vector of Contour Points into Mat

I am using OpenCV 3.1 with VS2012 C++/CLI.

I have stored the result of a finContours call into:

std::vector<std::vector<Point>> Contours;

Thus, Contours[0] is a vector of the contour points of the first contour. Contours[1] is a vector of the contour points of the second vector, etc.

Now, I want to load one of the contours into a Mat Based on Convert Mat to vector <float> and Vector<float> to mat in opencv I thought something like this would work.

Mat testMat=Mat(Images->Contours[0].size(),2,CV_32FC1);    
memcpy(testMat.data,Images->Contours[0].data(),Images->Contours[0].size()*CV_32FC1);

I specified two columns because I each underlying pint must be composed of both an X point and a Y point and each of those should be a float. However, when I access the Mat elements, I can see that the first element is not the underlying data but the total number of contour points.

Any help on the right way to accomplish this appreaciated.

Upvotes: 1

Views: 2759

Answers (1)

Miki
Miki

Reputation: 41765

You can do that with:

Mat testMat = Mat(Images->Contours[0]).reshape(1);

Now testMat is of type CV_32SC1, aka of int. If you need float you can:

testMat.convertTo(testMat, CV_32F);

Some more details and variants...

You can simply use the Mat constructor that accepts a std::vector:

vector<Point> v = { {0,1}, {2,3}, {4,5} };
Mat m(v);

With this, you get a 2 channel matrix with the underlying data in v. This means that if you change the value in v, also the values in m change.

v[0].x = 7; // also 'm' changes

If you want a deep copy of the values, so that changes in v are not reflected in m, you can use clone:

Mat m2 = Mat(v).clone();

Your matrices are of type CV_32SC2, i.e. 2 channels matrices of int (because Point uses int. Use Point2f for float). If you want a 2 columns single channel matrix you can use reshape:

Mat m3 = m2.reshape(1);

If you want to convert to float type, you need to use convertTo:

Mat m4;
m2.convertTo(m4, CV_32F);

Here some working code as a proof of concept:

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

int main()
{
    vector<Point> v = { {0,1}, {2,3}, {4,5} };

    // changes in v affects m
    Mat m(v); 

    // changes in v doesn't affect m2
    Mat m2 = Mat(v).clone(); 

    // m is changed
    v[0].x = 7; 

    // m3 is a 2 columns single channel matrix
    Mat m3 = m2.reshape(1);

    // m4 is a matrix of floats
    Mat m4;
    m2.convertTo(m4, CV_32F);

    return 0;
}

Upvotes: 2

Related Questions