2015-11-02 37 views
2

我有一個RGB圖像,我想對R通道做一些修改。所以我做類似以下內容:拆分OpenCV墊沒有複製數據

Mat img; 
vector<Mat> chs; 
//.... 
split(img, chs); 
//some modification on chs[2] 
imshow("Result", img); 

但似乎OpenCV的按值(不是引用)的數據複製到chs。結果img矩陣沒有改變。 但由於內存限制,我不喜歡使用merge函數

有沒有其他方法可以在原地拆分矩陣?

+0

'split'拷貝數據,因爲它正在創建新的矩陣。我沒有看到你的記憶如何分裂而不是合併。但是,您可以直接在R通道上工作而不會分裂。這真的取決於你想要做什麼。 – Miki

回答

5

split將始終複製數據,因爲它正在創建新的矩陣。

工作的最簡單的方式,比如說,紅色通道將使用splitmerge

Mat3b img(10,10,Vec3b(1,2,3)); 

vector<Mat1b> planes; 
split(img, planes); 

// Work on red plane 
planes[2](2,3) = 5; 

merge(planes, img); 

注意merge不分配任何新的內存,所以如果你確定與split,有沒有任何理由不要致電merge


您可以直接在R通道始終工作:

Mat3b img(10,10,Vec3b(1,2,3)); 

// Work on red channel, [2] 
img(2,3)[2] = 5; 

如果你想節省split使用的內存,你可以直接在紅色通道工作,但它更繁瑣:

#include <opencv2\opencv.hpp> 
using namespace cv; 

int main() 
{ 
    Mat3b img(10,10,Vec3b(1,2,3)); 

    // Create a column matrix header with red plane unwound 
    // No copies here 
    Mat1b R = img.reshape(1, img.rows*img.cols).colRange(2, 3); 

    // Work on red plane 
    int r = 2; 
    int c = 3; 

    // You need to access by index, not by (row, col). 
    // This will also modify img 
    R(img.rows * r + c) = 5; 

    return 0; 
} 

你或許可以找到只有在一個新的矩陣複製紅色通道(避免還分配空間用於其他渠道)一個很好的妥協,然後通過複製結果返回到原始圖像:

#include <opencv2\opencv.hpp> 
using namespace cv; 

int main() 
{ 
    Mat3b img(10,10,Vec3b(1,2,3)); 

    // Allocate space only for red channel 
    Mat1b R(img.rows, img.cols); 
    for (int r=0; r<img.rows; ++r) 
     for(int c=0; c<img.cols; ++c) 
      R(r, c) = img(r, c)[2]; 

    // Work on red plane 
    R(2,3) = 5; 

    // Copy back into img 
    for (int r = 0; r<img.rows; ++r) 
     for (int c = 0; c<img.cols; ++c) 
      img(r, c)[2] = R(r,c); 


    return 0; 
} 

謝謝 to @sturkmen審查答案

+0

親愛的@Miki,請根據「存儲在B G R訂單中的頻道」修改您的答案 – sturkmen

+0

@sturkmen更正,再次感謝! – Miki

+0

@Miki,謝謝。我將致力於您提出的解決方案。 –