2015-11-02 163 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,谢谢。我将致力于您提出的解决方案。 –