The fastest way to copy some rows from one matrix to another in OpenCV

I have a matrix [32678 x 10] ( w2c ), and I want to copy 24,700 rows from it to another matrix ( out ). I have an index of the rows that need to be copied to a vector ( index ). To do this in MATLAB:

 out = w2c(index_im,:); 

It takes approximately 0.002622 seconds.

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

It takes approximately 0.015121 seconds.

As you can see, Matlab is 6 times faster. How can I make OpenCV code efficient?

I am using cmake-2.9, g ++ - 4.8, opencv-2.4.9, ubuntu 14.04

UPDATE

I ran my code in release mode, here is the result (it is still significantly slower than 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 
+1
source share
2 answers

So I tried different methods for this problem and the only way to achieve better performance than Matlab used memcpy and directly copied the data myself.

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

Thus, all this took approximately 0.001063, which is slightly faster than Matlab.

I also found that copying data this way:

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

faster than copying it:

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

but I do not know why. In any case, both of them are slower than Matlab.

0
source

Based on our chat discussion, you are not compiling with optimization enabled. If you do, you will see a noticeable increase in performance. Also, make sure you reference the OpenCV release build.

I measured the runtime for the following example: without and with optimization:

main.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}) 

Compile and run without optimization

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

Compile and run with optimization

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

I conducted these tests on

  • Intel Core i7-4600U Processor
  • Ubuntu 14.04 (x64)
  • GCC 4.8.2
  • OpenCV 3.0.0 (release)
+3
source

All Articles