《Computer Vision:Algorithms and Applications》學習筆記(一)——圖像旋轉算法與實現

http://www.cnblogs.com/mlv5/archive/2012/02/02/2336321.html


 昨天和今天學習了《Computer Vision:Algorithms and Applications》中第二章「Image formation」前半部分,主要是如何表示2D、3D圖像中的點、線、面等,以及如何用公式推導出2D圖形的幾何變換,如位移、旋轉、放縮、仿射變換、投射等,如下圖所示:

《Computer Vision:Algorithms and Applications》學習筆記(一)——圖像旋轉算法與實現_第1张图片

一、圖像旋轉方法簡介   

   其中的圖像旋轉是一種常用的數字圖像處理技術。由於旋轉後圖像像素點坐標不再是整數,所以旋轉後必須對新的像素點灰度值進行插值運算。目前常用的方法有最近鄰插值法、線性插值法和樣條插值法。文獻介紹,最近鄰法速度快,方法簡單,但生成圖像效果較差;樣條插值法計算精度高,效果好,但計算復雜,速度較慢;線性插值法(E.g. 雙線性插值法)效果較好,運行時間較短。另外,實現賦值的方法分為正向映射法和反向映射法:正向映射法是指,從原始圖像坐標出發,計算出在旋轉圖像上坐標,然後將原始圖像該坐標的灰度值賦給對應旋轉圖像該坐標點;反向映射法則反之。

     本文將分別采用基於最近鄰取值的正向映射法、基於最近鄰取值的反向映射法、基於雙線性插值的反向映射法實現圖像旋轉,並對比三種方法的效果。       

 

二、本文方法

1. 基於最近鄰取值的正向映射法

   這種方法最簡單,也最直觀,先考慮圖像旋轉原理:

以順時針旋轉為例來堆到旋轉變換公式。如下圖所示。

 

 

旋轉前:

x0=rcosby0=rsinb

旋轉a角度後:

x1=rcos(b-a)=rcosbcosa+rsinbsina=x0cosa+y0sina

y1=rsin(b-a)=rsinbcosa-rcosbsina=-x0sina+y0cosa

正向映射即根據原圖的坐標推導出旋轉圖像對應點坐標,然後直接將原圖坐標灰度值賦給x1,y1

 

2.基於最近鄰取值的反向映射法

《Computer Vision:Algorithms and Applications》學習筆記(一)——圖像旋轉算法與實現_第2张图片

旋轉前:

x1=rcoscy1=rsinc

旋轉a角度後:

x0=rcos(c+a)=rcosccosa-rsincsina=x1cosa-y1sina

y0=rsin(c+a)=rsinccosa+rcoscsina=-x1sina+y1cosa

反向映射即已知旋轉後圖像坐標,通過公式推導出原始圖像上對應坐標,將該坐標對應灰度值賦給旋轉後坐標。因為計算得到的y0, x0非整數,最近鄰方法即將與(Xo,Yo)距離最近的像素的灰度值作為(Xo,Yo)的灰度值賦給(X1,Y1)點。

 

3.基於雙線性插值的反向映射法

在計算(Xo,Yo)的灰度值時,采用如下方法計算:

《Computer Vision:Algorithms and Applications》學習筆記(一)——圖像旋轉算法與實現_第3张图片

《Computer Vision:Algorithms and Applications》學習筆記(一)——圖像旋轉算法與實現_第4张图片

 

三、實驗對比

     三種實驗結果的對比圖如下:

《Computer Vision:Algorithms and Applications》學習筆記(一)——圖像旋轉算法與實現_第5张图片

可見,雙線性插值法獲得的旋轉圖像更平滑,接近真實圖像。

 

三種方法的matlab代碼如下

