samedi 31 août 2019

Data in `std::vector` different when using `std::unique_ptr`

I have written a custom class that stores images and eventually computes a calibration based on those images, but I am encountering an issue in the way that the images are stored. I have two overloaded functions that do this, with one reading the images from file using cv::imread, and the other using an intermediate Snapshot data structure for holding the data. The function using cv::imread works fine, but the one using the custom data structure does not. I am trying to store three images right now, and the issue is that as I push the images into a vector, the data for the second images is copied into the first one.

This is the working function:

bool CalibClass::AddImage(const std::string& snapshotPath) {
    cv::Mat img = cv::imread(snapshotPath);

    // _snapshots is a private member declared as a std::vector<cv::Mat>
    _snapshots.push_back(img);

    return true;
}

This is the function that is not working:

bool CalibClass::AddImage(const ImageSet& snapshot) {

    RGBImage *rgb_image_ptr = snapshot.GetRGBImage();

    std::vector<unsigned char> img_data(rgb_image_ptr->GetData());
    cv::Mat img(rgb_image_ptr->GetHeight(), rgb_image_ptr->GetWidth(), CV_8UC3, img_data.data());

    _snapshots.push_back(img);

    return true;
}

The ImageSet class stores images as an std::unique_ptr<RGBImage>. The RGBImage class stores the image data as a std::vector<unsigned char>.

This is how the images are loaded into the class from the main:

cv::Mat img1 = cv::imread("img1.png");
cv::Mat img2 = cv::imread("img2.png");      
cv::Mat img3 = cv::imread("img3.png");

int length = img1.total() * img1.elemSize();

std::vector<unsigned char> data1;
std::vector<unsigned char> data2;
std::vector<unsigned char> data3;
for (int i = 0; i < length; i++) {
    data1.push_back(img1.data[i]);
}

for (int i = 0; i < length; i++) {
    data2.push_back(img2.data[i]);
}

for (int i = 0; i < length; i++) {
    data3.push_back(img3.data[i]);
}


CalibClass calib_test;

std::unique_ptr<RGBImage> rgb_image_ptr1(new RGBImage(img1.rows, img1.cols, data1));
ImageSet new_snap1(rgb_image_ptr1, nullptr, 0);
calib_test.AddImage(new_snap1);


std::unique_ptr<RGBImage> rgb_image_ptr2(new RGBImage(img2.rows, img2.cols, data2));
ImageSet new_snap2(rgb_image_ptr2, nullptr, 0);
calib_test.AddImage(new_snap2);

std::unique_ptr<RGBImage> rgb_image_ptr3(new RGBImage(img3.rows, img3.cols, data3));
ImageSet new_snap3(rgb_image_ptr3, nullptr, 0);
calib_test.AddImage(new_snap3);

When I put a break point inside the function and check the content of the _snapshots, the first element is the second image, and the second and third elements are the third image. When I set a break point after all the AddImage() calls, the content of _snapshots has the second image as the first element, the third image as the second element, and the third element has a cv::Mat with invalid data.

What is the reason why the two methods are storing the images differently? What would be the way to fix this issue?

Aucun commentaire:

Enregistrer un commentaire