学习@浅墨_毛星云【OpenCV入门教程之五】 分离颜色通道&多通道图像混合

来源:互联网 发布:中国 程序员 总数 2017 编辑:程序博客网 时间:2024/05/11 14:04

本文参考@浅墨_毛星云【OpenCV入门教程之五】 分离颜色通道&多通道图像混合,

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

而为了更好的观察一些图像材料的特征,有时需要对RGB三个颜色通道的分量进行分别显示和调整。通过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容器。

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

它通过组合一些给定的单通道数组,将这些孤立的单通道数组合并成一个多通道的数组,从而创建出一个由多个单通道阵列组成的多通道阵列。它有两个基于C++的函数原型:

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]拥有一样的尺寸和深度,并且通道的数量是矩阵阵列中的通道的总数。

 
函数解析:

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

PS: Mat::at()方法,返回一个引用到指定的数组元素。注意是引用,修改其中一个另一个跟着变。

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

下面是多通道图像混合示例程序:

#include<opencv2\core\core.hpp>#include<opencv2\highgui\highgui.hpp>#include<iostream>using namespace cv;using namespace std;//首先是进行蓝色通道分离void Test1_blue(){Mat srcimg,imgROI,logoimg;vector<Mat> channels;srcimg=imread("img/3.jpg");logoimg=imread("img/logo.png",0);//把一个三通道图像转换成三个单通道图像split(srcimg,channels);//将原图的蓝色通道.at(0)引用返回给imgROI,注意是引用,若修改其中一个另一个跟着变imgROI=channels.at(0);imgROI=imgROI(Rect(100,100,logoimg.cols,logoimg.rows));//将原图的蓝色通道.at(0)的(100,100)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imgROIaddWeighted(imgROI,1.0,logoimg,0.5,0.0,imgROI);//将三个通道重新合并成一个通道merge(channels,srcimg);namedWindow("将原图的.at(0)通道混合到原图");imshow("将原图的.at(0)通道混合到原图",srcimg);}//其次是进行绿色通道分离void Test1_green(){Mat srcimg,imgROI,logoimg;vector<Mat> channels;srcimg=imread("img/3.jpg");logoimg=imread("img/logo.png",0);//把一个三通道图像转换成三个单通道图像split(srcimg,channels);//将原图的绿色通道.at(1)引用返回给imgROI,注意是引用,若修改其中一个另一个跟着变imgROI=channels.at(1);imgROI=imgROI(Rect(100,100,logoimg.cols,logoimg.rows));//将原图的绿色通道.at(1)的(100,100)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imgROIaddWeighted(imgROI,1.0,logoimg,0.5,0.0,imgROI);//将三个通道重新合并成一个通道merge(channels,srcimg);namedWindow("将原图的.at(1)通道混合到原图");imshow("将原图的.at(1)通道混合到原图",srcimg);}//再次是进行红色通道分离void Test1_red(){Mat srcimg,imgROI,logoimg;vector<Mat> channels;srcimg=imread("img/3.jpg");logoimg=imread("img/logo.png",0);//把一个三通道图像转换成三个单通道图像split(srcimg,channels);//将原图的红色通道.at(2)引用返回给imgROI,注意是引用,若修改其中一个另一个跟着变imgROI=channels.at(2);imgROI=imgROI(Rect(100,100,logoimg.cols,logoimg.rows));//将原图的红色通道.at(2)的(100,100)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imgROIaddWeighted(imgROI,1.0,logoimg,0.5,0.0,imgROI);//将三个通道重新合并成一个通道merge(channels,srcimg);namedWindow("将原图的.at(2)通道混合到原图");imshow("将原图的.at(2)通道混合到原图",srcimg);}int main(){ Test1_blue(); Test1_green(); Test1_red(); waitKey(); return 0;}

三个通道分别分离后的效果图如下:


0 0