复制代码
  1 Image=imread('E:\1.jpg');
  2 
  3 %X,Y為其行列數
  4 angle=30;
  5 %角度任意的一個數 表示30度
  6 pai=3.1415929657;
  7 Angle=pai*angle/180;
  8 %轉換一下角度的表示方法。
  9 [Y,X,Z]=size(Image);
 10 %原圖顯示
 11 subplot(2,2,1);
 12 imshow(Image);
 13 title('原圖像');
 14 
 15 % 
 16 %計算四個角點的新坐標,確定旋轉後的顯示區域
 17 LeftBottom(1,1)=(Y-1)*sin(Angle);
 18 LeftBottom(1,2)=(Y-1)*cos(Angle);
 19 
 20 LeftTop(1,1)=0;
 21 LeftTop(1,2)=0;
 22 
 23 RightBottom(1,1)=(X-1)*cos(Angle)+(Y-1)*sin(Angle);
 24 RightBottom(1,2)=-(X-1)*sin(Angle)+(Y-1)*cos(Angle);
 25 
 26 RightTop(1,1)=(X-1)*cos(Angle);
 27 RightTop(1,2)=-(X-1)*sin(Angle);
 28 
 29 %計算顯示區域的行列數
 30 Xnew=max([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)])-min([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)]);
 31 Ynew=max([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)])-min([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)]);
 32 
 33 % 分配新顯示區域矩陣
 34 ImageNewForward=zeros(round(Ynew),round(Xnew),3)+255;
 35 ImageNewIntersection=zeros(round(Ynew),round(Xnew),3)+255;
 36 ImageNew1nn=zeros(round(Ynew),round(Xnew),3)+255;
 37 
 38 %計算原圖像各像素的新坐標:正向映射法
 39 for indexX=0:(X-1)
 40     for indexY=0:(Y-1)
 41         Yn=1+round(-indexX*sin(Angle)+indexY*cos(Angle))+round(abs(min([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)])));
 42         Xn=round(indexX*cos(Angle)+indexY*sin(Angle))+round(abs(min([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)])))+1;
 43         ImageNewForward(Yn,Xn,1)=Image(indexY+1,indexX+1,1);
 44         ImageNewForward(Yn,Xn,2)=Image(indexY+1,indexX+1,2);
 45         ImageNewForward(Yn,Xn,3)=Image(indexY+1,indexX+1,3);
 46     end 
 47 end
 48 
 49 %%反向映射法
 50 for indexY=1:round(Ynew)
 51     for indexX=1:round(Xnew)
 52         Y1=indexY-round(abs(min([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)])));
 53         X1=indexX-round(abs(min([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)])));
 54         Yoo=X1*sin(Angle)+Y1*cos(Angle);
 55         Xoo=X1*cos(Angle)-Y1*sin(Angle);
 56         Yo=round(Yoo);
 57         Xo=round(Xoo);
 58         if 1<Xo&&Xo<X&&1<Yo&&Yo<Y
 59             %最近鄰法
 60             ImageNew1nn(indexY,indexX,1)=Image(Yo,Xo,1);
 61             ImageNew1nn(indexY,indexX,2)=Image(Yo,Xo,2);
 62             ImageNew1nn(indexY,indexX,3)=Image(Yo,Xo,3);
 63             
 64             %雙線性插值法
 65             left=floor(Xoo);
 66             right=ceil(Xoo);
 67             up=floor(Yoo);
 68             down=ceil(Yoo);
 69             
 70             upmid1=(1-Xoo+left)*Image(up,left,1)+(Xoo-left)*Image(up,right,1);
 71             downmid1=(1-Xoo+left)*Image(down,left,1)+(Xoo-left)*Image(down,right,1);
 72             upmid2=(1-Xoo+left)*Image(up,left,2)+(Xoo-left)*Image(up,right,2);
 73             downmid2=(1-Xoo+left)*Image(down,left,2)+(Xoo-left)*Image(down,right,2);
 74             upmid3=(1-Xoo+left)*Image(up,left,3)+(Xoo-left)*Image(up,right,3);
 75             downmid3=(1-Xoo+left)*Image(down,left,3)+(Xoo-left)*Image(down,right,3);
 76             central1=(1-Yoo+up)*upmid1+(Yoo-up)*downmid1;
 77             central2=(1-Yoo+up)*upmid2+(Yoo-up)*downmid2;
 78             central3=(1-Yoo+up)*upmid3+(Yoo-up)*downmid3;
 79             
 80             ImageNew(indexY,indexX,1)=central1;
 81             ImageNew(indexY,indexX,2)=central2;
 82             ImageNew(indexY,indexX,3)=central3;    
 83             
 84         else
 85              ImageNew(indexY,indexX,:)=255;
 86         end
 87     end
 88 end
 89 
 90 %顯示
 91 subplot(2,2,2);
 92 ImageNewForward=uint8(ImageNewForward);
 93 imshow(ImageNewForward);
 94 promp=['旋轉角度為:' int2str(angle) '度圖像 正向映射法'];
 95 title(promp);
 96 
 97 subplot(2,2,3);
 98 ImageNew1nn=uint8(ImageNew1nn);
 99 imshow(ImageNew1nn);
100 promp=['旋轉角度為:' int2str(angle) '度圖像 最近鄰插值法'];
101 title(promp);
102 
103 subplot(2,2,4);
104 ImageNew=uint8(ImageNew);
105 imshow(ImageNew);
106 promp=['旋轉角度為:' int2str(angle) '度圖像 雙線性插值法'];
107 title(promp);
复制代码



參考文獻:

1. 《Computer Vision:Algorithms and Applications》,pp30-40

2. 曹佃國, 陳浩傑,李鵬, "基於 Matlab 雙線性插值算法圖像旋轉中應用".


你可能感兴趣的:(算法,image,matlab,UP)