美文网首页
「OpenCV」 分离颜色通道&多通道图像混合

「OpenCV」 分离颜色通道&多通道图像混合

作者: 叨码 | 来源:发表于2020-05-22 14:54 被阅读0次

    文中内容大多来自大神浅墨_毛星云 所著【OpenCV3编程入门】,在此基础上加入了自己的理解和补充内容。

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

    而为了更好的观察一些图像材料的特征,有时需要对RGB三个颜色通道的分量进行分别显示和调整。通过OpenCV的splitmerge方法可以很方便的达到目的。
    示例代码:

    /**
     * ROI region of interest 感兴趣区域
     * 图像混合操作
     */
    #include <iostream>
    #include <opencv2/opencv.hpp>
    #include <opencv2/highgui/highgui.hpp>
    
    using namespace cv;
    using namespace std;
    //函数声明
    void MultiChannelBlending() ;
    int main() {
        MultiChannelBlending();
        waitKey(0);
        return 0;
    }
    
    
    /***
     * 多通道混合的实现函数
     */
    void MultiChannelBlending() {
        //定义相关变量
        Mat srcImage;
        Mat logoImage;
        vector<Mat> channels;
        Mat imageBlueChannel;
        //-----------【蓝色通道部分】----------
        // 多通道混合--蓝色分量部分
        //-----------------------------------
        //1.载入图片
        //参数 0        IMREAD_GRAYSCALE = 0,  // If set, always convert image to the single channel grayscale image (codec internal conversion).
        logoImage = imread("/Users/ing/Pictures/img/OnePiece.png", 0);
        srcImage = imread("/Users/ing/Pictures/32.png");
        if(!logoImage.data){
            printf("读取logoImage错误\n");
            return;
        }
        if(!srcImage.data){
            printf("读取srcImage错误\n");
            return;
        }
        //2.把一个三通道图像转换成3个单通道图像
        split(srcImage,channels);//分离色彩通道
        //3.将原图的蓝色通道引用返回给imageBlueChannel ,注意这里是引用,相当于两者等价,修改其一另一个也会跟着变
        //三通道的颜色顺序BRG
        imageBlueChannel = channels.at(0);
        //4.将原图的蓝色通道的(100,100)坐标处的一块区域和logo图进行加权操作,将得到的混合结果存到imageBlueChannel中
        addWeighted(imageBlueChannel(Rect(100,100,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0,imageBlueChannel(Rect(100,100,logoImage.cols,logoImage.rows)));
        //5.将三个单通道重新合并成一个三通道
        merge(channels,srcImage);
        //6.显示效果图
        namedWindow("原画+logo蓝色通道");
        imshow("原画+logo蓝色通道",srcImage);
    
        //-----------【绿色通道部分】----------
        // 多通道混合--绿色分量部分
        //-----------------------------------
        //0.定义相关变量
        Mat imageGreenChannel;
        //1.重新载入图像
        logoImage = imread("/Users/ing/Pictures/img/OnePiece.png", 0);
        srcImage = imread("/Users/ing/Pictures/32.png");
        if(!logoImage.data){
            printf("读取logoImage错误\n");
            return;
        }
        if(!srcImage.data){
            printf("读取srcImage错误\n");
            return;
        }
        //2.将一个三通道图像转换成三个单通道的图像
        split(srcImage,channels);//分离色彩通道
        //3.将原图的绿色通道的引用返回给imageGreenChannel
        imageGreenChannel = channels.at(1);
        //4.将原图的绿色通道的(100,100)坐标处的一块区域和logo图进行加权操作,将得到的混合结果存到imageGreenChannel中
        addWeighted(imageGreenChannel(Rect(200,200,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.0,imageGreenChannel(Rect(200,200,logoImage
        .cols,logoImage.rows)));
        //5.将三个独立的单通道重新合并成一个三通道
        merge(channels,srcImage);
        //6.显示效果图
        namedWindow("原画+logo绿色通道");
        imshow("原画+logo绿色通道",srcImage);
    
        //-----------【红色通道部分】----------
        // 多通道混合--红色分量部分
        //-----------------------------------
        //0.定义变量
        Mat imageRedChannel;
        //1.重新载入图像
        logoImage = imread("/Users/ing/Pictures/img/OnePiece.png", 0);
        srcImage = imread("/Users/ing/Pictures/32.png");
        //2.将一个三通道图像转换成三个单通道图像
        split(srcImage,channels);
        //3.将原图的红色通道的引用返回给imageRedChannel
        imageRedChannel = channels.at(2);
        //4.将原图的红色通道的(100,100)坐标点出的一块区域和logo图像进行加权操作,将得到的混合结果存到imageRedChannel中
        addWeighted(imageRedChannel(Rect(100,100,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.0,imageRedChannel(Rect(100,100,logoImage.cols,logoImage.rows)));
        //5.将三个独立的单通道重新合并成一个三通道
        merge(channels,srcImage);
        //6.显示效果图
        namedWindow("原画+logo红色通道");
        imshow("原画+logo绿色通道",srcImage);
    
    }
    

    对应的运行结果:


    blue_channel.png
    green_channel.png
    red_channel.png

    补充

    1.split() 函数:将一个多通道数组分离成几个单通道数组。
    函数原型

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

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

    2.merge() 函数的功能是split()函数的逆向操作,将多个数组组合合并成一个多通道的数组。
    它通过组合一些给定的单通道数组,将这些孤立的单通道数组合并成一个多通道的数组,从而创建出一个由多个单通道阵列组成的多通道阵列。
    函数原型

    C++: void merge(const Mat* mv, size_tcount, OutputArray dst)
    C++: void merge(InputArrayOfArrays mv,OutputArray dst)
    

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

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

    相关文章

      网友评论

          本文标题:「OpenCV」 分离颜色通道&多通道图像混合

          本文链接:https://www.haomeiwen.com/subject/uvmqahtx.html