一、顯示RGB圖像算法
相同點:這三個函數都是把m*n*3的矩陣中的數值當作RGB值來顯示的。編程
區別:imshow將圖像以原始尺寸顯示,image和imagesc則會對圖像進行適當的縮放(顯示出來的尺寸大小)。小程序
二、顯示灰度圖像數據結構
說明:先搞明白什麼是索引圖像?(灰度圖像也是索引圖像的一種)函數
當用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],下面咱們結合具體實例來看看這三個函數的調用效果,並解釋緣由。代碼:ui
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');
顯示效果:this
咱們看到現象是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中則出現了大面積的紅色的區域,人物的輪廓被抹掉了不少。spa
爲何會出現這樣的狀況呢?這就要說說索引圖像矩陣中的數(如下簡稱矩陣中的數)和colormap中的索引(index)的對應關係了。.net
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)。
三、最後再說說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))能夠將整幅圖像的信息顯示出來。