今天呢,我们一起来学习彩色图像的颜色通道分离与多通道图像混合,一般情况下,我们大多数看到的图像都是基于RGB颜色通道的图像,因此要实现颜色通道的分离,即要将R、G、B三个通道分离,而多通道图像混合,即将R、G、B三个通道的图像进行混合起来,重新组成一幅彩色图像。

实现的话,我们可以通过OpenCV的split函数与merge函数可以很方便的达到目的。

接下来我们正式进入颜色通道分离与多通道图像混合的内容

一、颜色通道的分离与合并

1、split()函数

功能:将一个多通道的数组分离成几个单通道的数组。

函数原型:

void split(const Mat& src, Mat*mvbegin);
void split(InputArray m,OutputArrayOfArrays mv);
  • 第一个参数,InputArray类型的m或者const Mat&类型的src,填我们需要进行分离的多通道数组。
  • 第二个参数,OutputArrayOfArrays类型的mv,填函数的输出数组或者输出的vector容器。

split函数分割多通道数组转换成独立的单通道数组,按公式来看就是这样:

分离彩色图像的实例:

#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;

int main() 
{
    Mat srcImage = imread("lena.png",
        IMREAD_COLOR);

    if (srcImage.empty())
    {
        printf("image error!\n");
        return 0;
    }
    std::vector<Mat> channels;
    Mat aChannels[3];
    
    //利用数组分离
    split(srcImage, aChannels);
    //利用vector对象分离
    split(srcImage, channels); 

    // 显示原图
    namedWindow("src");
    imshow("src", srcImage);

    namedWindow("B");
    namedWindow("G");
    namedWindow("R");
    imshow("B", aChannels[0]);
    imshow("G", aChannels[1]);
    imshow("R", aChannels[2]);

    waitKey(0);
    return 0;
}

原图

分离通道的三个图

2、merge()函数

功能:merge()函数的功能是split()函数的逆向操作,将多个数组组合合并成一个多通道的数组。

函数原型:

void merge(const Mat* mv, size_tcount, OutputArray dst)
void merge(InputArrayOfArrays mv,OutputArray dst)
  • 第一个参数,mv,填需要被合并的输入矩阵或vector容器的阵列,这个mv参数中所有的矩阵必须有着一样的尺寸和深度。
  • 第二个参数,count,当mv为一个空白的C数组时,代表输入矩阵的个数,这个参数显然必须大于1.
  • 第三个参数,dst,即输出矩阵,和mv[0]拥有一样的尺寸和深度,并且通道的数量是矩阵阵列中的通道的总数。

图像通道的分离与合并的实例:

#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;

// 图像通道的分离与合并
///@srcImage const Mat 原始图像
///@logoImage const Mat 融合图像
///@outputImage Mat 输出图像
///@splitChannel int 图像的某个通道(0--2)
void SplitMerge(const Mat &srcImage, 
    const Mat &logoImage, 
    Mat &outputImage, 
    int splitChannel)
{
    vector<Mat>channels;
    //把一个3通道图像转换成3个单通道图像
    //分离色彩通道
    split(srcImage, channels);

    // 得到其中一个通道的图像
    Mat ChannelImage = 
        channels.at(splitChannel);

    //将原图的蓝色通道的(50,50)坐标处
    // 右下方的一块区域和logo图进行加权操作,
    // 将得到的混合结果存到imageBlueChannel中
    addWeighted(ChannelImage(
        Rect(50, 50, logoImage.cols, 
            logoImage.rows)), 1.0,logoImage, 
        0.9, 0, ChannelImage(Rect(50, 50, 
            logoImage.cols, logoImage.rows)));

    // 将三个单通道重新合并成一个三通道
    merge(channels, outputImage);
}

int main() 
{
    //【0】定义相关变量
    Mat srcImage;
    Mat logoImage;

    //读入图片
    logoImage = imread("2.png", 0);
    srcImage = imread("lena.png");

    if (!logoImage.data) 
    { 
        printf("image error!\n"); 
        return false; 
    }
    if (!srcImage.data) 
    { 
        printf("image error!\n"); 
        return false; 
    }
    Mat outputImage1, 
        outputImage2, 
        outputImage3;

    SplitMerge(srcImage, logoImage, 
        outputImage1, 0);
    // 显示效果图
    namedWindow("B");
    imshow("B", outputImage1);

    SplitMerge(srcImage, logoImage, 
        outputImage2, 1);
    // 显示效果图
    namedWindow("G");
    imshow("G", outputImage2);

    SplitMerge(srcImage, logoImage, 
        outputImage3, 2);
    // 显示效果图
    namedWindow("R");
    imshow("R", outputImage3);
    
    waitKey(0);
    return 0;
}

运行结果:

 

图像通道的分离与合并