2015-04-17 62 views
3

刪除行或山坳的最佳方式。假設我有一個墊目標,例如如下:什麼是從簡歷墊

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]; 

,我想從它說第二排不得不刪除行墊這樣的:

[75, 97, 66, 95, 15, 22; 
21, 69, 88, 72, 64, 1; 
26, 47, 26, 40, 95, 24; 
70, 37, 9, 83, 16, 83] 

或刪除一個山坳說西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] 

什麼是做到這一點的最快方法?我可以將矩陣分解爲ROI,然後將它們合併到一起,但有沒有更好的方法?

回答

1

刪除行N:

memmove(mat + N * x_size, 
     mat + (N + 1) * x_size, 
     x_size * sizeof(int) * (y_size - N - 1)); 

刪除COL N:

for(int y = 0; y < y_size; y++) 
    memmove(mat + N + y * (x_size - 1), 
    mat + N + y * x_size + 1, 
    (x_size - 1) * sizeof(int)); 

ATTN:第二代碼(刪除列)讀出後面矩陣額外的行。在大多數情況下,這是可以接受的,並且算法保持簡單。如果需要,修改代碼以將正確尺寸傳遞到最後一個移除。

5

我測試了兩種方式:

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

用於第一方法的時序測試表明:

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 

而對於第二種方法:

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 

因此,考慮接近時限結果和短實施方式中,第一種方法似乎更適合的。 我發佈了minimal working example on github以驗證此測試的結果。