天天看点

(OpenCV — 8)分离颜色通道、多通道图像混合

使用 addWeighted 函数进行图像混合操作,以及如何将 ROI 和 addWeighted 函数结合起来 , 对指定区域进行图像混合操作。

参考:​​(OpenCV — 7)ROI 区域图像叠加&图像混合​​ 而为了更好地观察一些图像材料的特征,有时需要对 RGB 三个颜色通道的分量进行分别显示和调整。通过 OpenCV 的 split 和 merge 方法可以很方便地达到目的 。

通道分离: split()函数

split 函数用于将一个 多通道数组分离成几个单通道数组。这里的 array 按语境翻译为数组或者阵列。

这个 split 函数的 C++版本有两个原型 , 分别是 :

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

变量介绍如下 :

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

split 函数分割多通道数组转换成独立的单通道数组 , 公式如下 :

(OpenCV — 8)分离颜色通道、多通道图像混合

实例代码:

//【0】定义相关变量
    Mat srcImage;
    Mat logoImage;
    vector<Mat> channels;
    Mat  imageBlueChannel;

    //=================【蓝色通道部分】=================
    //  描述:多通道混合-蓝色分量部分
    //============================================

    // 【1】读入图片
    logoImage= imread("D:\\QT\\project\\opencv_qtcreaor\\dota_logo_5_3.jpg",0);
    srcImage= imread("D:\\QT\\project\\opencv_qtcreaor\\dota_jugg_5_3.jpg");

    if( !logoImage.data ) { printf("Oh,no,读取logoImage错误~! \n"); return false; }
    if( !srcImage.data ) { printf("Oh,no,读取srcImage错误~! \n"); return false; }

    //【2】把一个3通道图像转换成3个单通道图像
    split(srcImage,channels);//分离色彩通道

    //【3】将原图的蓝色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变
    imageBlueChannel= channels.at(0);
    //【4】将原图的蓝色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageBlueChannel中
    addWeighted(imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,
        logoImage,0.5,0,imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)));

    //【5】将三个单通道重新合并成一个三通道
    merge(channels,srcImage);

    //【6】显示效果图
    namedWindow(" <1>游戏原画+logo蓝色通道");
    imshow(" <1>游戏原画+logo蓝色通道",srcImage);      

通道合并: merge()函数

merge()函数是 split()函数 的逆 向操作一将多 个数组合并成一个 多通道的数组 。 它通过组合一些给定 的单通道数组 , 将这些孤立的单通道数组合并成一个多通道的数组,从而创建出 一个由多个单通道阵列组成的 多通道阵列 。 它有两个基于 C++的 函数原型如下 。

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

变量介绍如下 。

第一个参数 , mv 。 填需要被合并 的输入矩阵或 vector 容器的阵列,这个mv 参数中所有 的矩阵必须有着一样的尺寸和深度。

第二个参数 , count。当 mv 为一个空白 的 C 数组时 , 代表输入矩阵的个数,这个参数显然必须大于1。

第三个参数 , dst 。 即输出矩阵 , 和 mv[0]拥有一样 的尺寸和深度 , 并且通道的数益是矩阵阵列中的通道的总数 。

函数解析如下 。

merge 函数的功能是将一些数组合并成一个多通道的数组。关千组合的细 节 ,输出矩阵中 的每个元素都将是输出数组的串接。其中, 第 i 个输入数组的元素被视为 mv[i]。C 一般用其中的 Mat::at()方法对某个通道进行存取 ,也就是这样用 :

channels.a t(0)      

这里的 Mat: :at()方法返回一个引用到指定 的数组元素 。 注意是引用,相当于两者等价,也就是修改其中一个 , 另 一个也会随之改变。

依然是一个示例 , 如下 。

vector<Mat> channels;
Mat imageBlueChannel;
Mat imageGreenChannel;
Mat imageRedChannel ;
srcimage4 = imread("dota.jpg" );
//把一个 3 通道 图像转换成 3 个单通道图像
split(srcimage4, channels);//分离色彩通道
imageBlueChannel = channels.at(0);
imageGreenChannel = channels.at(1);
imageRedChannel = channels.at(2);      

上面的代码先做了 相关的类型声明 , 然后把载入 的 3 通道图像转换成 3 个单通道图像,放到 vector<Mat>类型的 channels 中,接着进行引用赋值 。

根据 OpenCV 的 BGR 色彩空间 (Bule 、 Green 、 Red 、蓝绿红),其中 channels.at(0)就表示引用取出 channels 中的蓝色分量 , channels.at(1)就表示引用取出 channels中的绿色分量, channels.at(2)就表示引用取出 channels 中的红色分量 。

一对做相反操作的 split()函数和 merge()函数的用法就是这些。另外提一点 ,如果我们需要从多通道数组中提取出特定的单通道数组,或者说实现一些复杂的通道组合,可以使用 mixChannels()函数 。

上面只是实现单一颜色混合,下面实现BGR三色混合

Mat srcImage;
    Mat logoImage;
    vector<Mat> channels;
    Mat  imageBlueChannel_B;
    Mat  imageBlueChannel_G;
    Mat  imageBlueChannel_R;

    logoImage= imread("D:\\QT\\project\\opencv_qtcreaor\\dota_logo_5_3.jpg",0);
    srcImage= imread("D:\\QT\\project\\opencv_qtcreaor\\dota_jugg_5_3.jpg");

    if( !logoImage.data ) { printf("Oh,no,读取logoImage错误~! \n"); return false; }
    if( !srcImage.data ) { printf("Oh,no,读取srcImage错误~! \n"); return false; }

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

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

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

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

    merge(channels,srcImage);

    namedWindow("效果图");
    imshow("效果图",srcImage);      

运行结果:

(OpenCV — 8)分离颜色通道、多通道图像混合

原理图:

(OpenCV — 8)分离颜色通道、多通道图像混合

继续阅读