C++ – How to get access to vector mat object in OpenCV

cimage processingmatopencvvector

I would like to load some pictures from files to Mat-objects (OpenCV) and want to store them in a vector. Further OpenCV calls/objects need vectors (like: AlignMTB) as arguments. But after filling the vector with Mat-objects I'm only able to get access to the last element I added to the vector.

In the example I first load the images to an intermediary Mat-object and convert it to CV_32FC3. Then I print out the BGR-values of one sample-pixel. The print out is:

File 0: 13 13 157
File 1: 17 20 159
File 2: 8 8 152

Then I add this intermediary Mat to the Mat-vector images.

Afterwards I'm trying to print out the sample-pixel values of the first and second image but always I get the values of the third image:

File 0: 8 8 152
File 1: 8 8 152

What I'm making wrong during accessing the vector data?

I was trying it with this routine:

vector<Mat> images;
images.reserve(3);

Mat img;
for (int i = 0; i < 3; i++)
{
    imread("F:/Test/file" + to_string(i) + ".jpg").convertTo(img, CV_32FC3);

    cout << "File " << i << ": " << img.at<Vec3f>(800, 800)[0] << " " << img.at<Vec3f>(800, 800)[1] << " " << img.at<Vec3f>(800, 800)[2] << endl;

    images.push_back(img);
}
cout << endl;

cout << "File " << 0 << ": " << images[0].at<Vec3f>(800, 800)[0] << " " << images[0].at<Vec3f>(800, 800)[1] << " " << images[0].at<Vec3f>(800, 800)[2] << endl;
cout << "File " << 1 << ": " << images[1].at<Vec3f>(800, 800)[0] << " " << images[1].at<Vec3f>(800, 800)[1] << " " << images[1].at<Vec3f>(800, 800)[2] << endl;

Best Answer

The problem is not vector::push_back, because it will construct a copy of the given element. However, the problem is the copy constructor of Mat which does not copy the associated data:

No data is copied by these constructors. Instead, the header pointing to m data or its sub-array is constructed and associated with it.

What you can do to solve the problem is either an explicit Mat::clone operation which also copies the data or to move the matrix declaration in the for loop.

vector<Mat> images;
images.reserve(3);

Mat img;
for (int i = 0; i < 3; i++)
{
    imread("F:/Test/file" + to_string(i) + ".jpg").convertTo(img, CV_32FC3);

    cout << "File " << i << ": " << img.at<Vec3f>(800, 800)[0] << " " << img.at<Vec3f>(800, 800)[1] << " " << img.at<Vec3f>(800, 800)[2] << endl;

    images.push_back(img.clone());
}
cout << endl;

cout << "File " << 0 << ": " << images[0].at<Vec3f>(800, 800)[0] << " " << images[0].at<Vec3f>(800, 800)[1] << " " << images[0].at<Vec3f>(800, 800)[2] << endl;
cout << "File " << 1 << ": " << images[1].at<Vec3f>(800, 800)[0] << " " << images[1].at<Vec3f>(800, 800)[1] << " " << images[1].at<Vec3f>(800, 800)[2] << endl;
Related Topic