一個仿ps液化效果(前傾變形)的matlab程序

前一陣子,老師留了一個課後題,大致就是題目所說的效果,就用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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章