一个仿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

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