什么是从cv垫中删除行或col的最佳方法

man*_*ans 3 c++ algorithm opencv

假设我有一个mat对象,如下所示:

mat = 
   [75, 97, 66, 95, 15, 22;
    24, 21, 71, 72, 34, 66;
    21, 69, 88, 72, 64, 1;
    26, 47, 26, 40, 95, 24;
    70, 37, 9, 83, 16, 83];
Run Code Online (Sandbox Code Playgroud)

我想从它删除一行说第二行有这样的垫子:

 [75, 97, 66, 95, 15, 22;
 21, 69, 88, 72, 64, 1;
 26, 47, 26, 40, 95, 24;
 70, 37, 9, 83, 16, 83]
Run Code Online (Sandbox Code Playgroud)

或删除col col say col 3:

[75, 97,  95, 15, 22;
 24, 21,  72, 34, 66;
 21, 69,  72, 64, 1;
 26, 47,  40, 95, 24;
 70, 37,  83, 16, 83]
Run Code Online (Sandbox Code Playgroud)

最快的方法是什么?我可以将矩阵分解为ROI,然后将它们相互合并,但有没有更好的方法?

nil*_*ils 7

我测试了两种方法:

  1. 使用cv::Rectcv::Mat::copyTo:

    // Removing a row
    cv::Mat matIn;    // Matrix of which a row will be deleted.
    int row;          // Row to delete.
    int col;          // Column to delete.
    cv::Mat matOut;   // Result: matIn less that one row.
    
    if ( row > 0 ) // Copy everything above that one row.
    {
        cv::Rect rect( 0, 0, size.width, row );
        matIn( rect ).copyTo( matOut( rect ) );
    }
    
    if ( row < size.height - 1 ) // Copy everything below that one row.
    {
        cv::Rect rect1( 0, row + 1, size.width, size.height - row - 1 );
        cv::Rect rect2( 0, row, size.width, size.height - row - 1 );
        matIn( rect1 ).copyTo( matOut( rect2 ) );
    }
    
    // Removing a column
    if ( col > 0 ) // Copy everything left of that one column.
    {
        cv::Rect rect( 0, 0, col, size.height );
        matIn( rect ).copyTo( matOut( rect ) );
    }
    
    if ( col < size.width - 1 ) // Copy everything right of that one column.
    {
        cv::Rect rect1( col + 1, 0, size.width - col - 1, size.height );
        cv::Rect rect2( col,     0, size.width - col - 1, size.height );
        matIn( rect1 ).copyTo( matOut( rect2 ) );
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用std::memcpycv::Mat::data:

    // Removing a row
    int rowSizeInBytes = size.width * sizeof( T );
    
    if ( row > 0 )
    {
        int numRows  = row;
        int numBytes = rowSizeInBytes * numRows;
        std::memcpy( matOut.data, matIn.data, numBytes );
    }
    
    if ( row < size.height - 1 )
    {
        int matOutOffset = rowSizeInBytes * row;
        int matInOffset  = matOutOffset + rowSizeInBytes;
    
        int numRows  = size.height - ( row + 1 );
        int numBytes = rowSizeInBytes * numRows;
        std::memcpy( matOut.data + matOutOffset , matIn.data + matInOffset, numBytes );
    }
    
    // Removing a column
    int rowInInBytes  = size.width * sizeof( T );
    int rowOutInBytes = ( size.width - 1 ) * sizeof( T );
    
    if ( col > 0 )
    {
        int matInOffset = 0;
        int matOutOffset = 0;
        int numCols = col;
        int numBytes = numCols * sizeof( T );
    
        for ( int y = 0; y < size.height; ++y )
        {
            std::memcpy( matOut.data + matOutOffset, matIn.data + matInOffset, numBytes );
    
            matInOffset  += rowInInBytes;
            matOutOffset += rowOutInBytes;
        }
    }
    
    if ( col < size.width - 1 )
    {
        int matInOffset = ( col + 1 ) * sizeof( T );
        int matOutOffset = col * sizeof( T );
        int numCols = size.width - ( col + 1 );
        int numBytes = numCols * sizeof( T );
    
        for ( int y = 0; y < size.height; ++y )
        {
            std::memcpy( matOut.data + matOutOffset, matIn.data + matInOffset, numBytes );
    
            matInOffset  += rowInInBytes;
            matOutOffset += rowOutInBytes;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

第一种方法的定时测试显示:

Removed:      row
Method:       cv::Rect + cv::Mat::copyTo()
Iterations:   10000
Size:         [500 x 500]
Best time:    67ms
Worst time:   526ms
Average time: 70.9061ms
Median time:  70ms

Removed:      column
Method:       cv::Rect + cv::Mat::copyTo()
Iterations:   10000
Size:         [500 x 500]
Best time:    64ms
Worst time:   284ms
Average time: 80.3893ms
Median time:  79ms
Run Code Online (Sandbox Code Playgroud)

对于第二种方法:

Removed:      row
Method:       std::memcpy and/or for-loop
Iterations:   10000
Size:         [500 x 500]
Best time:    31ms
Worst time:   444ms
Average time: 68.9445ms
Median time:  68ms

Removed:      column
Method:       std::memcpy and/or for-loop
Iterations:   10000
Size:         [500 x 500]
Best time:    49ms
Worst time:   122ms
Average time: 79.3948ms
Median time:  78ms
Run Code Online (Sandbox Code Playgroud)

因此,考虑到接近的时序结果和短的实现,第一种方法似乎更合适.我在github上发布了一个最小的工作示例,以验证此测试的结果.