【问题标题】:Copying a GpuMat row to a std::vector将 GpuMat 行复制到 std::vector
【发布时间】:2011-11-21 00:53:26
【问题描述】:

如何使用尽可能少的复制操作将 cv::gpu::GpuMat 行传输到 std::vector?

我能想到的最快的方法是:

GpuMat fooGpu(numRows, numCols, CV_32FC1);
Mat foo = fooGpu;

Mat fooRow = foo.row(i);

std::vector<float> vec;
vec.resize(numCols);

memcpy(&vec[0], fooRow.data, sizeof(float)*numCols);

但我什至不确定这是否有效,因为 fooRow 内容必须对齐...

还有其他(更好的)方法吗?

【问题讨论】:

    标签: c++ opencv copy gpu stdvector


    【解决方案1】:

    this 的帖子可能会回答您的问题。

    【讨论】:

      【解决方案2】:

      这是不会产生任何不必要复制的方法:

      GpuMat fooGpu(numRows, numCols, CV_32FC1);
      std::vector<float> vec;
      vec.resize(numCols);
      fooGpu.row(i).download(Mat(vec).reshape(1/*channels*/, 1/*rows*/));
      

      【讨论】:

      • 谢谢!这正是我想要的:)
      • 不,抱歉。我测试了它,它不起作用。 Mat(vec) 使用 vec 进行初始化值,但似乎并没有指向 vec 的数据,因为下载后,vec 仍然用零填充。垫米; fooGpu.row(i).download(m); vec = 米;有效,但这又涉及到复制。
      • 我很确定Mat(vec) 共享向量数据,但向量必须分配正确的长度(vec.resize(numCols); 是强制性的)。如果此代码不起作用,则它是 OpenCV 错误,应在 OpenCV bugtracker 上报告。
      • 你是对的。但是 download() 方法似乎重新分配了内存。
      • 我找到了问题的根源并更新了答案:默认情况下,向量被转换为具有vec.size() 行和 1 列的 Mat。不过我觉得这个case是bug,要提交ticket了。
      【解决方案3】:

      我认为std::copy 更好:

      std::vector<float> vec;
      vec.resize(numCols); 
      std::copy(fooRow.data, fooRow.data + numCols, vec.begin());
      

      请注意,第二个参数是:fooRow.data + numCols,而不是 fooRow.data + sizeof(float)* numCols

      另外,在您的代码中 vec.resize(numRows); 似乎不正确。应该是:

       vec.resize(numCols);
      

      因为fooRow 是一行,并且其中有numCols 个值。

      【讨论】:

      • 使用back_inserter 可能不需要调整大小,并且调整大小无论如何都会摊销到 O(1),但我认为保留不是一个坏主意,因为无论如何你都知道大小。虽然比起过早优化的代码更喜欢干净的代码是个好主意,但我们不应该让我们变得比现在更笨。
      • 你当然是对的......而且你的代码看起来更好。但我仍然想知道我是否可以直接访问 GpuMat 数据。如果不是:我可以假设 fooRow-data 是对齐的吗?
      • @Nawaz 但是现在你有一个resize 和一个back_inserter。使用reservevec.begin()
      猜你喜欢
      • 2011-05-19
      • 1970-01-01
      • 2014-01-11
      • 1970-01-01
      • 1970-01-01
      • 2018-07-24
      • 1970-01-01
      • 2012-01-06
      • 2011-02-23
      相关资源
      最近更新 更多