在OpenCV中访问每个独立的通道

33

我有一张三通道的图像(img),还有一张单通道的图像(ch1)。

    Mat img(5,5,CV_64FC3);
    Mat ch1 (5,5,CV_64FC1);
有没有高效的方法(不使用 for 循环)将 img 的第一个通道复制到 ch1 中?
5个回答

54

实际上,如果你只想复制其中一个通道或将彩色图像拆分成3个不同的通道,CvSplit() 更为合适(我的意思是使用简单)。

Mat img(5,5,CV_64FC3);
Mat ch1, ch2, ch3;
// "channels" is a vector of 3 Mat arrays:
vector<Mat> channels(3);
// split img:
split(img, channels);
// get the channels (dont forget they follow BGR order in OpenCV)
ch1 = channels[0];
ch2 = channels[1];
ch3 = channels[2];

15

有一个名为cvMixChannels的函数。你需要查看源代码来了解其实现方式,但我敢打赌它一定被优化得很好。


谢谢Jacek。看来我可以使用mixChannels完成我的任务。 - iampat
谢谢您的回答。我尝试了split和mixChannels两种方法,但它们都报错了!您有什么想法,可能是什么原因呢? - iampat
我在类型上犯了错误。我使用了CV_64FC1而不是CV_32FC1。谢谢你的帮助。 - iampat
1
尽可能使用C++ API(C API即将被弃用):因此应使用cv :: mixChannels,而不是cvMixChannels。同样适用于cvSplit,应改用core.hpp中的cv :: split。 - Ela782

14
你可以使用split函数,然后将零放到你想要忽略的通道中。这将导致只显示三个通道中的一个。请见下文。
例如:
Mat img, chans[3]; 
img = imread(.....);  //make sure its loaded with an image

//split the channels in order to manipulate them
split(img, chans);

//by default opencv put channels in BGR order , so in your situation you want to copy the first channel which is blue. Set green and red channels elements to zero.
chans[1]=Mat::zeros(img.rows, img.cols, CV_8UC1); // green channel is set to 0
chans[2]=Mat::zeros(img.rows, img.cols, CV_8UC1);// red channel is set to 0

//then merge them back
merge(chans, 3, img);

//display 
imshow("BLUE CHAN", img);
cvWaitKey();

4
这是一个更好的答案,它在得票最高的答案(不是被接受的答案)的基础上进行了改进,通过加入补充函数cv::merge()来改进它(不过也许仅编辑那个其他答案会更好,但是该用户缺乏声望积分?)。 - Lucas Walter

12

您可以访问特定的频道,它比 split 操作更快。

Mat img(5,5,CV_64FC3);
Mat ch1;
int channelIdx = 0;
extractChannel(img, ch1, channelIdx); // extract specific channel

// or extract them all
vector<Mat> channels(3);
split(img, channels);
cout << channels[0].size() << endl;

2
如果您有一个带有3个通道的RGB图像,更简单的方法是使用cvSplit(),如果我没记错的话,您需要配置的内容较少...(我认为它也被优化得很好)。
对于“更难”的任务,我会使用cvMixChannel()...:p(我知道我很懒)。 这里是cvSplit()的文档

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接