一、 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. chip8模拟器的python3实现-2-指令介绍

    CHIP指令表 CHIP-8有35个指令,都为两字节长,以大端方式存储.指令表的指令格式规定如下: NNN:地址 NN:8位常量 N:4位常量 V:寄存器 X和Y:4位,标识寄存器 PC:程序计数器 ...

  2. spring mvc 500错误Allocate exception for servlet AppService javax.naming.NamingException: Cannot create resource instance 竟是@Resource的原因

    头几天已经测试的完毕了,换了个目录出现这个问题 严重: Allocate exception for servlet AppService javax.naming.NamingException: ...

  3. swoole和workerman

    作者:韩天峰链接:https://www.zhihu.com/question/47994137/answer/131700752来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...

  4. python基础之Day14

    一.生成器 1.什么是生成器 在函数内但凡出现yield关键字,再调用函数就不会执行函数体代码,会返回一个值,该值称之为生成器,生成器本质就是迭代器 2.为什么要有生成器 生成器是一种自定义迭代器的方 ...

  5. 电商项目-商品表(spu)、规格表(sku)设计

    之前在工作中,需要实现商品规格功能,做了很长一段时间,现在回过头来整理下设计思路. sku,spu概念: SPU = Standard Product Unit (标准化产品单元),SPU是商品信息聚 ...

  6. 博客六--Tensorflow卷积神经网络的自主搭建

    本人较懒也很忙,所以就不重复工作.连接我的开源中国博客查询:https://my.oschina.net/u/3770644/blog/3042523

  7. HTML元素的分类

    HTML元素的分类 EC前端 - HTML教程 块元素 div:无语义,常用于布局 aside:表示article元素的内容之外的与article元素的内容相关内容 figure:表示一段独立的流内容 ...

  8. Netsharp系列文章目录结构

    作者:秋时  转载须说明出处  Netsharp交流群:338963050(请有详细的请求说明) ->. 总体介绍 Netsharp总体介绍 一. Netsharp快速入门系列 Netsharp ...

  9. BaseDao.util(虎大将军)

    package logistics.util; import java.sql.Connection; import java.sql.PreparedStatement; import java.s ...

  10. eclipse配置逆向工程

    eclipse单行注释:ctrl + shfit + c   或者   Ctrl+/:    添加//注释 快速查找某个类:Ctrl+Shift +T   查找这个类的子类是ctrl+t eclips ...