我有一个 RGB 图像,我试图对 R channel 进行一些修改。所以我做了类似以下的事情:
Mat img;
vector<Mat> chs;
//....
split(img, chs);
//some modification on chs[2]
imshow("Result", img);
但似乎 OpenCV 将数据按值(而不是按引用)复制到 chs
。结果 img
矩阵没有改变。 但由于内存限制,我不喜欢使用merge
函数。
是否有其他方法可以就地拆分矩阵?
最佳答案
split
将始终复制数据,因为它正在创建新矩阵。
处理红色 channel 的最简单方法是使用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);
请注意 merge
不会分配任何新内存,因此如果您对 split
没意见,就没有任何理由不调用 >合并
。
您始终可以直接在 R channel 上工作:
Mat3b img(10,10,Vec3b(1,2,3));
// Work on red channel, [2]
img(2,3)[2] = 5;
如果想节省split
使用的内存,可以直接在红色 channel 上操作,但是比较麻烦:
#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;
}
您可以通过仅在新矩阵中复制红色 channel (避免为其他 channel 分配空间),然后将结果复制回原始图像来找到一个很好的折衷方案:
#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;
}
感谢@sturkmen 审阅答案
关于c++ - 在不复制数据的情况下拆分 OpenCV Mat,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33480983/