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


    一、 split()通道分离函数

    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()显示每个元素时,最后显示出来的都是单通道的灰度图。

    上述程序运行结果如下:

     

    二、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;
    }

    若待合并通道放在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;
    }

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

    错误之处,敬请雅正!

     

     

  • 相关阅读:
    中文字符串怎么按拼音比较大小(转)
    C语言的面向对象技术(转)
    学校网又不行了哇。人人也上不了了。
    POJ2255Tree Recovery
    myeclipse无法编译java源文件(转)
    SQL语句中JOIN的用法(转)
    POJ3094Quicksum
    ssh_exchange_identification: Connection closed by remote host 问题的解决 (转)
    56视频网除了广告都看不了了
    java实现微信扫一扫详解
  • 原文地址:https://www.cnblogs.com/HL-space/p/10546605.html
Copyright © 2020-2023  润新知