1.显示RGB图像
相似之处:这三个函数都是将m*n*3矩阵中的值显示为RGB值。
区别:以原始尺寸显示图像,图像会适当缩放图像。 请注意,这只是图像显示的大小。
2. 显示灰度图像
说明:首先了解什么是索引图像? (灰度图像也是索引图像的一种)
当使用in中的函数将图像读入并存储到矩阵中时,我们知道如果是RGB图像,得到的矩阵是m*n*3,但是如果是索引图像,得到的矩阵是m*n。 这个矩阵的每个元素只是一个数值,那么如何确定它的RGB值来显示图像呢? 这就是所需要的。
是一个m*3的矩阵。 每行有3个列元素组成一个RGB组,即一种颜色。 一个m*3中有m种颜色,索引图像中存储的值对应于图像中的行号,图像以RGB方式显示。 至于对应的方法,可以是直接对应(例如1对应1,2对应2),也可以是线性映射(例如[-128,128]映射到[1,256])。
还有一点需要注意的是,默认情况下,各只有一个,默认的是jet(64),可以通过窗口查看,edit->...,在弹出的窗口中,可以通过Tools->修改当前的,这里有一些已经完成的。
(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); %equalsto 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');
显示效果:
我们看到现象是图像显示的是彩色的,但只显示灰度图像。 为什么会出现这种情况? 还记得我之前说过的,索引图像是和矩阵一起显示的,并且每个默认都使用jet(64)而不是gray(gray和gray(64)是一样的),这个jet(64)会让sum显示出来彩色。 当然,你也可以修改当前使用的(gray),(使用64级灰度色彩图)或者(gray(256))(使用256级灰度色彩图)。 如图,这是调用函数时使用的,稍后解释)。 为什么它是灰度图像? 这是因为当调用该函数显示索引图像时,会将当前图像设置为灰色(256)。 现在您可以理解为什么会发生这种情况了。 如果我们再仔细看的话,我们会发现图片中的人物轮廓还不错,但是图片中出现了大片的红色区域,并且人物的轮廓被抹掉了很多。
为什么会出现这样的情况呢? 这是关于索引图像矩阵中的数字(以下简称矩阵中的数字)与索引(index)之间的对应关系。
image:这个函数直接使用矩阵中的数字作为索引值(我称之为直接映射)。 例如,1 处的索引是颜色 RGB1,2 处的索引是颜色 RGB2,...,64 处的索引是颜色 RGB64 。 那么矩阵中的数字1显示为颜色RGB1,矩阵中的数字2显示为颜色RGB2,...,矩阵中的数字64显示为颜色RGB64。 值得注意的是,当矩阵中的数字小于1时,该数字也会显示为颜色RGB1。 同样,矩阵中大于64的数字会显示为颜色RGB64(类似于信号处理中的限制,也可以认为是顶部或底部切割。),现在我们可以理解为什么矩阵中有大片红色区域了,也就是说这些地方的值都大于等于64。
:in,我们用它来显示图像比in更好。我们还要了解调用中矩阵的编号和索引的对应关系。 与图像不同的是,它不是直接映射,而是线性映射。 ,至于什么是线性映射,我简单说一下。 例如,要将区间 A = [0, a] 映射到区间 B = [0, b],我们只需对 A 中的元素执行 A/a*b 即可。 矩阵 数字到索引的线性映射大致为像这样。 它会自动获取矩阵中数字的最小值和最大值,并将区间[Cmin,Cmax]映射到[最小索引,最大索引]如[1,64],然后根据到这个对应关系。 具体算法细节确定。 当然,您也可以自己指定显示范围。 例如,索引图像的I范围是[27,218],我只想显示[164]。 使用命令( I,[1 64]) 就可以了。 如果把上面程序中的(I)替换为(I,[1,64]),那么in中的效果会和in中一样,因为只要替换[1,64]这个范围就映射到了颜色图上,任何东西超过 64 则被考虑。 关于映射,我将在屏幕截图中向您展示帮助页面。 你要慢慢去体会。 使用像(I)这样的线性映射,您可以使用整个颜色图来更好地显示图像。 这就是显示效果优于的原因。
:调用该函数会将当前值设置为灰色(256)。 这一点前面也提到过。 首先讨论矩阵元素是uint8类型(范围:0~255,整数,一般使用和返回都是uint8类型)。 同样,我们还需要了解矩阵中的数字与颜色索引的对应关系。 功能比较齐全。 它可以使用像图像这样的直接映射或像这样的线性映射。 当我们使用(I)时,即只有一个矩阵作为参数。 这是直接映射。 例如,矩阵中的元素0显示为中间索引1的颜色,即黑色,矩阵中的元素255显示为中间索引256的颜色,即白色,(注:uint8范围是0~255,灰度(256)的索引是1:256,当然我们只需要了解这些,在编程中不会用到它们,因为这些对应的细节已经帮我们做好了。 )
如果这样调用(I,[]),则矩阵和颜色表中的数字是线性映射。 为什么是这样? 让我解释。 我们看到这个调用方式和(I,[164])非常相似。 其实原理都是一样的。 第二个参数是一个向量。 这个向量指定了矩阵中映射到颜色表的数字范围,也就是显示范围(这里称为显示范围)。 之前已经介绍过,帮助中说如果你使用(I, [])被调用并且你使用[]而不是[low high],那么[min(I(:))max(I(:)) ] 将用作显示范围,这意味着 I 中的最小值将以黑色显示,最大值将以白色显示,这实际上是整个范围的线性映射(没有顶部或底部裁剪)。 此时(I,[])函数等价于(I);
为了说明它不仅具有图像的功能而且还具有图像的功能,同时了解直接映射和线性映射的区别,我们来写一个小程序来测试一下。 程序如下:
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).
显示效果:
我们可以看到 中的图像比 中的图像更亮,并且显示效果与 中的显示效果相同。 为什么是这样? 这是因为image(I)和(I)直接使用I中的值作为(gray(256))中的索引,这就是我所说的直接映射。 我这里读到的索引图像矩阵也是 I 中的索引,取值范围是[27, 218],也就是说直接映射显示 I 只使用颜色图的 [27, 218] 范围内的颜色()(例如,不使用代表白色的索引255)。
但线性映射不同。 (I) 和 (I,[]) 使用线性映射。 线性映射根据线性算法(书面)将[27,218]映射到颜色图索引[1,256],然后显示它。 ,以便使用整个颜色图的颜色。 也可以认为将[27,218]放大为[1,256]。 这就是为什么中等显示效果比中等更亮的原因。
总结:直接映射和线性映射的区别在于映射到颜色图的数值范围。 如果是[min(I(:))max(I(:))],则为线性映射。 如果是0-255或者1-64或者0-1就是直接映射。 这个数值范围称为显示范围()。
3、最后说一下图像在显示数据时的使用。
当我们进行图像处理时,我们会对图像进行操作。 使用uint8类型数据的精度不高,因为当运算结果超过255时会被认为是255,负数会被认为是0(注意是默认类型(64位)中的数据进行存储和运算)因此,我们读取灰度图像后,通常会将图像转换为形状(I=(I)),然后参与运算。 运算的结果有正数、负数、小数,正数可能超过255。比如我运算后得到图像矩阵I。 如果I的范围是[-187,152],当然也可以使用max(I(:))和min(I(:))来获取。 这个时候怎么显示呢? 那么图像呢? image,都可以用来显示数据的图像矩阵。 主要区别如下:
image:对类型数据进行四舍五入(四舍五入正数就是四舍五入小数部分),然后根据颜色表使用直接映射的方式显示。
: 这个功能非常好。 它会在显示数据之前对数据进行缩放,即自动将显示范围设置为[min(I(:))max(I(:))],这是一个线性映射。
:该函数的调用方法不同,显示效果也不同,如下:
(I): 直接调用,因为当图像类型时,该函数会将显示范围设置为[0, 1],这样如果小于0就会变成黑色,如果大于1 ,它会变成白色,所以如果处理不当,就会出现。
(I/(max(I(:))):解决直接调用函数的问题,在显示之前使用max(I(:))对图像矩阵进行归一化处理,这样负数部分就会变成黑色,正面部分就OK了,显示正常,但是缺少一些信息。
(uint8(I)):该方法将 I 转换为 uint8。 负数将重置为零,超过255的值将设置为255,小数点也会四舍五入。 当参数为uint8时,函数将显示范围设置为[0,255],这样虽然可以显示图像,但与原始数据相比丢失了很多信息,但有时可能是想要的结果,具体取决于就具体情况而言。
(I,[]):该方法是设置显示范围为[min(I(:))max(I(:))],是线性映射,相当于(I),(gray(256) )可以显示整个图像的信息。
综上所述,您可以根据自己的实际需要选择显示功能和相应的参数。 这些是我自己的研究和学习经历。 表述中难免有一些遗漏。 如果您发现严重错误,可以给我留言,但我可以给您情感审核。 了解并走出迷雾困境。