1
votes

In OpenCV I have cv::Mat object.

  1. It is one channel with the format CV_8UC1 = unsigned char.

  2. It is continuous, which means the data are stored in one place and rows by rows.

  3. I know the numbers of rows and columns of the cv::Mat object.

  4. I have 2D std::vector of size vector< vector > vec1(rows, vector(img.cols));

How could I assign the data of cv::Mat object to the std::vector without copying.

For copying it is easy to create a for-loop or maybe use vector::assign with an iterator.

The storage of the data is the same between cv::Mat and 2D-std::vector. Both have an internal pointer to the data (vector::data and Mat::ptr) but vector::data can't be set to the value of Mat::ptr.

Currently, I have the code with copying the data:

cv::Mat img = cv::imread("test.tif");
cv::cvtColor(img, img, cv::COLOR_BGR2GRAY);

vector< vector<double> > vec1(img.rows, vector<double>(img.cols));

for(int i=0; i < img.rows; ++i)
    for(int j=0; j < img.cols; ++j)
        vec1.at(i).at(j) = img.at<double>(i, j);

Thanx.

1
you can't with vector. Maybe span?Miki
Looks like the pointer to the data in cv::Mat class is public, which means you can access it directly through img.data. However, you can't manipulate the pointer to the data in std::vector, so I'm afraid it's not possible to do what you want.Eron
It is simply not possible. You cannot set vector's data to some memory managed elsewhere.Daniel Langr

1 Answers

0
votes

The short answer is you shouldn't try to share data between std::vector and cv::Mat because both take ownership of the data and cv::Mat can share it with other cv::Mat objects and that will become pretty unmanageable pretty fast.

But cv::Mat can share data with another cv::Mat and you can extract one or more rows (or columns) and have a partial shared data with another cv::Mat like this:

    cv::Mat img;
    //.. read the img

    //first row
    cv::Mat row0 = img(cv::Range(0,1), cv::Range(0,img.cols));

    //the 4'th column is shared
    cv::Mat column3 = img(cv::Range(0,img.rows), cv::Range(3,4));
    //you can set new data into column3/row0 and you'll see it's shared:
    //row0.setTo(0);
    //column3.setTo(0);

Now you can create a std::vector<cv::Mat> where each Mat will be a row in the original image (and it will share the data with the original image), or use it in whatever way you need.