Matlab中image、imagesc和imshow函数用法解析
来源:https://blog.csdn.net/zhuiyuanzhongjia/article/details/79621813
1、显示RGB图像
相同点:这三个函数都是把m*n*3的矩阵中的数值当做RGB值来显示的。
区别:imshow将图像以原始尺寸显示,image和imagesc则会对图像进行适当的缩放(显示出来的尺寸大小)。
2、显示灰度图像
说明:先搞明白什么是索引图像?(灰度图像也是索引图像的一种)
当用Matlab中的imread函数将图像读入并存入矩阵时,我们知道如果是RGB图像,得到是m*n*3的矩阵,但如果是索引图像,得到就是m*n的矩阵,这个矩阵的每个元素只是1个数值,那么怎么确定它的RGB值来显示图像呢?这就需要colormap了,colormap是一个m*3的矩阵,每一行有3列元素构成RGB组,也就是一种颜色,一个m*3的colormap中有m中颜色,而索引图像存储的数值和colormap中的行号对应起来就可以像RGB那样显示图片了,至于对应方法,可以直接对应(比如1对应1,2对应2)也可以是线性映射对应(比如[-128,128]映射到[1,256])。还有一点要说明的是,默认情况下每一个figure都有且仅有一个colormap,而且默认的是 jet(64),可在figure窗口通过,edit->colormap...查看,另外在弹出的窗口colormap editor中,可通过Tools->Standard colormap来修改当前figure的colormap,这里是Matlab已经做好的一些colormap。
(1)当灰度图像转化成矩阵后,矩阵中的元素都介于[0,255],下面我们结合具体实例来看看这三个函数的调用效果,并解释原因。代码:
- clear all;clc;close all;
- img = imread('lenna.bmp');
- % my picture is named lenna.bmp while yours may be not
- I = rgb2gray(img);
- % Attention: we use the axis off to get rid of the axis.
- figure(1),image(I); %equals to imagesc(I,[1 64]);you can try it.
- colorbar,title('show by image in figure1');axis off;
- figure(2),imagesc(I);
- %equals to imagesc(I,[min(I(:)) max(I(:))]);you can try it.
- colorbar,title('show by imagesc in figure2');axis off;
- %colormap(gray) %use this statement you can get a gray image.
- figure(3),imshow(I),colorbar,title('show by imshow in figure3');
显示效果:
我们看到现象是image 和imagesc 显示出来是彩色的,只有imshow显示出来是灰度图像,为什么会出现这种情况呢?还记得前面所说的吗,索引图像是矩阵和colormap配合起来显示的,而每个figure默认使用的colormap 是jet(64),而不是gray(gray和gray(64)是一样的),这个jet(64)就使得figure1和figure2中显示出来时是彩色的,当然你也可以修改当前figure的colormap使用colormap(gray)(使用64个等级的灰度色图),或者colormap(gray(256))(使用256个等级的灰度色图,这就是调用imshow函数时使用的colormap,后面有讲解)。而figure3为什么会是灰度图像呢,这是因为当调用imshow来显示索引图像时,这个函数就会把当前的figure的colormap设置成gray(256),这下明白为什么会出现这种情况了吧。我们再仔细观察一下figure1和figure2会发现,figure2中人物的轮廓显示的还算可以,而figure1中则出现了大面积的红色的区域,人物的轮廓被抹掉了很多。
为什么会出现这样的情况呢?这就要说说索引图像矩阵中的数(以下简称矩阵中的数)和colormap中的索引(index)的对应关系了。
image:这个函数,直接把矩阵中的数当做索引值(我称为直接映射),例如colormap中索引为1的是颜色RGB1,索引为2的是颜色RGB2,……,索引为64的是颜色RGB64。那么矩阵中为1的数就显示成颜色RGB1,矩阵中为2的数就显示成颜色RGB2,……,矩阵中为64的数就显示成颜色RGB64,值得注意的是当矩阵中的数小于1时,此时该数也将被显示成颜色RGB1,同样,而矩阵中大于64的数将被显示成颜色RGB64(类似于信号处理里面的限幅,也可以认为是削顶或者削底了),这下我们就能明白为什么figure1中会出现大面积的红色区域,这说明这些地方的数值都大于等于64。
imagesc: 在figure2中我们用imagesc来显示图像与figure1相比能较好的显示出来,同样我们也得搞明白调用imagesc时矩阵的数和colormap中索引的对应关系,与image不同的是imagesc采用的不是直接映射而是线性映射,至于什么是线性映射,我粗略的说一下,比如把区间A = [0,a]映射到区间B = [0,b]我们对A中的元素做A/a*b就可以了,矩阵的数到colormap索引的线性映射大概就是这样,Matlab会自动获取矩阵中数的最小值和最大值,并把区间[Cmin,Cmax]映射到colormap的[最小索引,最大索引]比如[1,64],然后再根据这个对应关系把图像显示出来,具体的算法细节是Matlab确定的,当然也可以自己指定显示范围,比如一副索引图像I范围为[27,218],而我只想显示[1 64 ],使用命令imagesc(I,[1 64])就可以了,如果你把上面程序中的imagesc(I)换成imagesc(I,[1,64]),那么figure2中的效果就和figure1中一样了,因为只是把[1,64]这个范围映射到色图,超过的都被认为是64。关于映射,我截图Matlab中imagesc的help页给大家看看,这里要自己慢慢体会哦,使用imagesc(I)这种线性映射就可以用到整个色图从而将图像较好的显示出来,这就是figure2中的显示效果比figure1中好的原因。
imshow:调用这个函数会把当前figure的colormap设置成gray(256),这个前面也有提到,我们先讨论矩阵元素是uint8型(范围:0~255,整数,一般使用imread和 rgb2gray返回的都是uint8型的),同样我们也要搞明白矩阵中的数和colormap中颜色索引的对应关系,imshow的功能是比较全的,它即可使用像image那样的直接映射,也可使用像imagesc那样的线性映射,当我们使用imshow(I),即只有一个矩阵作为参数,这时采用的是直接映射,比如矩阵中元素0就显示成colormap中索引为1的颜色也就是黑色,矩阵中元素255就显示成colormap中索引为256的颜色也就是白色,(注意:uint8范围是0~255,而gray(256)的索引是1:256,当然这些我们只要了解就可以了,编程并不会用到,因为这些对应的细节Matlab已经帮我们做好了)如果这样调用imshow(I,[ ]),此时矩阵中的数和颜色表就是线性映射,为什么会这样,我解释一下,我们看这种调用方式和imagesc(I,[1 64])很相似,其实原理是一样的,第二个参数是一个向量,这个向量指定了矩阵中映射到颜色表的数的范围,也就是显示范围(Matlab里叫做display range)前面已经介绍了,Matlab中imshow的help中说如果采用imshow(I,[low high])调用imshow的话而且你用[ ]代替[low high]那么imshow会使用[min(I(:)) max(I(:))]作为显示范围,也就说I中的最小值会显示成黑色,最大值会显示成白色,这其实就是整个范围的线性映射(没有削顶也没有削底),此时的imshow(I,[ ])函数就相当于imagesc(I);
为了说明imshow不仅具有image的功能也具有imagesc的功能,同时体会一下直接映射和线性映射的区别,我们来写一段小程序来测试一下,程序如下:
- clear all;clc;close all;
- img = imread('lenna.bmp');
- I = rgb2gray(img);
- figure(1),image(I); colormap(gray(256));
- colorbar,title('show by image in figure1');axis off;
- figure(2),imagesc(I);colormap(gray(256));
- % We can see that the image showed in figure(2) is a little bright
- % than in figure(1).
- colorbar,title('show by imagesc in figure2');axis off;
- % When we use the imshow, we do not need to set the colormap,
- % because the imshow set the colormap to gray(256) automatically.
- figure(3),imshow(I),colorbar,title('show by imshow(I) in figure3');
- % The effectiveness in figure(3) is the same as in figure(1).
- figure(4),imshow(I,[]),colorbar,title('show by imshow(I,[]) in figure3');
- % The effectiveness in figure(4) is the same as in figure(2).
显示效果:
我们可以看出figure2中的图像比figure1中的图像要亮一些,而且,figure3中的显示效果和figure1中是一样的,figure4中的显示效果和figure2中是一样的,为什么会这样呢?这是因为image(I)和imshow(I)是将I中的值直接作为colormap(gray(256))中的索引,也就是我所说的直接映射,我这里读到的索引图像矩阵也就是I中的数值的范围是[27,218],也就是说直接映射显示I,只用到的色图(colormap)上[27,218]范围的颜色,(比如表示白色的索引255就没有用到),从右边的colorbar也可以看出来。但线性映射就不一样了,imagesc(I),和imshow(I,[ ])采用的就是线性映射,线性映射把[27,218]按照线性算法(Matlab写的)映射到色图索引[1,256]然后再显示出来,这样整个色图的颜色都被用到了,这里也可以认为把[27,218]放大到[1,256],这就是figure2中显示效果比figure1中亮的原因。
小结:直接映射和线性映射的区别在于映射到色图的数值范围,如果是[min(I(:)) max(I(:))]就是线性映射,如果是0-255或者1-64或者0-1就是直接映射。这个数值范围就叫做显示范围(display range)。
3、最后再说说image,imagesc,imshow 在显示double型数据时的用法,
我们做图像处理就会对图像进行运算,使用uint8型数据精度不高,因为当运算结果超过255时会被认为是255,而负数就会被认为是0(注意在Matlab中数据默认采用double型(64位)进行存储和运算)所以,我们读到灰度图像后一般都会将图像转换成double型(I = double(I))然后再参与运算,运算的结果有正有负,也有小数,正的还可能超过255,比如我经过运算后的得到图像矩阵I,假如I的范围是[-187,152],当然你也可以用max(I(:))和min(I(:))去获取,这时怎么显示图像呢?image,imagesc,imshow 都可以用来显示double型数据的图像矩阵,主要区别如下:
image:将double型数据取整(正数取整就是把小数部分舍掉)然后使用直接映射的方法按照颜色表显示。
imagesc:这个函数很好,会对数据进行缩放再显示,也就是把显示范围自动设置成[min(I(:)) max(I(:))],也就是线性 映射。
imshow:这个函数调用方式不同,显示效果也不同,如下:
imshow(I):直接调用,因为当图像为double型时imshow函数会把显示范围设置成[0 , 1],这样小于0的就变成黑色了,大于1的就变成白色了,所以处理不当就会出现全白的情况。
imshow( I/(max(I(:))):针对直接调用imshow函数出现的问题,用max(I(:) ) 对图像矩阵进行归一化再显示,这样负数部分会变黑,正数部分还可以正常显示,但有一部分信息丢失了。
imshow(uint8(I)):这种方式把I转化成uint8,负数会被归零,超过255的被置为255,而且小数也会被round(四舍五入),当参数为uint8型时,imshow函数把显示范围设置成[0,255],这样图像虽然也能显示出来,但与原始数据相比来说,丢掉很多信息,但有时可能却是想要的结果,这个要看具体情况。
imshow(I,[ ]):这种方式就是把imshow的显示范围设置成[min(I(:)) max(I(:))],也就是线性映射,相当于imagesc(I),colormap(gray(256))可以将整幅图像的信息显示出来。
综上所述,大家根据自己实际需要选用显示函数和对应的参数,这些是我自己研究学习的心得,表述难免有些疏漏,有发现严重错误的,可以给我留言,但可以给大家一个感性的认识,从云里雾里的困境里走出来。
Matlab中image、imagesc和imshow函数用法解析的更多相关文章
- matlab中求解线性方程组的rref函数
摘自:http://www.maybe520.net/blog/987/ matlab中怎么求解线性方程组呢? matlab中求解线性方程组可应用克拉默法则(Cramer's Rule)即通过det( ...
- matlab中imfilter、conv2、imfilter2用法及区别
来源 :https://blog.csdn.net/u013066730/article/details/56665308(比较详细) https://blog.csdn.net/yuanhuilin ...
- MATLAB中提高fwrite和fprintf函数的I/O性能
提高fwrite和fprintf函数的I/O性能 http://www.matlabsky.com/thread-34861-1-1.html 今天我们将讨论下著名的fwrite(fprint ...
- sql中的group by 和 having 用法解析
转载博客:http://www.cnblogs.com/wang-123/archive/2012/01/05/2312676.html --sql中的group by 用法解析:-- Group B ...
- (C/C++学习)5.C++中的虚继承-虚函数-多态解析
说明:在C++学习的过程中,虚继承-虚函数经常是初学者容易产生误解的两个概念,它们与C++中多态形成的关系,也是很多初学者经常产生困惑的地方,这篇文章将依次分别对三者进行解析,并讲述其之间的联系与不同 ...
- MATLAB中的nargin与varargin的用法
nargin的用法: nargin:number of function input arguments,指的是一个函数的输入变量的个数. 用法:nargin或着nargin(fx), 其中fx指的是 ...
- sql server中replace()函数用法解析
知识点一:replace()的语法 REPLACE ( string_replace1 , string_replace2 , string_replace3 ) 参数解析: string_repla ...
- Matlab中常见的神经网络训练函数和学习函数
一.训练函数 1.traingd Name:Gradient descent backpropagation (梯度下降反向传播算法 ) Description:triangd is a networ ...
- matlab中m文件与m函数的学习与理解
1. m文件与m函数的区别 所谓 MATLAB 程序,大致分为两类: M 脚本文件 (M-Script) 和 M 函数 (M-function), 它们均是普通的 ASCII 码构成的文件. M 脚本 ...
随机推荐
- if-else 可以这么写
最近部门在对以往的代码做一些优化,我在代码中看到一连串的 if(){}elseif(){} 的逻辑判断.这明显是有优化空间的. 由于内部代码不适合分享,这里我就用 <输出今天为星期几> 来 ...
- checkbox手动样式改变
.image_input_checkbox{ width:18px; height:18px; display: inline-block; vertical-align: middle; -webk ...
- 【转】Android 音量键+电源键 截屏代码小结
http://104zz.iteye.com/blog/1752961 原文地址:http://blog.csdn.net/hk_256/article/details/7306590 ,转载请注明出 ...
- vue、react等SPA应用页脚组件闪烁的解决办法
大家好,我是木瓜太香.大家在开发单页应用的时候,经常会遇到这样的需求,头部和尾部两个组件是大多数组件公用的,而中间的内容区域则是单独存在的,而且一般内容组件逻辑会比较多,如果我们不停刷新页面可能会出现 ...
- 安装JDK的攻略
打开浏览器搜索JDK官网 单击Oracle下的JDK Download. 如果英语不好就直接打开浏览器自带翻译功能,根据自己的系统以及相应版本,下载对应的JDK 根据安装提示进行安装,路径自己选择. ...
- AWD攻防技战法
round1 弱口令 cat /etc/passwd 查看用户信息 修改用户密码(passwd username) 通过ssh弱口令批量getshell (通过msf的auxiliary/sca ...
- matplotlib | Python强大的作图工具,让你从此驾驭图表
今天是数据处理专题的第9篇文章,在之前的8篇文章当中我们已经介绍完了pandas这个库的一些基本用法,我们先把一些冷门的高级用法放一放,先来给大家介绍一下另外一个很有用的数据分析库--matplotl ...
- Javaweb应用中配置错误跳转页面
关于在Javaweb应用中配置错误跳转页面 应用场景,比如服务器的出现404错误,我们想让它返回跳转到我们自定义的错误页面 解决方法: 主要在web.xml文件中进行配置,这里玩的错误页面都单独放在e ...
- 关于while (~scanf("%d %d", &m, &n))的用法
其功能是循环从输入流读入m和n,直到遇到EOF,有如下关系: while (~scanf("%d %d", &m, &n)) ↔ while (scanf(&quo ...
- Unit4:碎片
基本使用 动态调用 碎片和活动 碎片周期