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],下面我們結合具體實例來看看這三個函數的調用效果,並解釋原因。代碼:

 

[plain]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
 
 
  1. clear all;clc;close all;  
  2. img = imread('lenna.bmp');  
  3. % my picture is named lenna.bmp while yours may be not  
  4. I = rgb2gray(img);  
  5. % Attention: we use the axis off to get rid of the axis.  
  6. figure(1),image(I); %equals to imagesc(I,[1 64]);you can try it.  
  7. colorbar,title('show by image in figure1');axis off;  
  8. figure(2),imagesc(I);  
  9. %equals to imagesc(I,[min(I(:)) max(I(:))]);you can try it.  
  10. colorbar,title('show by imagesc in figure2');axis off;  
  11. %colormap(gray) %use this statement you can get a gray image.  
  12. 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。關於映射,我截圖Matlabimageschelp頁給大家看看,這里要自己慢慢體會哦,使用imagesc(I)這種線性映射就可以用到整個色圖從而將圖像較好的顯示出來,這就是figure2中的顯示效果比figure1中好的原因。


 

imshow調用這個函數會把當前figurecolormap設置成gray256),這個前面也有提到,我們先討論矩陣元素是uint8型(范圍:0~255,整數,一般使用imread和 rgb2gray返回的都是uint8型的),同樣我們也要搞明白矩陣中的數和colormap中顏色索引的對應關系,imshow的功能是比較全的,它即可使用像image那樣的直接映射,也可使用像imagesc那樣的線性映射,當我們使用imshow(I),即只有一個矩陣作為參數,這時采用的是直接映射,比如矩陣中元素0就顯示成colormap中索引為1的顏色也就是黑色,矩陣中元素255就顯示成colormap中索引為256的顏色也就是白色,(注意:uint8范圍是0~255,而gray256)的索引是1:256,當然這些我們只要了解就可以了,編程並不會用到,因為這些對應的細節Matlab已經幫我們做好了)如果這樣調用imshow(I,[ ])此時矩陣中的數和顏色表就是線性映射,為什么會這樣,我解釋一下,我們看這種調用方式和imagesc(I,[1 64])很相似,其實原理是一樣的,第二個參數是一個向量,這個向量指定了矩陣中映射到顏色表的數的范圍,也就是顯示范圍(Matlab里叫做display range前面已經介紹了,Matlabimshowhelp中說如果采用imshow(I,[low high])調用imshow的話而且你用[ ]代替[low high]那么imshow會使用[min(I(:)) max(I(:))]作為顯示范圍,也就說I中的最小值會顯示成黑色,最大值會顯示成白色,這其實就是整個范圍的線性映射(沒有削頂也沒有削底),此時的imshow(I,[ ])函數就相當於imagesc(I);

 

為了說明imshow不僅具有image的功能也具有imagesc的功能,同時體會一下直接映射和線性映射的區別,我們來寫一段小程序來測試一下,程序如下:

 

[plain]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
 
 
  1. clear all;clc;close all;  
  2. img = imread('lenna.bmp');  
  3.    
  4. I = rgb2gray(img);  
  5.    
  6. figure(1),image(I); colormap(gray(256));  
  7. colorbar,title('show by image in figure1');axis off;  
  8. figure(2),imagesc(I);colormap(gray(256));  
  9. % We can see that the image showed in figure(2) is a little bright  
  10. % than in figure(1).  
  11. colorbar,title('show by imagesc in figure2');axis off;  
  12. % When we use the imshow, we do not need to set the colormap,  
  13. % because the imshow set the colormap to gray(256) automatically.  
  14. figure(3),imshow(I),colorbar,title('show by imshow(I) in figure3');  
  15. % The effectiveness in figure(3) is the same as in figure(1).  
  16. figure(4),imshow(I,[]),colorbar,title('show by imshow(I,[]) in figure3');  
  17. % 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、最后再說說imageimagesc,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型數據的圖像矩陣,主要區別如下:

imagedouble型數據取整(正數取整就是把小數部分舍掉)然后使用直接映射的方法按照顏色表顯示。

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))可以將整幅圖像的信息顯示出來。

 

綜上所述,大家根據自己實際需要選用顯示函數和對應的參數,這些是我自己研究學習的心得,表述難免有些疏漏,有發現嚴重錯誤的,可以給我留言,但可以給大家一個感性的認識,從雲里霧里的困境里走出來。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM