【问题标题】:Convert cv::Mat to std::vector without copying将 cv::Mat 转换为 std::vector 而不复制
【发布时间】:2017-09-29 07:50:50
【问题描述】:

我有这个功能:

void foo(cv::Mat &mat){
  float *p = mat.ptr<float>(0);
  //modify mat values through p
}

我有这个调用函数的代码:

void bar(std::vector<unsigned char> &vec){
  //...
  cv::Mat res(m, n, CV_32FC1, (void *)&workspace.front());
}

但是,上面的代码存在性能问题:vec 可能没有对齐。事实上,英特尔编译器说reference *out has unaligned access。我希望是这个原因。

顺便说一句,正如我在this 问题中发现的那样,cv::Mat 将被对齐。所以一个简单的解决方法是:

  1. 创建cv::Mat res(m,n)
  2. 致电foo(m);
  3. vec 指针分配给m.ptr&lt;float&gt;(0)

正如您可以想象的那样,这里的性能至关重要,因此深拷贝是不可能的。

我试过this问题中的代码:

vec = res.data;

但是我得到一个编译器错误。此外,我不知道上面的这段代码是否会进行(低效)复制,或者只是将指向的数据更改为vec

我怎样才能顺利地做到这一点?否则,将不胜感激另一种解决方法。

【问题讨论】:

    标签: c++ opencv vector alignment mat


    【解决方案1】:

    看看here

    std::vector<uchar> array;
    if (mat.isContinuous()) {
      array.assign(mat.datastart, mat.dataend);
    } else {
      for (int i = 0; i < mat.rows; ++i) {
        array.insert(array.end(), mat.ptr<uchar>(i), mat.ptr<uchar>(i)+mat.cols);
      }
    }
    
    //p.s.: For cv::Mats of other types, like CV_32F, you should do like this:
    
    std::vector<float> array;
    if (mat.isContinuous()) {
      array.assign((float*)mat.datastart, (float*)mat.dataend);
    } else {
      for (int i = 0; i < mat.rows; ++i) {
        array.insert(array.end(), (float*)mat.ptr<uchar>(i), (float*)mat.ptr<uchar>(i)+mat.cols);
      }
    }
    

    【讨论】:

    • 感谢您的回答,但我担心这会对元素进行深度复制,而不是引用(因此效率低下),对吧?换句话说,这将是线性的。
    • 对不起,我没有注意。也许是一个普通的指针数组,我还问了一个也使用 open CV 的朋友,他指向了同一个方向。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多