C++ 拆分OpenCV Mat而不复制数据

C++ 拆分OpenCV Mat而不复制数据,c++,opencv,C++,Opencv,我有一个RGB图像,我试图在R通道上做一些修改。因此,我做了如下类似的工作: Mat img; vector<Mat> chs; //.... split(img, chs); //some modification on chs[2] imshow("Result", img); matimg; 载体chs; //.... 拆分(img、chs); //chs[2]的一些改进 imshow(“结果”,img); 但OpenCV似乎是通过值(而不是引用)将数据复制到chs。因

我有一个RGB图像,我试图在R通道上做一些修改。因此,我做了如下类似的工作:

Mat img;
vector<Mat> chs;
//.... 
split(img, chs);
//some modification on chs[2]
imshow("Result", img);
matimg;
载体chs;
//.... 
拆分(img、chs);
//chs[2]的一些改进
imshow(“结果”,img);
但OpenCV似乎是通过值(而不是引用)将数据复制到
chs
。因此,
img
矩阵没有改变但是由于内存限制,我不喜欢使用
合并
函数


是否有其他方法可以就地拆分矩阵?

split
将始终复制数据,因为它正在创建新矩阵

例如,处理红色通道的最简单方法是使用
split
merge

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

如果要保存
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;
}
#包括
使用名称空间cv;
int main()
{
Mat3b-img(10,10,Vec3b(1,2,3));
//创建红色平面展开的列矩阵标题
//这里没有副本
Mat1b R=img.重塑(1,img.行*img.列).colRange(2,3);
//在红色飞机上工作
int r=2;
int c=3;
//您需要按索引访问,而不是按(行、列)访问。
//这也将修改img
R(img.rows*R+c)=5;
返回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;
}
#包括
使用名称空间cv;
int main()
{
Mat3b-img(10,10,Vec3b(1,2,3));
//仅为红色通道分配空间
Mat1b R(img.rows,img.cols);

for(int r=0;r
split
复制数据,因为它正在创建新的矩阵。我看不出拆分而不合并对您的内存有什么影响。但是,您可以直接在r频道上工作,而不进行拆分。这完全取决于您想要做什么。亲爱的@Miki,请根据需要修改您的答案“以B G R顺序存储的频道”@Miki,谢谢。我将研究您建议的解决方案。@ma.mehralian很高兴它有所帮助。如果您发现此答案有用,请进行投票,如果此答案回答了您的问题,请最终标记为答案。否则,请让我知道为什么这无法回答问题,以便我可以寻找更好的解决方案。
#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;
}