Matlab中image、imagesc和imshow函式用法解析
原文轉自:http://blog.csdn.net/zhupananhui/article/details/16340345
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))可以將整幅影象的資訊顯示出來。
綜上所述,大家根據自己實際需要選用顯示函式和對應的引數,這些是我自己研究學習的心得,表述難免有些疏漏,有發現嚴重錯誤的,可以給我留言,但可以給大家一個感性的認識,從雲裡霧裡的困境裡走出來。