若要对Opencv中(BGR)颜色通道进行单一处理,那必然会涉及到通道分离(split)与合并(merge)。那么本篇博客笔者记录了两个方法的使用方法和案例。案例来源于《Opencv3编程入门学习》。

0. 环境

系统:Windows 10
平台:VS 2013
OpenCV版本:Opencv 3.0

1. split()通道分离函数

void split(const Mat& src, Mat* mvbegin);
void split(InputArray m, OutputArrayOfArrays mv);

第一个参数:即是原图像;
第二个参数:mvbegin,是一个Mat类型的一个数组,通常这个数组都是[3]的大小,这个数组大小表示的是通道个数,mvbegin就是指的将原图像按照(BGR)通道顺序逐一进行存储的单通道数组。通常可以用vector mvbegin的方式进行定义。

2. merge()通道合并函数

void merge(const Mat* mv, size_tcount, OutputArray dst);
void merge(InputArrayOfArrays mv, OutputArray dst);

第一个参数:mv,单通道图像数组,在split函数的第二个参数有解释;
第二个参数:size_tcoutn,当mv为一个空白的C数组时,代表输入矩阵的个数,参数要大于1;
第三个参数:dst,合并后的图像。

3. 使用案例

#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
//#include <opencv2\opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;

bool MultiChannelBlending()
{
    Mat srcImage;
    Mat logoImage;
    vector<Mat> channels;
    Mat imageBlueChannel, imageGreenChannel, imageRedChannel;

    //channels.resize(3);

    //=====================蓝色通道=====================
    //描述:多通道混合-蓝色分量部分
    //==================================================
    srcImage = imread("dota_jugg.jpg");
    logoImage = imread("dota_logo.jpg", 0);

    if (!srcImage.data){ printf("读取srcImage图像错误!\n"); return false; }
    if (!logoImage.data){ printf("读取logoImage图像错误!\n"); return false; }

    split(srcImage, channels);//分离色彩通道

    imageBlueChannel = channels.at(0);
    addWeighted(imageBlueChannel(Rect(500, 250, logoImage.cols, logoImage.rows)),
        1.0,
        logoImage,
        0.5,
        0,
        imageBlueChannel(Rect(500, 250, logoImage.cols, logoImage.rows)));

    merge(channels, srcImage);//合并色彩通道

    namedWindow("【多通道混合-蓝】");
    imshow("【多通道混合-蓝】", srcImage);

    //=====================绿色通道=====================
    //描述:多通道混合-绿色分量部分
    //==================================================
    srcImage = imread("dota_jugg.jpg");
    logoImage = imread("dota_logo.jpg", 0);

    if (!srcImage.data){ printf("读取srcImage图像错误!\n"); return false; }
    if (!logoImage.data){ printf("读取logoImage图像错误!\n"); return false; }

    split(srcImage, channels);//分离色彩通道

    imageGreenChannel = channels.at(1);

    addWeighted(imageGreenChannel(Rect(500, 250, logoImage.cols, logoImage.rows)),
        1.0,
        logoImage,
        0.5,
        0,
        imageGreenChannel(Rect(500, 250, logoImage.cols, logoImage.rows)));

    merge(channels, srcImage);

    namedWindow("【多通道混合-绿】");
    imshow("【多通道混合-绿】", srcImage);


    //=====================红色通道=====================
    //描述:多通道混合-红色分量部分
    //==================================================
    srcImage = imread("dota_jugg.jpg");
    logoImage = imread("dota_logo.jpg", 0);

    if (!srcImage.data){ printf("读取srcImage图像错误!\n"); return false; }
    if (!logoImage.data){ printf("读取logoImage图像错误!\n"); return false; }

    split(srcImage, channels);//分离色彩通道

    imageRedChannel = channels.at(2);

    addWeighted(imageRedChannel(Rect(500, 250, logoImage.cols, logoImage.rows)),
        1.0,
        logoImage,
        0.5,
        0,
        imageRedChannel(Rect(500, 250, logoImage.cols, logoImage.rows)));
    merge(channels, srcImage);

    namedWindow("【多通道混合-红】");
    imshow("【多通道混合-红】", srcImage);

    return true;
}

void main()
{
    system("color 9F");//控制台背景色设置

    if (MultiChannelBlending())
    {
        cout << endl << "\n运行成功,得出了需要的图像!";
    }

    waitKey(0);
}

4. 效果

opencv 三通道转为单通道 opencv通道合并分离_opencv

5. 注意

在使用split函数过程中,如果是Debug版本运行极有可能碰到“0xC0000005内存访问冲突问题”,若遇到可参考笔者上篇blog进行解决。