前一阵子,老师留了一个课后题,大致就是题目所说的效果,就用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