【问题标题】:Fastest way to copy some rows from one matrix to another in OpenCV在 OpenCV 中将一些行从一个矩阵复制到另一个矩阵的最快方法
【发布时间】:2015-09-06 06:10:53
【问题描述】:

我有一个 [32678 x 10] 矩阵 (w2c),我想将它的 24700 行复制到另一个矩阵 (out)。我有要在向量中复制的行的索引(index)。为了在 matlab 中执行此操作,我这样做:

out = w2c(index_im,:);

大约需要 0.002622 秒。

在 OpenCV 中:

Mat out(index.cols, w2c.cols, w2c.type());
for (int i = 0; i < index.cols; ++i) {
    w2c.row(index.at<int>(i) - 1).copyTo(out.row(i));
}

大约需要 0.015121 秒。

如您所见,Matlab 快了 6 倍。如何让 OpenCV 代码高效?

我正在使用 cmake-2.9、g++-4.8、opencv-2.4.9、ubuntu 14.04

更新

我在发布模式下运行我的代码,结果如下(它仍然比 Matlab 慢很多)

RELEASE     DEBUG       MATLAB
0.008183    0.010070    0.001604    
0.009630    0.010050    0.001679
0.009120    0.009890    0.001566
0.007534    0.009567    0.001635
0.007886    0.009886    0.001840

【问题讨论】:

  • index 向量的内容是什么样的?它是一个还是多个连续的部分?请提供您的 OpenCV 代码的Minimal, Complete, and Verifiable example
  • index向量是一个1行24700列的矩阵,是连续的。
  • 以什么方式连续?它是否存储值,例如0 到 24699?它包含什么?
  • 连续为index.isContinious()。它包含 0 到 32677 之间的随机数,并且没有任何特定的顺序。
  • 添加更多详细信息:哪个 OpenCV 版本、哪个编译器、哪个编译器标志、哪个操作系统以及完整的示例代码

标签: c++ matlab opencv matrix


【解决方案1】:

所以我尝试了不同的方法来解决这个问题,我能获得比 Matlab 更好的性能的唯一方法是使用 memcpy 并自己直接复制数据。

    Mat out( index.cols, w2c.cols, w2c.type() );
    for ( int i=0;i<index.cols;++i ){
        int ind = index.at<int>(i)-1;
        const float *src = w2c.ptr<float> (ind);
        float *des = out.ptr<float> (i);
        memcpy(des,src,w2c.cols*sizeof(float));
    }

这样整个过程大约花费了 0.001063,比 Matlab 快一点。

我还发现用这种方式复制数据:

    Mat out;
    Mat out( index.cols, w2c.cols, w2c.type() );
    for ( int i=0;i<index.cols;++i ){
        int ind = index.at<int>(i)-1;
        out.push_back(w2c.row(ind)); 
    }

比这样复制要快:

    Mat out( index.cols, w2c.cols, w2c.type() );
    for ( int i=0;i<index.cols;++i ){
        int ind = index.at<int>(i)-1;
        w2c.row(ind).copyTo(out.row(i));
    }

但我不知道为什么。无论如何,它们都比 Matlab 慢。

【讨论】:

    【解决方案2】:

    基于our discussion in chat,您没有在启用优化的情况下进行编译。如果你这样做,你会看到显着的性能提升。此外,请确保您链接的是 OpenCV 的发布版本。

    我测量了以下示例在未启用优化和启用优化的情况下的执行时间:

    ma​​in.cpp

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <numeric>
    #include <random>
    #include <vector>
    #include <chrono>
    #include <opencv2/opencv.hpp>
    
    
    int main(int argc, char **argv)
    {
        const int num_rows = 32678;
        const int num_cols = 10;
        const int index_size = 24700;
    
        const int num_runs = 1000;
        const int seed = 42;
    
        std::vector<int> index_vec(num_rows);
    
        // fill index with sequence
        std::iota (index_vec.begin(), index_vec.end(), 0);
    
        // randomize sequence
        std::random_device rd;
        std::mt19937 g(rd());
        g.seed(seed);
        std::shuffle(index_vec.begin(), index_vec.end(), g);
    
        // trunkate index
        index_vec.resize(index_size);
    
        cv::Mat w2c(num_rows, num_cols, CV_32F);
    
        // copy
        cv::Mat out(index_size, w2c.cols, w2c.type());
    
        auto start = std::chrono::high_resolution_clock::now();
        for (int k = 0; k<num_runs; ++k)
        {
            for (int i = 0; i < index_size; ++i)
            {
                w2c.row(index_vec[i]).copyTo(out.row(i));
            }
        }
    
        auto end = std::chrono::high_resolution_clock::now();
    
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    
        std::cout << duration.count()/num_runs << " microseconds" << std::endl;
    
        return 0;
    }
    

    CMakeLists.txt

    project(copy)
    find_package(OpenCV REQUIRED)
    add_executable(copy main.cpp)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
    include_directories(${OpenCV_INCLUDE_DIRS})
    target_link_libraries(copy ${OpenCV_LIBS})
    

    无需优化即可编译运行

    cmake . -DCMAKE_BUILD_TYPE=DEBUG
    make
    ./copy
    3924 microseconds
    

    编译并运行优化

    cmake . -DCMAKE_BUILD_TYPE=RELEASE
    make
    ./copy
    2664 microseconds
    

    我在

    上运行了这些测试
    • 英特尔酷睿 i7-4600U CPU
    • Ubuntu 14.04 (x64)
    • GCC 4.8.2
    • OpenCV 3.0.0(发布版本)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 1970-01-01
      • 2013-11-18
      • 2019-04-13
      • 1970-01-01
      相关资源
      最近更新 更多