前一陣子,老師留了一個課後題,大致就是題目所說的效果,就用matlab來實現了一下,最後效果還算不錯,只是可能是matlab循環效率問題,還有自己代碼沒有再進一步優化的原因,可能致使程序運行有點慢,希望同志們能給點建議,謝謝。
代碼見下:
自己將代碼封裝成一個子函數change()
大體思路就是:
1)根據外界給的起點和終點的座標,求解出此方向的單位向量a=[ax ay]表示;
注意:通過對向量a的ax及ay的正負性判斷,決定圖像的迭代方向
2)在方向向量求解出來的情況下,分別根據距離此單位向量a的平行距離ax和垂直距離ay,求解出變形程度(當然前提是點必須在圓內!);
注意:此處迭代思想大致可以這麼理解:
若有一條直線,在前向變形的作用下,肯定會變成下面的曲線b_line。
這樣的話,原圖上的A、B、C三點就映射到變形後圖上的A‘、B’、C‘三點。
現在假設A、B、C三點的座標分別爲(Ax,Ay)(Bx,By) (Cx,Cy) (同時Ay=By=Cy,即原直線爲一水平直線)
那麼ABC三點的座標分別爲(Ax,Ay+a)(Bx,By+b) (Cx,Cy+c),也就是說反過來看,曲線上點的灰度或者其他RGB分量可以根據他們前一個點的灰度或者RGB分量獲得(此例中,前面的點由當前點減去a/b/c這樣的增量得到)
也就是說,如果假定A A’之間有一點A'',那麼A點的值可以間接的由A''獲得,而A''的值由A點獲得。可能大家覺得這樣做沒有必要,但是你想一想,如果A點距離A‘點太遠,就會出現這樣的情況:根據A點算出的A'點已經不再圖像的範圍ie之內,也就無法獲得準確的值。合理控制迭代距離,會使得圖像變形效果更好。
至於不是特殊情況(水平、垂直)下,映射如何建立,參見下面的程序代碼。
3) 還有就是,弧線的形變程度也需要人爲控制(其實說得直白點,就是設定ax和ay的影響權係數)。
4)多次試驗後,發現迭代距離取5比較合適,還有就是計算出的A'點不一定爲整數點,這裏還要用插值估計下(本實驗採用雙線性插值)。
附上代碼:
change.m
%I爲原圖的rgb矩陣,sp爲起點座標,fp爲矩陣的終點座標,rm爲半徑,s爲形變程度(0<s<1) function J=change(I,sp,fp,rm,s); J=I; [ym xm]=size(rgb2gray(I)); %sp=[35 480];%起點 %fp=[1 40];%終點 %rm=100;%半徑 %s=0.75; p=sp; zz=sp-fp; z2=sqrt(zz(1)^2+zz(2)^2); danwei=zz/z2;%單位向量 x1=1;x2=1;%表明迭代方向,負值代表遞減迭代 if danwei(1)<0 x1=-1;end if danwei(2)<0 x2=-1;end for k=1:10 %迭代次數根據起點終點而定 yma=floor(min(p(1)+rm,ym));ymi=floor(max(1,p(1)-rm)); xma=floor(min(p(2)+rm,xm));xmi=floor(max(1,p(2)-rm));%四個邊界值 sm1=ymi;sm2=yma;sn1=xmi;sn2=xma;ii=1;jj=1; if x1<0 sm1=yma;sm2=ymi;ii=-1;end if x2<0 sn1=xma;sn2=xmi;jj=-1;end for i=sm1:ii:sm2%need for j=sn1:jj:sn2%need d2=(p(1)-i)^2+(p(2)-j)^2; if d2 <= rm^2 ab=[p(1)-i,p(2)-j]; py=abs(ab*danwei');%平行於移動方向 px=sqrt(d2-py^2);%垂直於移動方向 fmn=5*(1-(1/rm)*sqrt(s*px^2+(1-s)*py^2))*danwei+[i,j]; fm=fmn(1);fn=fmn(2); if(fm<1||fm>ym||fn<1||fn>xm) else km=fm-floor(fm);kn=fn-floor(fn); J(i,j,:)=(1-kn)*(km*J(floor(fm)+1,j,:)+(1-km)*J(floor(fm),j,:))+kn*(km*J(floor(fm)+1,j+1,:)+(1-km)*J(floor(fm),j+1,:)); end end end end p=p+5*danwei;%實驗測試發現取-5得到的效果爲最佳 end
現在打開matlab命令窗口寫上:
I=imread('tigger.jpg'); sp=[400,600];%起點座標 fp =[200,300];%終點座標 rm=100;s=0.75; J=change(I,sp,fp,rm,s); figure;imshow(I); figure;imshow(J);%顯示變形後的圖像
變換後如下:
有什麼錯誤及更好的方法,請多多指正。
轉載請指明出處http://www.cnblogs.com/blue-lg/archive/2011/12/09/2282631.html