您的位置:首页 > 运维架构

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

2017-05-11 18:42 681 查看
本文参考@浅墨_毛星云【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图进行加权操作,将得到的混合结果存到imgROI
addWeighted(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图进行加权操作,将得到的混合结果存到imgROI
addWeighted(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图进行加权操作,将得到的混合结果存到imgROI
addWeighted(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;
}

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





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: