参考链接: https://blog.csdn.net/guduruyu/article/details/70837779.
在图像处理中,尤其是处理多通道图像时,有时需要对各个通道进行分离,分别处理;有时还需要对分离处理后的各个通道进行合并,重新合并成一个多通道的图像。opencv中实现图像通道的分离与合并的函数分别是split()和merge()。
图像通道的分离 split()
来看程序:
#include <iostream>
#include "11_opencv_mat.h"
using namespace std;
void QuickDemo::channels_demo(Mat &image)
{
std::vector<Mat> mv;
/*
* 函数原型:
* void split(const Mat& src, Mat* mvbegin);
* 或
* void split(const Mat& mtx, vector<Mat>& mv)
*
* 将一个多通道阵列划分为几个单通道阵列。
*/
split(image,mv);
imshow("蓝色", mv[0]);
imshow("绿色", mv[1]);
imshow("红色", mv[2]);
}
运行结果如下:
可以看出来,三通道图像分离之后,变成了三个对应单通道的灰度图像。
图像通道的合并 merge()
来看程序:
#include <iostream>
#include "11_opencv_mat.h"
using namespace std;
void QuickDemo::channels_demo(Mat &image)
{
std::vector<Mat> mv;
split(image,mv);
Mat dst_B, dst_G,dst_R;
#if 1
/* 突出蓝色 */
mv[1] = 0;//相当于一张所有像素值为0的图像(纯黑色),长宽和输入image一样,只不过是单通道的。
mv[2] = 0;
/*
* 函数原型:
* void merge(const Mat* mv, size_t count, OutputArray dst)
* 或
* void merge(const vector<Mat>& mv, OutputArray dst)
* 由多个单通道阵列组成一个多通道阵列。
*
* 注意是引用类型。
*/
merge(mv, dst_B);
imshow("突出蓝色", dst_B);
#endif
#if 0
/* 突出绿色 */
mv[0] = 0;
mv[2] = 0;
merge(mv, dst_G);
imshow("突出绿色", dst_G);
#endif
#if 0
/* 突出红色 */
mv[0] = 0;
mv[1] = 0;
merge(mv, dst_R);
imshow("突出红色", dst_R);
#endif
}
分别突出不同通道的颜色,来看一下:
需要注意上面两个函数的参数是引用类型。
图像通道的合并 mixChannels()
这个函数可以输入多张图像,输出多张图像,如果是多张图像,请传入数组对象。输出时,所有的输出图像的通道都必须被分配。输出图像的大小和深度必须与输入图像相同。此外,在定义输出图像对象时,必须给它初始化,否则运行时会报异常。如下所示:
Mat dst = Mat::zeros(image.size(), image.type()); //必须初始化,否则异常
这里只输入单张图像
程序如下:
#include <iostream>
#include "11_opencv_mat.h"
using namespace std;
void QuickDemo::channels_demo(Mat &image)
{
Mat dst1 = Mat::zeros(image.size(), image.type());
Mat dst2 = Mat::zeros(image.size(), image.type());
/*
* mixChannels函数为变换图像通道提供了一种先进的机制。
* split()和merge()以及一些形式的cvtColor()是mixChannels的部分情况
*
* 函数功能:
* mixChannels主要就是把输入的矩阵(或矩阵数组)的某些通道拆分复制给对应的
* 输出矩阵(或矩阵数组)的某些通道中,其中的对应关系就由fromTo参数指定.
*
* 函数原型:
* void mixChannels(const Mat* src, int nsrc, Mat* dst, int ndst, const int* fromTo, size_t npairs)
* 或
* void mixChannels(const vector<Mat>& src, vector<Mat>& dst, const int* fromTo, int npairs)
*
* 参数:
* src - 输入图像(矩阵)。所有的图像(矩阵)必须具有相同的大小和相同的深度。
* 可以是一个,也可以是多个。如果是多个请传入数组对象。
* nsrc - 输入图像(对象)的个数,也就是参数1中的数组中元素的个数
* dst - 输出图像。所有的输出图像(矩阵)都必须被分配。它们的大小和深度必须与src[0]相同
* ndst - 输出图像(对象)的个数
* fromTo - 索引对数组,指定复制哪些通道和复制位置
* fromTo[k*2]是src中基于0的输入通道索引。fromTo[k*2+1]是dst中输出通道的索引。
* 使用连续的通道编号:第一个输入图像通道从0索引到src[0].channels()-1,
* 第二个输入图像通道从src[0].channels()索引到src[0].channels() + src[1].channels()-1,
* 以此类推。同样的方案用于输出图像通道。
* 作为特殊情况,当fromTo[k*2]为负时,对应的输出通道填充为零。
* npairs - fromTo中索引对的数量。
*/
//这里只输入单张图像
/*
下面数组的含义是
将输入图像的通道0(B分量)复制给目的图像的通道2(R分量)
将输入图像的通道1(G分量)复制给目的图像的通道1(G分量)
将输入图像的通道2(R分量)复制给目的图像的通道0(B分量)
*/
int fromTo1[] = {0,1,1,2,2,0};
int fromTo2[] = {0,2,1,1,2,0};
mixChannels(&image, 1, &dst1, 1, fromTo1, 3);
mixChannels(&image, 1, &dst2, 1, fromTo2, 3);
imshow("mixChannel_1", dst1);
imshow("mixChannel_2", dst2);
}
程序运行如下: