本文详细介绍了opencv中涉及通道的知识,包括图像类型转换,通道合成分解,图像的显示。

来源:http://blog.csdn.net/GDFSG/article/details/50927257

1. 知识点

tips1:  一个图像的通道数是N,就表明每个像素点处有N个数,一个a×b的N通道图像,其图像矩阵实际上是b行N×a列的数字矩阵。

OpenCV中图像的通道可以是1、2、3和4。其中常见的是1通道和3通道,2通道和4通道不常见。

1通道的是灰度图。

3通道的是彩色图像,比如RGB图像。

4通道的图像是RGBA,是RGB加上一个A通道,也叫alpha通道,表示透明度。PNG图像是一种典型的4通道图像。alpha通道可以赋值0到1,或者0到255,表示透明到不透明。

2通道的图像是RGB555和RGB565。2通道图在程序处理中会用到,如傅里叶变换,可能会用到,一个通道为实数,一个通道为虚数,主要是编程方便。RGB555是16位的,2个字节,5+6+5,第一字节的前5位是R,后三位+第二字节是G,第二字节后5位是B,可见对原图像进行压缩了。

tips2: OpenCV中用imshow( )来显示图像,只要Mat的数据矩阵符合图像的要求,就可以用imshow来显示。二通道好像不可以。。。超过了4通道,就不是图像了,imshow( )也显示不了。

tips3: imshow( )显示单通道图像时一定是灰度图,如果我们想显示红色的R分量,还是应该按三通道图像显示,只不过G和B通道要赋值成0或255.

tips4: 通道分解用split( ),通道合成用merg( ),这俩函数都是mixchannel( )的特例。

下面,结合程序说明以上知识点。

2 图像类型的转换与显示

  1. Mat image=imread("E:/图片/color.jpg");
  2. Mat imageGRAY,imageRGBA,imageRGB555;
  3. cvtColor(image,imageGRAY,CV_RGB2GRAY);            //RGB转GRAY
  4. cvtColor(image,imageRGBA,CV_RGB2BGRA);            //RGB转RGBA
  5. cvtColor(image,imageRGB555,CV_RGB2BGR555);        //RGB转RGB555
  6. //来看看通道数
  7. int n = image.channels();                        //n=3
  8. int nRGBA = imageRGBA.channels();                //nRGBA = 4
  9. int nRGB555 = imageRGB555.channels();            //nRGB555 = 2
  10. //显示GRAY、RGB和RGBA图像
  11. imshow("image",image);
  12. imshow("imageGRAY",imageGRAY);
  13. imshow("imageRGBA",imageRGBA);
  14. //imshow("imageRGB555",imageRGB555);             //无法显示

RGB转GRAY是根据一个心理学公式来的:Gray = R*0.299 + G*0.587 + B*0.114

RGB转GRBA,默认A通道的数值是255,也就是不透明的。

3 通道的合成与分解

3.1 简单的例子

我们先来看下最常用的合成与分解函数。

split()

C++: void split(const Mat& mtx, Mat* mv)
C++: void split(const Mat& mtx, vector<Mat>& mv)
C:   void cvSplit(const CvArr* src, CvArr* dst0, CvArr* dst1, CvArr* dst2, CvArr* dst3)

参数:mtx   输入矩阵

mv    输出矩阵或矩阵数组

src   输入矩阵

dst0、dst1、dst2、dst3   最多4个单通道的输出矩阵

当我们要固定提取某个通道的矩阵时,C形式的用法还是蛮实用的,不必向C++用法那样,先定义vector,再channels.at(k)

  1. Mat rgb( 3, 4, CV_8UC3, Scalar(1,2,3,4) );
  2. vector<Mat> channels;
  3. split(rgb,channels);
  4. Mat B = channels.at(0);          //从vector中读数据用vector::at()
  5. Mat G = channels.at(1);
  6. Mat R = channels.at(2);
  7. cout<<"RGB="<<endl<<rgb<<endl;
  8. cout<<"B="<<endl<<B<<endl;
  9. cout<<"G="<<endl<<G<<endl;
  10. cout<<"R="<<endl<<R<<endl;

注意rgb图像的通道排列是BGR

merge( )

C++: void merge(const Mat* mv, size_t count, OutputArray dst)
C++: void merge(const vector<Mat>& mv, OutputArray dst)
C:   void cvMerge(const CvArr* src0, const CvArr* src1, const CvArr* src2, const CvArr* src3, CvArr* dst)

参数:mv    输入矩阵

count   当mv是C形式的array时,count表示输入矩阵个数

dst   输出矩阵

src0、src1、src2、src3   最多4个单通道的输入矩阵

  1. Mat R(3,4,CV_8UC1, Scalar(3));
  2. Mat G(3,4,CV_8UC1, Scalar(2));
  3. Mat B(3,4,CV_8UC1, Scalar(1));
  4. Mat RGB( 3, 4, CV_8UC3);
  5. vector<Mat> src;
  6. src.push_back(B);               //往vector里存数据要用vector::push_back()
  7. src.push_back(G);
  8. src.push_back(R);
  9. merge(src,RGB);
  10. cout<<"B="<<endl<<B<<endl;
  11. cout<<"G="<<endl<<G<<endl;
  12. cout<<"R="<<endl<<R<<endl;
  13. cout<<"RGB="<<endl<<RGB<<endl;

split( )和merge( )都是mixChannels( )的特例,接下来看看mixChannels()的用法

mixChannels( )

C++: void mixChannels(const Mat* src, int nsrc, Mat* dst, int ndst, const int* fromTo, size_t npairs)
C++: void mixChannels(const vector<Mat>& src, vector<Mat>& dst, const int* fromTo, int npairs)

参数:src  输入的矩阵,可以是一个矩阵也可以是多个矩阵构成的vector

nsrc   输入矩阵的个数

dst   输出矩阵,可以是一个矩阵也可以是多个矩阵构成的vector

ndst   输出矩阵的个数

fromTo   src到dst通道对应数组

npairs    fromTo中有几组对应关系

mixChannels( )本质是改变了几个通道的顺序,输入一共有几个通道,输出肯定也有几个通道,所以定义fromTo时,要知道有多少个通道,而且通道的编号一定是0,1,2,...

  1. Mat RGB(3,4, CV_8UC3,Scalar(1,2,3,4));
  2. Mat A(3,4,CV_8UC1,Scalar(6));
  3. cout<<"RGB="<<endl<<RGB<<endl;
  4. cout<<"A="<<endl<<A<<endl;
  5. //RGB+A合成为RGBA
  6. cout<<"RGB+A合成为RGBA"<<endl;
  7. Mat RGBA(3,4,CV_8UC4);
  8. Mat in[]={RGB,A};
  9. int fromTo1[] = {0,0, 1,1, 2,2, 3,3};
  10. mixChannels(in,2,&RGBA,1,fromTo1,4);
  11. cout<<"RGBA="<<endl<<RGBA<<endl;
  12. //RGB分解为R+GB
  13. cout<<"RGB分解为R+GB"<<endl;
  14. Mat R(3,4,CV_8UC1);
  15. Mat GB(3,4, CV_8UC2);
  16. Mat out[]={R,GB};
  17. int fromTo2[] = {0,2, 1,1, 2,0};
  18. mixChannels(&RGB,1,out,2,fromTo2,3);
  19. cout<<"R="<<endl<<R<<endl;
  20. cout<<"GB="<<endl<<GB<<endl;

3.2 以图像为例

我们先来看一个例子

  1. Mat image=imread("E:/图片/color.jpg");
  2. vector<Mat> channels;
  3. split(image,channels);
  4. Mat B = channels.at(0);
  5. Mat G = channels.at(1);
  6. Mat R = channels.at(2);
  7. imshow("image",image);
  8. imshow("R",R);
  9. imshow("G",G);
  10. imshow("B",B);

三个分量R、G、B因为是单通道图像,所以只能显示为灰度图。如果要想显示出颜色来,应该用三通道图像来显示,比如显示R,我们就让G和B通道的数值为0或255。看下面例子

  1. Mat image=imread("E:/图片/color.jpg");
  2. vector<Mat> sbgr;
  3. split(image,sbgr);   //split to sbgr[0],sbgr[1] ,sbgr[2]
  4. vector<Mat> mbgr(3);
  5. Mat bk1(image.size(),CV_8UC1,Scalar(0));
  6. //Mat bk2(image.size(),CV_8UC1,Scalar(255));
  7. //显示彩色的B分量
  8. Mat imageB(image.size(),CV_8UC3);
  9. mbgr[0]= sbgr[0];
  10. mbgr[1]= bk1;
  11. mbgr[2]= bk1;
  12. merge(mbgr,imageB);
  13. imshow("imageB",imageB);
  14. //显示彩色的G分量
  15. Mat imageG(image.size(),CV_8UC3);
  16. mbgr[0]= bk1;
  17. mbgr[1]= sbgr[1];
  18. mbgr[2]= bk1;
  19. merge(mbgr,imageG);
  20. imshow("imageG",imageG);
  21. //显示彩色的R分量
  22. Mat imageR(image.size(),CV_8UC3);
  23. mbgr[0]= bk1;
  24. mbgr[1]= bk1;
  25. mbgr[2]= sbgr[2];
  26. merge(mbgr,imageR);
  27. imshow("imageR",imageR);
  28. imwrite("imageR.jpg",imageR);
  29. imwrite("imageG.jpg",imageG);
  30. imwrite("imageB.jpg",imageB);
  31. waitKey(0);


如果将bk1赋值成255,将会得到下面的图像

4  制作一个透明的图片

PNG是RGBA的图片格式,对于一般的RGB图像,我们只需要加上一个A通道,并且A通道的值不全为1(或255),就可以得到一个透明的图片。

  1. Mat image=imread("E:/图片/color.jpg");
  2. //定义4种A通道
  3. Mat imageA0 = Mat(image.size(),image.depth(),Scalar(0));         //image.depth()返回0,表示cv_8u
  4. Mat imageA85 = Mat(image.size(),image.depth(),Scalar(85));
  5. Mat imageA170 = Mat(image.size(),image.depth(),Scalar(170));
  6. Mat imageA255 = Mat(image.size(),image.depth(),Scalar(255));
  7. //定义合成后的RGBA图像,透明度分别为0%,33%,67%,100%,透明---->不透明
  8. Mat imageRGBA0 = Mat(image.size(),CV_8UC4);
  9. Mat imageRGBA85 = Mat(image.size(),CV_8UC4);
  10. Mat imageRGBA170 = Mat(image.size(),CV_8UC4);
  11. Mat imageRGBA255 = Mat(image.size(),CV_8UC4);
  12. Mat in1[] = {image,imageA0};
  13. Mat in2[] = {image,imageA85};
  14. Mat in3[] = {image,imageA170};
  15. Mat in4[] = {image,imageA255};
  16. int from_to[] = {0,0, 1,1, 2,2, 3,3};
  17. mixChannels(in1,2,&imageRGBA0,1,from_to,4);
  18. mixChannels(in2,2,&imageRGBA85,1,from_to,4);
  19. mixChannels(in3,2,&imageRGBA170,1,from_to,4);
  20. mixChannels(in4,2,&imageRGBA255,1,from_to,4);
  21. imwrite("imageRGBA0.png",imageRGBA0);
  22. imwrite("imageRGBA85.png",imageRGBA85);
  23. imwrite("imageRGBA170.png",imageRGBA170);
  24. imwrite("imageRGBA255.png",imageRGBA255);

直接用imshow( )是看不出差别来的,可以这么看。把一张PPT的空白背景替换成彩色背景,然后把这些 图片放上去,效果如下图所示。

上图显示的结果实质是背景网格图片和我们的PNG图片叠加显示的效果。所以我们有个更简洁的方法实现上面的显示效果,是显示效果!

imageResult = α·image + (1-α)·imageRGID

我们只需要调整α的值就能控制image和imageGRID显示的比例了。

