0、小敘閑言
續第一章之后,對數字圖像和圖像處理略有了解。第二章內容有不少,書中編寫了很多的函數,還是一樣,只要沉下心看看,理清楚結構,看明白功能,個人覺得很容易看明白。同時書中的代碼都有很多的注釋,更加減少我們看代碼的難度。耐心,靜心,定會有所收獲。
1、本章整體結構
本章內容很多,也有很多的數學知識,個人在學習的時候,碰到了好多困難,畢竟不是科班出生,而且也沒有學習過數字信號處理,還好,線性代數和概率論學得還可以,但依舊有不少不理解的地方。下面也只能整理一下書中的知識要點,以后有新的領悟再來更新,看下面一章,關於離散傅里葉變換,好像更難。
2、書中例子
例2.1 主要是使用函數imadjust,來熟悉一下灰度處理,體驗一把
>> imread('myimage.jpg'); >> f=imread('myimage.jpg'); >> g1 = imadjust(f, [0 1], [1 0]); >> imshow(g1); >> imshow(f); >> g2 = imadjust(f, [0.5 0.75], [0 1]); >> figure;imshow(g2); >> g3 = imadjust(f, [], [],2); >> figure;imshow(g3);
處理前后效果,還可以,f到g1的變換,就是對像素值進行了反轉,也就是書中所講的負片效果,對醫學很有用。
g2圖是將[0.5 0.75]間的像素線性變換到[0 1]之間,也就是進行了放大。那么這里有點疑問,我們的圖像像素幅值區間不可能只是有[0.5 0.75],這個參數的意義到底是什么呢?我對書中的理解如下,上面圖中所用到的是uint8類型圖像,因此圖像幅值區間是[0 255],有一點編程基礎的都應該清楚。所以對應uint8類型,它的實際區間為[0.5 0.75]*255=[127.5 191.25]。如果是對應是uint16類型,那么他的實際區間為[0.5 0.75]*(2^16-1)=[32767 49151],也就是只取區間[32767 49151]像素幅值。再回到imadjust(f, [0.5 0.75], [0 1]),也就是將區間[127.5 191.25]映射到[0 255],怎么一個映射法呢?默認的就是線性對應,由兩點(兩個區間形成兩點)確定一條直線。如下圖所示:
那么問題又來了,如果是區間[0.5 0.75]映射到[1 0]又是如何理解的呢,其實是一樣的道理,做好點對點的對應關系,求出線性函數即可。如下圖所示的對應關系,這也就解釋了g1圖效果的原因,從[0 1]映射到[1 0],就是斜率為-1,x取值范圍為[0 255],完全就是一個線性明暗反轉操作。
Low_High=strechlim(f),就是幫我們找到圖像f中的像素幅值的最大值和最小值,如果f是一個單值圖像,那么Low_High就是一個行向量(1*2的矩陣),如果f是一個彩色圖像,那么Low_High就是一個3*2的矩陣。當我們找到f圖像的最小,最大像素幅值后,再將其映射到整個像素區間[0 1],也就是書中所講,實現對比度拉伸,可以得到不錯的效果。如下圖,從A圖到D圖,D圖就是使用了strechlim(f),然后使用D=imadjust(f,Low_High,[0 1]);得到的圖像,很是清晰。
書中的一個tofloat函數,很短,但寫得很棒,我讀了一下,並添加了一些自己的注釋,代碼如下。
1 function [out, revertclass] = tofloat(in) 2 %out=輸入的圖像參數(in)轉化為float型數據點 3 %revertclass=一個函數句柄可以將類型轉回去 4
5 identity = @(x) x; %一個匿名函數的句柄,表示自身 6 tosingle = @im2single; %普通函數句柄 理解為函數指針也行 7 tabel = { 8 'uint8', tosingle, @im2uint8 9 'uint16', tosingle, @im2uint16 10 'int16', tosingle, @im2uint16 11 'int16', tosingle, @logical 12 'double', identity, identity 13 'single', identity, identity 14 }; 15 %在單元矩陣的第1列中找到輸入參數類型的名字 16 classIndex = find(strcmp(class(in), tabel(:, 1))); 17
18 if isempty(classIndex) 19 error('Unspported input image class.'); 20 end 21 %在單元矩陣的第2列中找到索引處轉為flaot型的函數句柄,進行轉換 22 out = tabel{classIndex, 2}(in); 23 %在單元矩陣的第3列中找到索引處反轉為原來類型函數句柄,進行轉換 24 revertclass = tabel{classIndex, 3};
運用例中的代碼做兩個圖看看,練練手,效果如下:
h=imhist(f,25); horz = linspace(0,255,25); subplot(1,2,1);bar(horz,h); subplot(1,2,2);stem(horz, h, 'fill');
3、個人對書中一些知識的理解
書中intrans函數的的結構如下,書中寫了比較長的代碼,但並不復雜。只是在下面結構基礎上添加了一些邏輯判斷,增加了代碼的長度,算法不復雜。
本質就是對前面灰度變換方法的一個綜合,書中函數代碼寫了很長,其實都很容易,大部分代碼都是在做一個判斷,減少函數的bug。
書中重新編寫的g = gscale(f, method, low, high)函數,也就是實現前文所講的,灰度全尺度拉伸變換,個人覺得其實配合,stretchlim函數和imadjust可以輕松完成此功能。
心得總結
學習本章,深深感受好數學功底太重要了,很多理論如果對數學沒有一定的了解,很難理解原理。只能掌握一些關於圖像處理的方法。這跟當年學習單片機是一樣的,很多的電路原理都不太清楚,但是照着別人的方法和步驟來編程,一樣可以取得想要的效果。當使用單片機多了,接觸得更多了,慢慢以也就理解了。目前學習數字圖像處理的我,正像是當年第一次接觸單片機一樣。很多圖像處理的算法,雖然書上說了,但我還是不理解,只能照着書上的來,然后也得到了書上的效果。
在知乎上搜索如何學習數字圖像處理這一話題時,有很多人跟我一樣,也是不能理解其中的算法原理,有一些知乎的大神也給出了建議,第一次學習,書中諸多難以理解的算法,暫且可不用刨根問底。先掌握數字圖像處理這一技能,而后理解數字圖像處理這一心法,最后化為自己的內功。自身不是天才,無法一次就能掌握。