一、 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++ Opencv split()通道分离函数 merge()通道合并函数 使用操作详解的更多相关文章

  1. c++排序二叉树的出现的私有函数讨论,以及二叉树的删除操作详解

    c++排序二叉树的出现的私有函数讨论, 以及二叉树的删除操作详解 标签(空格分隔): c++ 前言 我在c++学习的过程中, 最近打了一个排序二叉树的题目,题目中出现了私有函数成员,当时没有理解清楚这 ...

  2. C++学习45 流成员函数put输出单个字符 cin输入流详解 get()函数读入一个字符

    在程序中一般用cout和插入运算符“<<”实现输出,cout流在内存中有相应的缓冲区.有时用户还有特殊的输出要求,例如只输出一个字符.ostream类除了提供上面介绍过的用于格式控制的成员 ...

  3. Python趣味入门9:函数是你走过的套路,详解函数、调用、参数及返回值

    1.概念 琼恩·雪诺当上守夜人的司令后,为训练士兵对付僵尸兵团,把成功斩杀僵尸的一系列动作编排成了"葵花宝典剑法",这就是函数.相似,在计算机世界,一系列前后连续的计算机语句组合在 ...

  4. Opencv YAML和XML格式文件操作详解

    本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/47660943 本文参考Opencv 2 ...

  5. javascript函数setInterval和setTimeout的使用区别详解

    setTimeout和setInterval的使用 这两个方法都可以用来实现在一个固定时间段之后去执行JavaScript.不过两者各有各的应用场景. 方 法 实际上,setTimeout和setIn ...

  6. JQuery的ready函数与JS的onload的区别详解

    JQuery的ready函数与JS的onload的区别:1.执行时间window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行.$(document).ready()是DOM结构绘制 ...

  7. Python open()函数文件打开、读、写操作详解

    一.Python open()函数文件打开操作 打开文件会用到open函数,标准的python打开文件语法如下:open(name[,mode[,buffering]])open函数的文件名是必须的, ...

  8. JQuery(一)---- JQ的选择器,属性,节点,样式,函数等操作详解

    JQuery的基本概念 JQuery是一个javascript库,JQuery凭借着简洁的语法和跨平台的兼容性,极大的简化了js操作DOM.处理事件.执行动画等操作.JQuery强调的理念是:'wri ...

  9. js函数在frame中的相互调用详解

    原文章:http://www.jb51.net/article/47557.htm   一个HTML页面可以有一个或多个子框架,这些子框架以<iframe>来标记,用来显示一个独立的HTM ...

随机推荐

  1. Linux驱动之USB总线驱动程序框架简析

    通用串行总线(USB)是主机和外围设备之间的一种连接.USB总线规范有1.1版和2.0版,当然现在已经有了3.0版本.USB1.1支持两种传输速度:低速为1.5Mbps,高速为12Mbps.USB2. ...

  2. Python json.dumps 自定义序列化操作

    def login_ajax(request): if request.method == "GET": return render(request, 'login_ajax.ht ...

  3. pd16.5增加字段备注

    EXEC sp_addextendedproperty 'MS_Description', %.q:COLNNAME%, 'user', dbo, 'table', %TABLE%, 'column' ...

  4. Unity3D 中 脚本(MonoBehaviour) 生命周期WaitForEndOfFrame需要注意的地方

    首先看看MonoBehaviour的生命周期 先上个图(来源 http://blog.csdn.net/qitian67/article/details/18516503): 1.Awake 和 St ...

  5. python 模块——os 模块

    os 模块--操作系统的各种接口 常用函数: os.path os.path.join(path,*paths) (常用,设置文件路径)将一个或者多个路径连接起来. PATH_TO_TEST_IMAG ...

  6. list常用方法

    1.切片: ①.顾头不顾尾,从头开始取,但不包括最后一个. ②.从左向右数为正,从零开始,从右开始为负,从-1开始 如: names=['1','2','3'] ames[-1]与names[2]效果 ...

  7. OvO

    OvO 知乎 网易云 图书馆 B站 小众软件 360极速浏览器下载 开源下载工具 下载地址1 下载地址2 下载地址3

  8. org.apache.commons.httpclient工具类

    import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; import org.apache.commons.httpcl ...

  9. 关于python的展望

    在未接触这门课程以前,我完全对编程一类的操作毫无兴趣.但在短短的两星期时间里,我改变了想法,原因有二.其一是老师幽默,其二是课程实用性高.我希望课程以后可以继续沿用现在由浅入深,给予足够提示的方式,引 ...

  10. ORA-01017 invalid username/password;logon denied

    一般来说这个是密码丢失问题,但也许是因为你的用户名或密码写错啦,所以先检查下用户名和密码,觉得没错的话就去查看 sqlnet.ora (在 安装盘下面的:oracle\product\11.2.0\d ...