学习OpenCV2——Mat之通道的理解的更多相关文章

  1. OpenCV2:Mat属性type,depth,step

    在OpenCV2中Mat类无疑使占据着核心地位的,前段时间初学OpenCV2时对Mat类有了个初步的了解,见OpenCV2:Mat初学.这几天试着用OpenCV2实现了图像缩小的两种算法:基于等间隔采 ...

  2. OpenCV学习(5) Mat的基本操作(2)

          本章我们学习一下Mat中的常用操作,因为在后面其它的教程中,我们经常要对图像进行各种处理,也要使用这些操作. 一. Mat的复制,就是从一个矩阵A,生成相关的另一个矩阵B. (1)使用赋值 ...

  3. AI安全初探——利用深度学习检测DNS隐蔽通道

    AI安全初探——利用深度学习检测DNS隐蔽通道 目录 AI安全初探——利用深度学习检测DNS隐蔽通道 1.DNS 隐蔽通道简介 2. 算法前的准备工作——数据采集 3. 利用深度学习进行DNS隐蔽通道 ...

  4. 【VS开发】OpenCV2:Mat属性type,depth,step

    OpenCV2:Mat属性type,depth,step 在OpenCV2中Mat类无疑使占据着核心地位的,前段时间初学OpenCV2时对Mat类有了个初步的了解,见OpenCV2:Mat初学.这几天 ...

  5. 学习Logistic Regression的笔记与理解(转)

    学习Logistic Regression的笔记与理解 1.首先从结果往前来看下how logistic regression make predictions. 设我们某个测试数据为X(x0,x1, ...

  6. 学习 C++,关键是要理解概念,而不应过于深究语言的技术细节

    学习 C++学习 C++,关键是要理解概念,而不应过于深究语言的技术细节. 学习程序设计语言的目的是为了成为一个更好的程序员,也就是说,是为了能更有效率地设计和实现新系统,以及维护旧系统. C++ 支 ...

  7. 学习 opencv---(2) 图像的载入,显示和输出

    了解过之前老版本OpenCV的童鞋们都应该清楚,对于OpenCV1.0时代的基于 C 语言接口而建的图像存储格式IplImage*,如果在退出前忘记release掉的话,就会照成内存泄露.而且用起来超 ...

  8. 学习 opencv---(4) 分离颜色通道 && 多通道混合

    上篇文章中我们讲到了使用addWeighted函数进行图像混合操作,以及将ROI和addWeighted函数结合起来使用,对指定区域进行图像混合操作. 而为了更好地观察一些图像材料的特征,有时需要对R ...

  9. OpenCV2:Mat

    1.Mat基础 在计算机内存中,数字图像是已矩阵的形式保存的.OpenCV2中,数据结构Mat是保存图像像素信息的矩阵,它主要包含两部分:矩阵头和一个指向像素数据的矩阵指针. 矩阵头主要包含,矩阵尺寸 ...

随机推荐

  1. grub的三种安装方式

    1.install命令 install: install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p ...

  2. c++ 使用boost regex库 总结

    用java的时候觉得挺折腾,回头来弄c++才知道什么叫折腾...汗... 首先参考我写的这篇文章:http://www.cnblogs.com/qrlozte/p/4100892.html 我从sou ...

  3. htmt 5 素材

    http://www.html5code.net/plus/list.php?tid=20

  4. 关于PHP.INI中的错误ERROR报告级别设置

    最近在写php的过程中发现php提示php notice:………………的字样,虽然这个只是php的提示内容,并没有什么大的影响,但是出于安全性和美观方面的考虑,小弟还是想把这个东西去掉. 那么,怎么办 ...

  5. linux和pycharm下终端彩色打印输出

    实际上linux终端是调用ANSI控制码来实现终端彩色输出.终端的字符颜色由转义序列(Escape Sequence)控制,是文本模式下的系统显示功能,与具体语言无关. 转义序列以控制字符'ESC'开 ...

  6. python 循环内部添加多个条件判断会出现越界

    1.循环遍历数组是,想添加条件修改时,只删除第一个 # -*- coding: utf-8 -*- a=[11,22,33,44,55] for i in a: if i == 11 or i ==2 ...

  7. cocos2d-x 游戏优化方案

    优化的方案: 引擎底层优化.纹理优化.渲染优化.资源缓存.内存优化. 纹理优化: cocos2d-x 底层是OPenGL ES实现的. 对于图案片载入的内存是2的幂次方. 使用的图片是100*128 ...

  8. linux/unix下telnet提示Escape character is '^]'的意义

    在linux/unix下使用telnet hostname port连接上主机后会提示Escape character is '^]' 这个提示的意思是按Ctrl + ] 会呼出telnet的命令行, ...

  9. PHP中导出Excel,将数据以Excel形式导出

    现在,很多地方都需要导出数据,这里说一种简单的方法将数据以Excel的形式导出,方法如下: <?php date_default_timezone_set('PRC');//设置时区 /*设置h ...

  10. Python 文件操作、异常

    windows默认是gbk编码,又称cp936,汉字占2个字节. utf-8被称为万国码,这个编码下,汉字占3个字节. ASCII也是一种编码. 一.文件操作 最基本的文件打开: f = open(& ...