在图像颜色模型中不同的分量存放在不同的通道中,如果我们只需要颜色模型的某一个分量,例如只需要处理RGB图像中的红色通道,可以将红色通道从三通道的数据中分离出来再进行处理,这种方式可以减少数据所占据的内存,加快程序的运行速度。同时,当我们分别处理完多个通道后,需要将所有通道合并在一起重新生成RGB图像。针对图像多通道的分离与混合,OpenCV 4中提供了split()函数和merge()函数用于解决这些需求。
opencv知识点:
OpenCV 4中针对多通道分离函数split()有两种重载原型,在代码清单3-4中给出了这两种函数原型。
void cv::split(const Mat & src,
Mat * mvbegin
)
void cv::split(InputArray m,
OutputArrayOfArrays mv
)
src:待分离的多通道图像。
mvbegin:分离后的单通道图像,为数组形式,数组大小需要与图像的通道数相同
m:待分离的多通道图像
mv:分离后的单通道图像,为向量vector形式
该函数主要是用于将多通道的图像分离成若干单通道的图像,两个函数原型中不同之处在于前者第二个参数输入的是Mat类型的数组,其数组的长度需要与多通道图像的通道数相等并且提前定义;第二种函数原型的第二个参数输入的是一个vector容器,不需要知道多通道图像的通道数。两个函数原型虽然输入参数的类型不同,但是通道分离的原理是相同的,可以用公式(3.4)表示。
OpenCV 4中针对多通道合并函数merge()也有两种重载原型,在代码清单3-5中给出了两种原型。多通道合并函数merge()
OpenCV 4中针对多通道合并函数merge()也有两种重载原型,在代码清单3-5中给出了两种原型。
void cv::merge(const Mat * mv,
size_t count,
OutputArray dst
)
void cv::merge(InputArrayOfArrays mv,
OutputArray dst
)
mv:需要合并的图像数组,其中每个图像必须拥有相同的尺寸和数据类型。
count:输入的图像数组的长度,其数值必须大于0.
mv:需要合并的图像向量vector,其中每个图像必须拥有相同的尺寸和数据类型。
dst:合并后输出的图像,与mv[0]具有相同的尺寸和数据类型,通道数等于所有输入图像的通道数总和。
该函数主要是用于将多个图像合并成一个多通道图像,该函数也具有两种不同的函数原型,每一种函数原型都是与split()函数相对应,两种原型分别输入数组形式的图像数据和向量vector形式的图像数据,在输入数组形式数据的原型中,还需要输入数组的长度。合并函数的输出结果是一个多通道的图像,其通道数目是所有输入图像通道数目的总和。这里需要说明的是,用于合并的图像并非都是单通道的,也可以是多个通道数目不相同的图像合并成一个通道更多的图像,虽然这些图像的通道数目可以不相同,但是需要所有图像具有相同的尺寸和数据类型
//函数定义
void channels_demo(Mat& image);
//函数实现—
void QuickDemo::channels_demo(Mat& image) {
Mat mvt[3];
/*
第一种方式
通过创建图像数组,存储每个单通道图像
*/
split(image, mvt);
imshow("蓝色单通道", mvt[0]);
imshow("绿色单通道", mvt[1]);
imshow("蓝色单通道", mvt[2]);
}
void QuickDemo::channels_demo(Mat& image) {
std::vector<Mat> mvt;
/*
第二种方式
通过创建动态数组,存储每个单通道图像
*/
split(image, mvt);
imshow("蓝色单通道", mvt[0]);
imshow("绿色单通道", mvt[1]);
imshow("红色单通道", mvt[2]);
}
这里我们进行一个演示,实现如下通道的混合
0通道→2通道
1通道不变
2通道→1通道
这个混合的意思是,彩色图像本来是bgr的顺序,经过通道混合就变成了rgb。
0通道的单通道图像,变成了2通道的单通道图像
1通道不变
2通道的单通道图像,变成了0通道的单通道图像
void QuickDemo::channels_demo(Mat& image) {
Mat dst = Mat::zeros(image.size(), image.type());
int from_to[] = { 0,2,1,1,2,0 };
mixChannels(&image, 1, &dst, 1, from_to, 3);
imshow("通道混合",dst);
}
Mat bgra( 100, 100, CV_8UC4, Scalar(255,0,0,255) );
Mat bgr( bgra.rows, bgra.cols, CV_8UC3 );
Mat alpha( bgra.rows, bgra.cols, CV_8UC1 );
// forming an array of matrices is a quite efficient operation,
// because the matrix data is not copied, only the headers
Mat out[] = { bgr, alpha };
// bgra[0] -> bgr[2], bgra[1] -> bgr[1],
// bgra[2] -> bgr[0], bgra[3] -> alpha[0]
int from_to[] = { 0,2, 1,1, 2,0, 3,3 };
mixChannels( &bgra, 1, out, 2, from_to, 4 );
为了使读者更加熟悉图像多通道分离与合并的操作,同时加深对图像不同通道作用的理解,在代码清单3-6中实现了图像的多通道分离与合并的功能。程序中用两种函数原型分别分离了RGB图像和HSV图像,为了验证merge ()函数可以合并多个通道不相同的图像,程序中分别用两种函数原型合并了多个不同通道的图像,合并后图像的通道数为5,不能通过imshow()函数显示,我们用Image Watch插件查看了合并的结果。由于RGB三个通道分离结果显示时都是灰色且相差不大,因此图3-5没有给出其分离后的结果,只给出合并后显示为绿色的合并图像,同时给出HSV分离结果,其他结果读者可以自行运行程序查看。
void QuickDemo::channels_demo(Mat& image) {
Mat mvt[3];
split(image, mvt);
imshow("蓝色单通道", mvt[0]);
imshow("绿色单通道", mvt[1]);
imshow("红色单通道", mvt[2]);
Mat dst;
merge(mvt,3,dst);
/*
这里的3指,共有3个单通道图像
*/
imshow("分离再合并",dst);
}
void QuickDemo::channels_demo(Mat& image) {
std::vector<Mat> mvt;
split(image, mvt);
imshow("蓝色单通道", mvt[0]);
imshow("绿色单通道", mvt[1]);
imshow("红色单通道", mvt[2]);
Mat dst;
merge(mvt, dst);
imshow("分离再合并",dst);
}
#include
#include
#include
#include
#include "opencv/highgui.h"
using namespace std;
using namespace cv;
int main(int argc,char** argv) {
cout<<"OpenCv Version: "<<CV_VERSION<<endl;
Mat img=imread("/home/wyh/Documents/C++demo/699342568.jpg");
if(img.empty()){
cout<<"请确认输入图片的名称是否正确"<<endl;
return -1;
}
Mat HSV,dst;
resize(img,dst,Size(img.cols*0.5,img.rows*0.5));
cvtColor(dst,HSV,COLOR_BGR2HSV);
Mat imgs0,imgs1,imgs2;//用于存放数组类型的结果
Mat imgv0,imgv1,imgv2;//用于存放vector类型的结果
Mat result0,result1,result2;//多通道合并的结果
//输入数组参数的多通道分离与合并
Mat imgs[3];
split(dst,imgs);
imgs0=imgs[0];
imgs1=imgs[1];
imgs2=imgs[2];
imshow("RGB-R通道",imgs0);//显示分离后R通道的像素值
imshow("RGB-G通道",imgs1);//显示分离后G通道的像素值
imshow("RGB-B通道",imgs2);//显示分离后B通道的像素值
imgs[2]=dst;//将数组中的图像通道数变成不统一
merge(imgs,3,result0);//合并图像
Mat zero=Mat::zeros(dst.rows,dst.cols,CV_8UC1);
imgs[0]=zero;
imgs[2]=zero;
merge(imgs,3,result1);//用于还原G通道的真实情况,合并结果为绿色
imshow("result1",result1);//显示合并结果
//输入vector参数的多通道分离与合并
vector<Mat>imgv;
split(HSV,imgv);
imgv0=imgv.at(0);
imgv1=imgv.at(1);
imgv2=imgv.at(2);
imshow("HSV-H通道",imgv0);//显示分离后H通道的像素值
imshow("HSV-S通道",imgv1);//显示分离后S通道的像素值
imshow("HSV-V通道",imgv2);//显示分离后V通道的像素值
imgv.push_back(HSV);//将vector中的图像通道数变成不统一
merge(imgv,result2);//合并图像
waitKey(0);
return 0;
}