如何在不复制数据的情况下将 cv::Mat 转换为 2d std::vector

Posted

技术标签:

【中文标题】如何在不复制数据的情况下将 cv::Mat 转换为 2d std::vector【英文标题】:How to convert a cv::Mat to a 2d std::vector without copying data 【发布时间】:2019-10-03 10:40:14 【问题描述】:

在 OpenCV 中,我有 cv::Mat 对象。

    它是一个通道,格式为 CV_8UC1 = unsigned char。

    连续,即数据存储在一个地方,逐行存储。

    我知道 cv::Mat 对象的行数和列数。

    我有大小为 2D std::vector 向量 vec1(行,向量(img.cols));

如何在不复制的情况下将 cv::Mat 对象的数据分配给 std::vector

对于复制,很容易创建一个 for 循环,或者使用带有迭代器的 vector::assign。

cv::Mat 和 2D-​​std::vector 的数据存储方式相同。两者都有一个指向数据的内部指针(vector::data 和 Mat::ptr),但 vector::data 不能设置为 Mat::ptr 的值。

目前,我有复制数据的代码:

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);

谢谢。

【问题讨论】:

你不能用vector。也许span 貌似cv::Mat类中数据的指针是public,也就是说可以通过img.data直接访问。但是,你无法操作指向std::vector中数据的指针,所以恐怕无法为所欲为。 这根本不可能。您不能将向量的数据设置到其他地方管理的某些内存中。 【参考方案1】:

简短的回答是你不应该尝试在 std::vectorcv::Mat 之间共享数据,因为两者都拥有数据的所有权,cv::Mat 可以与其他 cv::Mat 对象共享它,这将变得非常难以管理漂亮快。

但是cv::Mat 可以与另一个cv::Mat 共享数据,您可以提取一个或多个行(或列)并与另一个cv::Mat 共享部分数据,如下所示:

    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);

现在您可以创建一个std::vector&lt;cv::Mat&gt;,其中每个 Mat 将是原始图像中的一行(并且它将与原始图像共享数据),或者以您需要的任何方式使用它。

【讨论】:

以上是关于如何在不复制数据的情况下将 cv::Mat 转换为 2d std::vector的主要内容,如果未能解决你的问题,请参考以下文章

如何在不将字体转换为轮廓的情况下将 cairo-pdf 转换为 eps

如何在不丢失值的情况下将 json 解析为 pandas 数据框? [复制]

如何在不使用画布的情况下将整个 div 数据转换为图像并将其保存到目录中?

如何在不丢失 exif 数据的情况下将 UIImage 转换为 JPEG?

如何在不丢失小数的情况下将数据框中的字符转换为数字

在不加载到内存的情况下将 HDF5 转换为 Parquet