有好多算法早就想實現了,可是總有各種原因沒有實現,這個雙線性插值旋轉圖像就是其中之一。
之前寫過最鄰近插值旋轉圖像,結合着看效果會很好。
1 clear all; 2 close all; 3 clc; 4
5 jiaodu=45; %要旋轉的角度,旋轉方向為順時針 6 img=imread('lena.jpg'); %這里v為原圖像的高度,u為原圖像的寬度 7 imshow(img); %這里y為變換后圖像的高度,x為變換后圖像的寬度 8 [h w]=size(img); 9
10 theta=jiaodu/180*pi; 11 rot=[cos(theta) -sin(theta) 0;sin(theta) cos(theta) 0;0 0 1]; 12 pix1=[1 1 1]*rot; %變換后圖像左上點的坐標 13 pix2=[1 w 1]*rot; %變換后圖像右上點的坐標 14 pix3=[h 1 1]*rot; %變換后圖像左下點的坐標 15 pix4=[h w 1]*rot; %變換后圖像右下點的坐標 16
17 height=round(max([abs(pix1(1)-pix4(1))+0.5 abs(pix2(1)-pix3(1))+0.5])); %變換后圖像的高度 18 width=round(max([abs(pix1(2)-pix4(2))+0.5 abs(pix2(2)-pix3(2))+0.5])); %變換后圖像的寬度 19 imgn=zeros(height,width); 20
21 delta_y=abs(min([pix1(1) pix2(1) pix3(1) pix4(1)])); %取得y方向的負軸超出的偏移量 22 delta_x=abs(min([pix1(2) pix2(2) pix3(2) pix4(2)])); %取得x方向的負軸超出的偏移量 23
24 for i=1-delta_y:height-delta_y 25 for j=1-delta_x:width-delta_x 26 pix=[i j 1]/rot; %用變換后圖像的點的坐標去尋找原圖像點的坐標, 27 %否則有些變換后的圖像的像素點無法完全填充 28 float_Y=pix(1)-floor(pix(1)); 29 float_X=pix(2)-floor(pix(2)); 30
31 if pix(1)>=1 && pix(2)>=1 && pix(1) <= h && pix(2) <= w 32
33 pix_up_left=[floor(pix(1)) floor(pix(2))]; %四個相鄰的點 34 pix_up_right=[floor(pix(1)) ceil(pix(2))]; 35 pix_down_left=[ceil(pix(1)) floor(pix(2))]; 36 pix_down_right=[ceil(pix(1)) ceil(pix(2))]; 37
38 value_up_left=(1-float_X)*(1-float_Y); %計算臨近四個點的權重 39 value_up_right=float_X*(1-float_Y); 40 value_down_left=(1-float_X)*float_Y; 41 value_down_right=float_X*float_Y; 42
43 imgn(i+delta_y,j+delta_x)=value_up_left*img(pix_up_left(1),pix_up_left(2))+ ... 44 value_up_right*img(pix_up_right(1),pix_up_right(2))+ ... 45 value_down_left*img(pix_down_left(1),pix_down_left(2))+ ... 46 value_down_right*img(pix_down_right(1),pix_down_right(2)); 47 end 48
49 end 50 end 51
52 figure,imshow(uint8(imgn))
原圖
最鄰近插值旋轉
雙線性插值旋轉
后記:
上面的無法通過極限情況,如果旋轉為90度或180度,邊界會有黑像素。修改如下:
main.m
1 clear all; 2 close all; 3 clc; 4
5 jiaodu=90; %要旋轉的角度,旋轉方向為順時針 6 img=imread('lena.jpg'); %這里v為原圖像的高度,u為原圖像的寬度 7 imshow(img); %這里y為變換后圖像的高度,x為變換后圖像的寬度 8 [h w]=size(img); 9
10 theta=jiaodu/180*pi; 11 rot=[cos(theta) -sin(theta) 0;sin(theta) cos(theta) 0;0 0 1]; 12 pix1=[1 1 1]*rot; %變換后圖像左上點的坐標 13 pix2=[1 w 1]*rot; %變換后圖像右上點的坐標 14 pix3=[h 1 1]*rot; %變換后圖像左下點的坐標 15 pix4=[h w 1]*rot; %變換后圖像右下點的坐標 16
17 height=round(max([abs(pix1(1)-pix4(1))+0.5 abs(pix2(1)-pix3(1))+0.5])); %變換后圖像的高度 18 width=round(max([abs(pix1(2)-pix4(2))+0.5 abs(pix2(2)-pix3(2))+0.5])); %變換后圖像的寬度 19 imgn=zeros(height,width); 20
21 delta_y=abs(min([pix1(1) pix2(1) pix3(1) pix4(1)])); %取得y方向的負軸超出的偏移量 22 delta_x=abs(min([pix1(2) pix2(2) pix3(2) pix4(2)])); %取得x方向的負軸超出的偏移量 23
24 imgm=img_extend(img,1); %擴展邊界得到的圖像 25
26 for i=1-delta_y:height-delta_y 27 for j=1-delta_x:width-delta_x 28 pix=[i j 1]/rot; %用變換后圖像的點的坐標去尋找原圖像點的坐標, 29 %否則有些變換后的圖像的像素點無法完全填充 30 float_Y=pix(1)-floor(pix(1)); 31 float_X=pix(2)-floor(pix(2)); 32
33 if pix(1)>=-1 && pix(2)>=-1 && pix(1) <= h+1 && pix(2) <= w+1
34
35 pix_up_left=[floor(pix(1)) floor(pix(2))]; %四個相鄰的點 36 pix_up_right=[floor(pix(1)) ceil(pix(2))]; 37 pix_down_left=[ceil(pix(1)) floor(pix(2))]; 38 pix_down_right=[ceil(pix(1)) ceil(pix(2))]; 39
40 value_up_left=(1-float_X)*(1-float_Y); %計算臨近四個點的權重 41 value_up_right=float_X*(1-float_Y); 42 value_down_left=(1-float_X)*float_Y; 43 value_down_right=float_X*float_Y; 44
45 imgn(i+delta_y,j+delta_x)=value_up_left*imgm(pix_up_left(1)+2,pix_up_left(2)+2)+ ... 46 value_up_right*imgm(pix_up_right(1)+2,pix_up_right(2)+2)+ ... 47 value_down_left*imgm(pix_down_left(1)+2,pix_down_left(2)+2)+ ... 48 value_down_right*imgm(pix_down_right(1)+2,pix_down_right(2)+2); 49 end 50
51 end 52 end 53
54 figure,imshow(uint8(imgn))
img_extend.m
1 function imgm=img_extend(img,r) 2 [m n]=size(img); 3
4 imgm=zeros(m+2*r+1,n+2*r+1); 5
6 imgm(r+1:m+r,r+1:n+r)=img; 7 imgm(1:r,r+1:n+r)=img(1:r,1:n); 8 imgm(1:m+r,n+r+1:n+2*r+1)=imgm(1:m+r,n:n+r); 9 imgm(m+r+1:m+2*r+1,r+1:n+2*r+1)=imgm(m:m+r,r+1:n+2*r+1); 10 imgm(1:m+2*r+1,1:r)=imgm(1:m+2*r+1,r+1:2*r); 11
12 end