matlab练习程序(动感模糊)
其实在matlab中调用系统函数fspecial和imfilter这两个函数就能很简单的实现动感模糊,不过我可不想就这样简单的实现,所以就自己从头写了。动感模糊最复杂的就是构造卷积矩阵了,卷积矩阵由两个参数决定,模糊半径r和模糊角度theta,通过这两个参数,就能构造不同的模板矩阵,而图像卷积时则和普通的卷积没有什么区别。
构造模板矩阵,首先是通过模糊半径r确定模板矩阵的宽和高,这里需要用到勾股定理,这里的r其实就相当于勾股定理中的弦,也就是斜边,那么模板的高就是r*sin(theta),宽就是r*cos(theta),为了下面卷积的方便,判断这里的宽和高,把不是奇数的加1变为奇数。然后是通过theta确定模板矩阵中数据的位置,这里只要符合h=w*tan(theta)这样一个关系的位置就都赋值r,然后对矩阵归一化就行了。当然,边界处理的细节就看下面的代码吧。
上面是我构造矩阵的方法,和matlab与photoshop都不一样,不太清楚他们是怎样构造的,photoshop是完全不清楚,matlab是分析不出来。维基百科上有一个构造公式:http://zh.wikipedia.org/wiki/%E5%8B%95%E6%85%8B%E6%A8%A1%E7%B3%8A,不过我试了试,用这种方法好像构造不出来,if的第二个条件我不太清楚意义是什么。
下面是代码:
clear all; close all; clc; r=50; %模糊半径 jiaodu=-45; %模糊角度 jiaodu=mod(jiaodu,360); %经过这个处理,对所有角度均适用了。 flag=0; %%下面是把卷积模板做出来。 if jiaodu>=0 && jiaodu<90 jiaodu=jiaodu; flag=1; end if jiaodu>=90 && jiaodu<180 jiaodu=180-jiaodu; flag=2; end if jiaodu>=180 && jiaodu<270 jiaodu=jiaodu-180; flag=3; end if jiaodu>=270 && jiaodu<360 jiaodu=360-jiaodu; flag=4; end H=floor(r*sin(jiaodu*pi/180)); W=floor(r*cos(jiaodu*pi/180)); if mod(H,2)==0 H=H+1; end if mod(W,2)==0 W=W+1; end w=zeros(H,W); if jiaodu ~= 90 && jiaodu ~= 270 for i=1:H for j=1:W tmp=floor(j*tan(jiaodu*pi/180)); if tmp+1==i w(i,j)=r; end end end else for i=1:H w(i,1)=r; end end w=w/sum(sum(w)); if flag==1 || flag==3 %如果角度在1,3象限,卷积矩阵上下翻转 w=flipud(w); end %%下面是正常的图像处理,卷积等 HH=floor(H/2); WW=floor(W/2); img=imread('lena.jpg'); img=double(img); [m n]=size(img); imshow(mat2gray(img)); imgn=zeros(m+2*HH+1,n+2*WW+1); imgn(HH+1:m+HH,WW+1:n+WW)=img; imgn(1:HH,WW+1:n+WW)=img(1:HH,1:n); imgn(1:m+HH,n+WW+1:n+2*WW+1)=imgn(1:m+HH,n:n+WW); imgn(m+HH+1:m+2*HH+1,WW+1:n+2*WW+1)=imgn(m:m+HH,WW+1:n+2*WW+1); imgn(1:m+2*HH+1,1:WW)=imgn(1:m+2*HH+1,WW+1:2*WW); for i=HH+1:m+HH for j=WW+1:n+WW s=imgn(i-HH:i+HH,j-WW:j+WW).*w; imgn(i,j)=sum(sum(s))/sum(sum(w)); end end figure; img=imgn(HH+1:m+HH,WW+1:n+WW); imshow(mat2gray(img));
下面是效果:
原图
这里的处理效果,半径为50,角度为-45度
photoshop中相同参数的处理效果。