split()函数的C++版本有两个原型,他们分别是:


C++: void split(const Mat& src, Mat*mvbegin);//&为引用操作符
C++: void split(InputArray m,OutputArrayOfArrays mv);

两种定义用法相同,第一个参数填待分离的Mat型多通道矩阵(二维),第二个参数填分离后的Mat型单通道数组(三维)或一个vector<Mat>对象。应用实例如下:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat image = imread("colorful.jpg");
	if (image.data == 0)
	{
		cout << "读取错误" << endl;
	}
	imshow("原图", image);

	//使用Mat容器,用【】访问
	//vector<Mat> channels;
	//split(image, channels);
	//imshow("B", channels[0]);
	//imshow("G", channels[1]);
	//imshow("R", channels[2]);

	//使用Mat容器,用at访问
	vector<Mat> channels;
	split(image, channels);
	imshow("B", channels.at(0));
	imshow("G", channels.at(1));
	imshow("R", channels.at(2));

	//使用Mat数组,只能用【】访问
	//Mat aChannel[3];
	//split(image, aChannel);
	//imshow("B", aChannel[0]);
	//imshow("G", aChannel[1]);
	//imshow("R", aChannel[2]);

	waitKey();
	return 0;
}

如果将分离后的信息填入vector<Mat> channels中,最后channels对象内会有3个元素,每个元素都是大小为image.rows X image.cols的二维Mat型矩阵,依次存放着原图像对应像素位置的B、G、R分量数据。每个元素(二维矩阵)可以通过【】索引或.at()访问。

如果将分离后的信息填入Mat aChannel[3]中,最后aChannel数组内会的3个元素也都是大小为image.rows X image.cols的二维Mat型矩阵,依次存放着原图像对应像素位置的B、G、R分量数据。每个元素(二维矩阵)只能通过【】索引,不能通过.at()访问。

同时需要注意,vector<Mat> channels和Mat aChannel[3]中的元素均为二维矩阵,因此channels对象和aChannel数组都是三维的矩阵。而输出操作符“<<”仅能输出二维矩阵,所以可以用"cout<<"输出channels对象或aChannel数组中的单个元素,而channels对象和aChannel数组本身不能被输出。

因为分离出来的3个元素都是大小为image.rows X image.cols的二维Mat型矩阵,所以用imshow()显示每个元素时,最后显示出来的都是单通道的灰度图。

上述程序运行结果如下:

 

C++ Opencv split()通道分离函数  merge()通道合并函数  使用操作详解

二、merge()通道合并函数

merge()函数的C++版本有两个原型,他们分别是:

C++: void merge(const Mat* mv, size_tcount, OutputArray dst)
C++: void merge(InputArrayOfArrays mv,OutputArray dst)

若待合并通道放在Mat aChannel[ ]这样的数组里面,则使用第一种定义方法下的merge()函数。第一个参数填要传入数组的地址,可直接填入数组名aChannel;第二个参数填要合并矩阵的个数,通常情况下图像大都是单通道的灰度图或三通道的真彩图,因此要想合并后的输出dst能直接用imshow()显示的话,最好填1或3,填2也能进行数据的合并,但输出时会报错;最后一个参数填通道合并后的矩阵。

以下示例中,先用split()将图像三通道分离,将R红色分量全部置0后再将三通道用merge()融合。通道分离后,单通道矩阵存放于数组中,代码如下:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat image = imread("colorful.jpg");
	if (image.data == 0)
	{
		cout << "读取错误" << endl;
	}
	imshow("原图", image);

	//通道分离
	Mat aChannel[3];
	split(image, aChannel);
	Mat BlueChannel = aChannel[0];
	Mat GreenChannel = aChannel[1];
	Mat RedChannel = aChannel[2];

	//将R通道全部置0
	Mat newAddChannel = aChannel[2].clone();
	newAddChannel.setTo(0);
	Mat newChannels[3] = { BlueChannel , GreenChannel , newAddChannel };

	//通道合并
	Mat mergedImage;
	merge(newChannels, 3, mergedImage);

	imshow("Merged", mergedImage);
	waitKey();
	return 0;
}

C++ Opencv split()通道分离函数  merge()通道合并函数  使用操作详解

若待合并通道放在vector<Mat> channels这样的Mat型容器对象中,则使用第二种定义方法下的merge()函数。第一个参数填对象名channels,第二个参数填通道合并后的矩阵。相较第一种定义方法来说,本定义方法无需说明需合并矩阵的个数,默认合并容器对象内所有元素。因此可以通过更改容器对象内元素的个数来改变合并矩阵的个数。

以下示例中,先用split()将图像三通道分离,将B绿色分量全部置0后再将三通道用merge()融合。通道分离后,单通道矩阵存放于容器对象中,代码如下:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat image = imread("colorful.jpg");
	if (image.data == 0)
	{
		cout << "读取错误" << endl;
	}
	imshow("原图", image);

	//通道分离
	vector<Mat> channels;
	split(image, channels);
	Mat BlueChannel = channels.at(0);
	Mat GreenChannel = channels.at(1);
	Mat RedChannel = channels.at(2);

	//将B通道全部置0
	Mat newAddChannel = channels.at(0).clone();
	newAddChannel.setTo(0);
	vector<Mat> newChannels;
	newChannels.push_back(newAddChannel);
	newChannels.push_back(GreenChannel);
	newChannels.push_back(RedChannel);

	//通道合并
	Mat mergedImage;
	merge(newChannels, mergedImage);

	imshow("Merged", mergedImage);
	waitKey();
	return 0;
}

C++ Opencv split()通道分离函数  merge()通道合并函数  使用操作详解

注:无论将单通道矩阵放在数组中还是容器对象中,都要按照B、G、R的顺序存放。

错误之处,敬请雅正!

 

2022农历新年附:

时光如白驹过隙,转眼毕业参加工作一年半了,步入社会后便在生活中疲于奔命,少了当年的书生意气。博客短期没有更新的打算,也实在没有精力维护。同学们留言的问题部分我也有看到,但博客内容久远,好多细节我也实在记不大清楚了,便没有回复。其实学问就是摸着石头过河,在探索中不断遇到问题,而独立解决问题的过程就是学习提高的过程。

主目前在shopee从事机器学习平台开发工作,部门及公司都在大力招聘中。福利待遇极好,工作1075,work life balance,待遇比肩字节。有兴趣的同学可以关注我新开的内推公众号“进击的虾仔”,帮你内推进入虾厂~

江湖路远,大家后会有期~

C++ Opencv split()通道分离函数  merge()通道合并函数  使用操作详解

 

 

相关文章:

  • 2022-12-23
  • 2021-05-14
  • 2022-01-20
  • 2022-12-23
  • 2022-12-23
  • 2021-06-14
  • 2022-12-23
  • 2021-08-25
猜你喜欢
  • 2021-10-01
  • 2021-10-15
  • 2021-12-17
  • 2021-09-03
  • 2021-09-23
  • 2021-08-19
  • 2021-05-30
相关资源
相似解决方案