Opencv学习笔记(八)多通道图像的分解和单通道图像的合成
2015-10-31 12:03阅读:
多通道图像的分解和单通道图像的合成
在一开始做这个程序的时候,对于图像由三通道分割成三个单通道的算法,我对于结果是这样假设的。三个通道分别是BGR,我们分出的三个单通道的色调应该是蓝色、绿色、红色。不知道是不是有和我一样想法的人,在接下来的实例之中我们便能慢慢理解为什么这种想法是不对的。
首先介绍在这个程序当中要新学习的两个函数split(分解)函数和merge(合成)函数,我们形象的称呼他们俩为冤家。
<1>split函数详解
将一个多通道数组分离成几个单通道数组。
这个split函数的C++版本有两个原型,他们分别是:
C++: void split(const Mat&
src, Mat*mvbegin);
C++: void
split(InputArray
m,OutputArrayOfArrays
mv);
关于变量介绍:
第一个参数,InputArray类型的m或者const
Mat&类型的src,填我们需要进行分离的多通道数组,这里的InputArray(多通道阵列),实际上就可以视为Mat类型
第二个参数,OutputArrayOfArrays类型的mv,填函数的输出数组或者输出的vector(向量)容器。
我们绝大多数图像是彩色的三通道图像,而颜色通道的分解实际上就是将其分解为单通道图像,下面我们来看一个简单的实例:
#include
#include
#include
'stdafx.h'
#include
'highgui.h'
#include <
Windows.h >
#include
#include
#include
#include
using namespace
std;
using namespace
cv;
void main()
{
//【0】定义相关变量
Mat
srcImage;//原图像
Mat
logoImage;//标志图
vector<</span>Mat>channels;//定义通道
Mat
imageBlueChanne;//以下分别为蓝绿红三个通道
Mat
imageGreenChanne;
Mat imageRedChanne;
//=================【颜色通道分割】=================
//【1】读入图片
logoImage =
imread('E://123.jpg',
0);
srcImage =
imread('E://2.jpg');
//【2】把一个3通道图像转换成3个单通道图像
split(srcImage, channels);//分离色彩通道
//【3】将原图的蓝色通道引用返回给imageBlueChanne
imageBlueChanne = channels.at(0);
namedWindow('蓝色单通道图像');
imshow('蓝色单通道图像',
imageBlueChanne);
imageGreenChanne = channels.at(1);
namedWindow('绿色单通道图像');
imshow('绿色单通道图像',
imageGreenChanne);
imageRedChanne = channels.at(2);
namedWindow('红色单通道图像');
imshow('红色单通道图像',
imageRedChanne);
waitKey(0);
}
显示结果



从这三张结果图像显示的来看,可以很明显看出这三张图片都是灰度图像,但是他们的灰度值不同。这是因为我们的split函数是将三通道的彩色图像分解为三个单通道图像。
下面简单介绍一下单通道和三通道:
单通道: 此通道上值为0-255。
(255为白色,0是黑色) 只能表示灰度,不能表示彩色。
三通道,在BGR
(255,255,255为白色,
0,0,0是黑色 )
可以表示彩色,
灰度也是彩色的一种。
所以我们分解出来的三个图像灰度值不同实际上就是对应他各自之前蓝绿红的像素值。
对于split函数基本上就讲这些,下面就是split的死对头merge函数的讲解。
<</span>2>merge函数详解
merge()函数的功能是split()函数的逆向操作,将多个数组组合合并成一个多通道的数组。
它通过组合一些给定的单通道数组,将这些孤立的单通道数组合并成一个多通道的数组,从而创建出一个由多个单通道阵列组成的多通道阵列。它有两个基于C++的函数原型:
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]拥有一样的尺寸和深度,并且通道的数量是矩阵阵列中的通道的总数。
下面是一个实例:
#include
#include
#include
'stdafx.h'
#include
'highgui.h'
#include <
Windows.h >
#include
#include
#include
#include
using namespace
std;
using namespace
cv;
void main()
{
//【0】定义相关变量
Mat
srcImage;//原图像
Mat
logoImage;//标志图
vector<</span>Mat>channels;//定义通道
Mat
imageBlueChanne;//以下分别为蓝绿红三个通道
Mat
imageGreenChanne;
Mat imageRedChanne;
//=================【颜色通道分割合成】=================
//【1】读入图片
logoImage =
imread('E://123.jpg',0);
srcImage =
imread('E://2.jpg');
//【2】把一个3通道图像转换成3个单通道图像
split(srcImage, channels);//分离色彩通道
//【3】将原图的蓝色通道引用返回给imageBlueChanne
imageBlueChanne = channels.at(0);
addWeighted(imageBlueChanne(Rect(0,
0, logoImage.cols, logoImage.rows)), 1,
logoImage, 0.5, 0.0,
imageBlueChanne(Rect(0, 0,
logoImage.cols, logoImage.rows)));
merge(channels, srcImage);
namedWindow('蓝色通道');
imshow('蓝色通道',
srcImage);
//【4】将原图的绿色通道引用返回给imageGreenChanne
imageGreenChanne = channels.at(1);
addWeighted(imageGreenChanne(Rect(0,
0, logoImage.cols, logoImage.rows)), 1,
logoImage, 0.5, 0.0,
imageGreenChanne(Rect(0, 0,
logoImage.cols, logoImage.rows)));
merge(channels, srcImage);
namedWindow('绿色通道');
imshow('绿色通道', srcImage);
//【5】将原图的红色通道引用返回给imageRedChanne
imageRedChanne = channels.at(2);
addWeighted(imageRedChanne(Rect(0,
0, logoImage.cols, logoImage.rows)),
0.5, logoImage, 1, 0.0,
imageRedChanne(Rect(0, 0,
logoImage.cols, logoImage.rows)));
merge(channels, srcImage);
namedWindow('红色通道');
imshow('红色通道',
srcImage);
waitKey(0);
}
显示结果
这就是我们颜色通道合成后的效果,这三张图与前面分成三个单通道的效果相对比,其结果也是吻合的
这是我们的原logo图:
原图中主要色调是黄色,而学过画画的人都知道,黄色是由蓝色和绿色调和而成,所以在merge合成图像的时候我们可以看出,蓝色和绿色通道比较明显,而红色部分的灰度值非常低,几乎看不出来。
本篇文章到这里就结束了,欢迎继续关注下一篇创建Trackbar
& 图像对比度、亮度值调整