拆分OpenCV Mat而不复制数据

Split OpenCV Mat without copying the data

本文关键字:复制 数据 OpenCV Mat 拆分      更新时间:2023-10-16

我有一个RGB图像,我试图对R通道进行一些修改。所以我做了类似于以下的事情:

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

但OpenCV似乎是通过值(而不是通过引用)将数据复制到chs。因此CCD_ 2矩阵没有改变但由于内存限制,我不喜欢使用merge函数

有没有其他选择可以将矩阵拆分到位?

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 <opencv2opencv.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 <opencv2opencv.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;
}

感谢@sturkmen审阅答案