1. 程式人生 > >雙線性插值-影象旋轉

雙線性插值-影象旋轉

首先,什麼是雙線性插值?具體的說明大家可參照各種百科,我在這裡從影象角度來簡單講下,大體相似。

看下面這個圖


影象旋轉後,畫素點的整數座標必然會得到小數,顯然在影象的畫素點裡面是沒有小數座標的,那計算這些點的顏色值怎麼辦呢,為了保持準確性,我們把旋轉後的影象再旋轉回去,看這個點旋轉回去後在原圖上是否是整數座標,如果是,那沒問題,如果不是(即至少有一個座標是小數),假設這個點為P,我們可以用跟P點最近的四個點的顏色值的某種加權平均和來估計(Q幾個點均是在原圖上,是確實存在的,而P不存在)。如圖所示,P的周圍四點為Q11,Q12,Q21,Q22。Q11和Q21加權平均得到R1,Q12和Q22加權平均得到R2,再用R1,R2加權平均得到P,就OK啦。

怎麼加權平均?可用距離作為權值,而相鄰畫素點距離為1,那就更簡單了,具體見程式碼。

第二點就是怎麼計算旋轉的問題了,建議大家用矩陣來做,比較方便,同樣也是為了方便,關於旋轉矩陣,我轉載了一篇博文,就是下一篇《旋轉矩陣》供大家參考。

Rotation.m

%以影象中心為中心旋轉
theta=30;%自定義旋轉角度,順時針
angle=theta*pi/180;
a= cos(angle);
b= sin(angle);
rotation=[a,-b;b,a];%順時針旋轉矩陣
%rotation=[a,b;-b,a];%逆時針旋轉矩陣

A=imread('image_bmp\55.bmp');%讀入原影象,命名為A
h=size(A,1);
w=size(A,2);
A= double(A);%為了便於後面的計算,這裡強制轉換為double型,原影象為uint8型
newh=round(h*a+w*b);%重新計算旋轉以後的視窗的長和寬
neww=round(h*b+w*a);

for x = 1 : neww
   for y = 1 : newh
        t = rotation * [ y - newh / 2; x - neww / 2 ] + [ h / 2; w / 2 ];%t是一個兩行一列的座標矩陣,記錄旋轉後圖像返回到原圖中所在的位置
        %繼續上行的註釋:等式後面的是我已經計算簡化後的表示,中間過程大家可參考我那篇博文,動動筆計算一下就是我的結果
        if( t(1) >= 1 && t(2) >= 1 && t(1) <= h && t(2) <= w )%保證點落在原圖內
            m = floor( t(1) );%m,n表示位置t最近且最小的點的下標
            n = floor( t(2) );%由於鄰近畫素點在x,y方向上的距離均為1,顯然鄰近的其餘三個點分別為(m,n+1),(m+1,n),(m+1,n+1)
         
            d1 = A( m + 1, n, : ) * ( t(1) - m ) + A(m, n, : ) * ( 1 +m - t(1) );%d1,d2分別表示兩次加權和
            %這裡的加權大家注意下,我們用的是某個點的顏色值乘以離它更遠的那段距離,這樣交錯相乘,可以把P點如果有整數座標的情況都包含進來,程式更具一般性
            d2 = A( m + 1,n + 1, : ) * ( t(1) - m) + A(m, n + 1, : ) * ( 1 + m - t(1) );
            d = d2 * ( t(2) - n ) + d1 * ( 1 + n - t(2) );%根據新算出來的d1,d2再做一次加權,得到最終四個點的加權和d
            B( y, x, : ) = round(d);%把d的最近整數賦給B的RGB值,B是我們旋轉後的圖
       
        end
    end
end

B= uint8(B);
imshow(B);

原始影象:


效果圖: