在對圖像進行空間變換的過程中,典型的情況是在對圖像進行放大處理的時候,圖像會出現失真的現象。這是由於在變換之后的圖像中,存在着一些變換之前的圖像中沒有的像素位置。為了說明這個問題,不妨假設有一副大小為64x64的灰度圖像A,現在將圖像放大到256x256,不妨令其為圖像B,如圖1所示。顯然,根據簡單的幾何換算關系,可以知道B圖像中(x,y)處的像素值應該對應着A圖像中的(x/4,y/4)處的象素值,即
B(x,y) = A(x/4,y/4) (式1)
對於B中的(4,4),(4,8),(4,16)…(256,256)這些位置,通過式1就可以計算出其在A中的位置,從而可以得到灰度值。但是,對於B中的(1,1),(1,2),(1,3)…等等這些坐標點而言,如果按照式1計算的話,那么它們在A中對應的坐標不再是整數。比如,對於B中的坐標點(1,1),其在A中的對應坐標就變成了(0.25,0.25)。對於數字圖像而言,小數坐標是沒有意義的。因此,必須考慮采用某種方法來得到B中像素點在A中對應位置上的灰度級。處理這一問題的方法被稱為圖像灰度級插值。常用的插值方式有三種:最近鄰域插值、雙線性插值、雙三次插值。理論上來講,最近鄰域插值的效果最差,雙三次插值的效果最好,雙線性插值的效果介於兩者之間。不過對於要求不是非常嚴格的圖像插值而言,使用雙線性插值通常就足夠了。
本文中將采用matlab實現一個雙線性插值的程序。雙線性插值的原理如圖2所示。圖像之間坐標映射有兩種方式:如果是從原圖像的坐標映射到目標圖像,稱為前向映射,反之則稱為后向映射。顯然,雙線性插值采用的是后向映射方式。下面對圖2的具體含義進行說明。首先,根據幾何關系,從B圖像中的坐標(x,y)得到A圖像中的坐標(x/4,y/4),但是,映射得到的這個坐標(x/4,y/4)並沒有剛好位於A圖像中的整數坐標上,而是映射到了四個像素坐標(a,b)、(a+1,b)、(a,b+1)、(a+1,b+1)所圍成的矩形之間,其中,a、b是A圖像的整數坐標。現在的問題就是如何根據A(a,b)、A(a+1,b)、A(a,b+1)、A(a+1,b+1)這四個點上的灰度級求出A(x/4,y/4)處的灰度級。雙線性插值技術采用的方法是:假設A圖像的灰度級變化在縱向方向上是線性變化的,這樣根據直線方程或者幾何比例關系就能夠求得(a,y/4)和(a+1,y/4)坐標處的灰度級A(a,y/4)和A(a+1,y/4)。然后,再假設在((a,y/4),A(a,y/4))和(a+1,y/4),A(a+1,y/4))這兩點所確定的直線上,灰度級仍然是線性變化的。求出直線方程,於是就可以求得(x/4,y/4)處的灰度級A(x/4,y/4)。這就是雙線性插值的基本思路。其中用到的兩個基本假設是:首先灰度級在縱向方向上是線性變化的,然后假定灰度級在橫向方向上也是線性變化的。
圖1 圖像縮放示意圖
圖2 雙線性插值示意圖
附錄:
I=imread('image1.bmp'); [m,n]=size(I); K=3; width = K * m; height = K * n; J = uint8(zeros(width,height)); % width scale and height scale widthScale = m/width; heightScale = n/height; % bilinear interplot for x = 5:width - 5 for y = 5:height - 5 xx = x * widthScale; yy = y * heightScale; if (xx/double(uint16(xx)) == 1.0) & (xx/double(uint16(xx)) == 1.0) J(x,y) = I(int16(xx),int16(yy)); else % a or b is not integer a = double(uint16(xx)); % (a,b) is the base-dot b = double(uint16(yy)); x11 = double(I(a,b)); % x11 <- I(a,b) x12 = double(I(a,b+1)); % x12 <- I(a,b+1) x21 = double(I(a+1,b)); % x21 <- I(a+1,b) x22 = double(I(a+1,b+1)); % x22 <- I(a+1,b+1) J(x,y) = uint8( (b+1-yy) * ((xx-a)*x21 + (a+1-xx)*x11) + (yy-b) * ((xx-a)*x22 +(a+1-xx) * x12)); % calculate J(x,y) end end end % 顯示圖像 imwrite(J, '放大的圖像.jpg', 'jpg'); imshow(I),title('原圖'); figure imshow(J),title('放大圖');
I=imread('image1.bmp'); [m,n]=size(I); K=3; width = K * m; height = K * n; J = uint8(zeros(width,height)); % width scale and height scale widthScale = m/width; heightScale = n/height; % bilinear interplot for x = 5:width - 5 for y = 5:height - 5 xx = x * widthScale; yy = y * heightScale; if (xx/double(uint16(xx)) == 1.0) & (xx/double(uint16(xx)) == 1.0) J(x,y) = I(int16(xx),int16(yy)); else % a or b is not integer a = double(uint16(xx)); % (a,b) is the base-dot b = double(uint16(yy)); x11 = double(I(a,b)); % x11 <- I(a,b) x12 = double(I(a,b+1)); % x12 <- I(a,b+1) x21 = double(I(a+1,b)); % x21 <- I(a+1,b) x22 = double(I(a+1,b+1)); % x22 <- I(a+1,b+1) J(x,y) = uint8( (b+1-yy) * ((xx-a)*x21 + (a+1-xx)*x11) + (yy-b) * ((xx-a)*x22 +(a+1-xx) * x12)); % calculate J(x,y) end end end % 顯示圖像 imwrite(J, '放大的圖像.jpg', 'jpg'); imshow(I),title('原圖'); figure imshow(J),title('放大圖');