MATLAB程序大全Word格式.docx
《MATLAB程序大全Word格式.docx》由会员分享,可在线阅读,更多相关《MATLAB程序大全Word格式.docx(67页珍藏版)》请在冰点文库上搜索。
theta=atan2(dis_y,dis_x);
end
ify<
theta=pi+atan2(-dis_y,-dis_x);
end
ify==re_m/2
theta=atan2(dis_y,dis_x)+0.0001;
xx=ceil(n*theta/(2*pi));
yy=ceil(l-r1);
ifyy>
=1&
yy<
=m&
xx>
xx<
=n
imgn(y,x)=img(yy,xx);
end
figure;
imshow(imgn,[])
最后要说的是,一般我们要是有一张全景图,通常会用cubic映射,将图像变换为立方体的六个面,然后通过图形学方法贴到立方体上,就能做出类似谷歌街景的样子。
cubic映射应该才是全景图最常用的处理方法,不过那又是另一类变换了。
2.GUI保存图像
%---Executesonbuttonpressinpushbutton5.
functionpushbutton5_Callback(hObject,eventdata,handles)
%hObjecthandletopushbutton5(seeGCBO)
%eventdatareserved-tobedefinedinafutureversionofMATLAB
%handlesstructurewithhandlesanduserdata(seeGUIDATA)
globalsrc_img;
[filename,pathname]=uiputfile({'
*.jpg'
;
'
*.bmp'
*.gif'
*.png'
*.tif'
},'
WritePic'
str=[pathnamefilename];
ifstr~=0
imwrite(src_img,str);
3.GUI读入图像
%---Executesonbuttonpressinpushbutton1.
functionpushbutton1_Callback(hObject,eventdata,handles)
%hObjecthandletopushbutton1(seeGCBO)
[filename,pathname]=uigetfile({'
*.*'
},'
ReadPic'
str=[pathnamefilename];
if~isequal([pathname,filename],[0,0])
src_img=imread(str);
axes(handles.axes1);
imshow(src_img);
4.GUI选项卡
1.在这个下载一个工具包,里面应该有四个文件:
tabselectionfcp.p、tabselectionfcn.m、tabpanel.p和tabpanel.m,显然代码用.p格式进行加密了。
2.建立一个空GUI文件,就起名kong.fig吧。
3.在kong.fig上画一个StaticText,默认的tag为text1。
4.终端运行tabpanel('
kong.fig'
'
text1'
命令,得到如下界面:
5.点击addpanel就能添加选项卡了,如图:
6.选中不同的选项卡,点击edit,就能进入常见的GUI编辑模式:
7.编辑完保存下就行了,所有的功能都在kong.m文件中实现。
注意,不同选项卡添加的组建时,tag会有重复,因此需要修改tag名。
8.终端输入kong就能得到如下结果:
5.structuretensor结构张量
根据结构张量能区分图像的平坦区域、边缘区域与角点区域。
此算法也算是之一了。
链接的文章中此算法名称为Strukturtensor算法,不过我搜索了一下,Strukturtensor这个单词好像是德语,翻译过来就是structuretensor结构张量了。
此处所说的张量不是相对论或黎曼几何里的张量,黎曼几何的张量好多论文都叫张量场了。
也不是数学界还没研究明白的对矩阵进行扩展的高阶张量,主要是张量分解。
这里的结构张量就是一个矩阵,一个对图像像素进行组织的数据结构而已。
像素组织而成的矩阵如下:
这个公式太常见了,在中就用到了。
其中Ix,Iy就是原对原图像在x和y方向求得的偏导。
然后求矩阵E的行列式K和迹H。
然后根据K和H的关系就能区分图像的区域模式了。
模式分以下三类:
平坦区域:
H=0;
边缘区域:
H>
0&
K=0;
角点区域:
K>
0;
harris角点检测就用到了第三类判断。
当然,在实际应用的时候H和K的值肯定都不会是理想,所以我用的都是近似判断。
处理结果如下:
角点区域(好像也不全角点,求角点还是harris好了):
结构张量行列式与迹的关系:
其中红框为平坦区域,黄框为边缘区域,铝框为角点区域。
closeall;
clc;
img=double(imread('
lena.jpg'
));
[mn]=size(img);
imshow(img,[])
[IxIy]=gradient(img);
Ix2=Ix.^2;
Iy2=Iy.^2;
Ixy=Ix.*Iy;
k=1;
lambda=zeros(m*n,2);
fori=1:
m
forj=1:
n
st=[Ix2(i,j)Ixy(i,j);
Ixy(i,j)Iy2(i,j)];
%结构张量
K=det(st);
%求行列式
H=trace(st);
%求迹
%所有的判断都是近似的
%ifH<
50%认为是平坦区域
%ifH>
50&
abs(K)<
0.01*10^(-9)%认为是边缘区域
ifH>
abs(K)>
0.01*10^(-9)%认为是角点区域
img(i,j)=255;
lambda(k,:
)=[KH];
k=k+1;
plot(lambda(:
1),lambda(:
2),'
.'
ylabel('
trace'
xlabel('
det'
6.模糊集图像增强
算法有很多变种。
不过主要就是以下三步。
1.设计隶属度函数将图像从空间域变换到模糊集域。
2.设计模糊增强算子,在模糊集域对图像进行处理。
3.根据第1步的隶属度函数重新将图像从模糊集域变换到空间域。
这和频域处理中的变换反变换不是很像么。
我使用的隶属度函数和模糊增强算子在里,也算相关算法的经典论文了。
模糊集增强后:
Fe=1;
%控制参数
Fd=128;
xmax=max(max(img));
u=(1+(xmax-img)/Fd).^(-Fe);
%空间域变换到模糊域
%也可以多次迭代
m%模糊域增强算子
n
ifu(i,j)<
0.5
u(i,j)=2*u(i,j)^2;
else
u(i,j)=1-2*(1-u(i,j))^2;
img=xmax-Fd.*(u.^(-1/Fe)-1);
%模糊域变换回空间域
imshow(uint8(img));
7.随机游走图像
随机游走类似布朗运动,就是随机的向各个方向走吧。
虽然代码没什么技术含量,不过产生的图像实在太漂亮了,所以还是贴上来吧。
产生的图像:
clc
n=70000;
%游走的步数。
也是图像中像素个数,有些位置可能重复,所以白像素小于等于n
x=0;
%初始x坐标
y=0;
%初始y坐标
pix=zeros(n,2);
%游走产生的像素坐标
neighbour=[-1-1;
-10;
-11;
0-1;
01;
1-1;
10;
11];
%当前像素邻域
r=floor(1+8*rand());
%八邻域随机选一个来走
y=y+neighbour(r,1);
%y方向游走
x=x+neighbour(r,2);
%x方向游走
pix(i,:
)=[yx];
%保存坐标
miny=min(pix(:
1));
%图像坐标不可能为负,所以找最小值再整体提升为正
minx=min(pix(:
2));
%同上
pix(:
1)=pix(:
1)-miny+1;
%像素坐标整体变为正
2)=pix(:
2)-minx+1;
maxy=max(pix(:
%找最大坐标值,为开辟图像做准备
maxx=max(pix(:
img=zeros(maxy,maxx);
%根据maxy、maxx产生图像
n%将游走的值赋给图像
img(pix(i,1),pix(i,2))=1;
imshow(img)
8.最大流/最小割
学习这个算法是为学习图像处理中的图割算法做准备的。
基本概念:
1.最大流是一个有向图。
2.一个流是最大流,当且仅当它的残余网络中不包括增广路径。
3.最小割就是网络中所有割中值最小的那个割,最小割是不唯一的,不过最小割的值是唯一的。
4.最大流的流量等于某一最小割的容量。
算法思想就是Ford-Fulkerson方法。
具体流程:
1.首先使用广度优先搜索找到源节点到汇节点的一条路径,为增广路径。
2.如果找不到新的从源到汇的增广路径,则上一次求得的网络就是最大流,否则向下执行。
3.找出增广路径中最小的路径的值。
5.用路径中最小的值构造最大流网络,原网络包含这个网络。
4.将增广路径中所有的路径减去最小路径这个值,形成新的网络图。
6.对新的网络图继续执行第1步。
网络图如下,没什么好办法形象表示。
我比较懒,不想画图了,真想看明白过程就看算法导论405页。
原网络:
最大流:
%初始化邻接压缩表,算法导论405页的图
b=[1216;
1413;
2312;
2410;
349;
3620;
424;
4514;
537;
564];
m=max(max(b(:
1:
2)));
%压缩表中最大值就是邻接矩阵的宽与高
A=compresstable2matrix(b);
%从邻接压缩表构造图的矩阵表示
netplot(A,1);
maxflow=zeros(m,m);
while1%下面用广度优先搜索找增广路径
flag=[];
%相当于closed表,已访问过的节点
flag=[flag1];
head=1;
tail=1;
queue=[];
%队列,相当于open表,将要访问的节点
queue(head)=1;
head=head+1;
pa=zeros(1,m);
%每个节点的前趋
pa
(1)=1;
%源节点前趋是自己
whiletail~=head%广度优先搜索,具体细节就不注释了
i=queue(tail);
ifA(i,j)>
isempty(find(flag==j,1))
queue(head)=j;
flag=[flagj];
pa(j)=i;
tail=tail+1;
ifpa(m)==0%如果搜索不到汇节点,退出循环
break;
path=[];
i=m;
%从汇节点开始
k=0;
%路径包含的边的个数
whilei~=1%使用前趋构造从源节点到汇节点的路径
path=[path;
pa(i)iA(pa(i),i)];
%存入路径
i=pa(i);
%使用前趋表反向搜寻,借鉴Dijsktra中的松弛方法
Mi=min(path(:
3));
%寻找增广路径中最小的那条边
fori=1:
k
A(path(i,1),path(i,2))=A(path(i,1),path(i,2))-Mi;
%增广路径中每条路径减去最小的边
maxflow(path(i,1),path(i,2))=maxflow(path(i,1),path(i,2))+Mi;
%最大流,原网络包含这个网络,我只能这样表示了
end%使用新的图A进入下一循环,从新开始找增广路径
end
netplot(maxflow,1)
9.单元最短路径
图的相关算法也算是自己的一个软肋了,当年没选修图论也是一大遗憾。
图像处理中,也有使用图论算法作为基础的相关算法,比如图割,这个算法就需要求最大流、最小割。
所以熟悉一下图论算法对于图像处理还是很有帮助的。
Dijkstra和Bellman-Ford类似,都是解决单源最短路径问题,不同的是这个方法只能解决边为非负的问题,实现的好的Dijkstra算法运行时间要快于Bellman-ford。
算法步骤如下:
1.首先设置队列,所有节点入列,源节点值为0,其他节点值为无穷。
2.然后在队列中找值最小的节点并出列。
3.计算出列的节点所有后继节点的距离。
4.松弛方法,如果新计算的距离小于上次计算的距离,那么更新距离,即将后继节点值设为较小的距离,并将后继节点的前趋设为当前的出列节点。
5.对剩余的节点队列继续找最小值并出列,不断循环2、3、4步直到队列中没有节点了。
步骤是上面没错,不过我程序中没有完全按照上述的步骤实现。
不同的地方在于我没有做出列操作,而是通过标记节点的形式实现的。
运行结果如下,图(是图不是图片)是算法导论367页上的:
matlab代码如下,netplot和compresstable2matrix和使用的一样:
main.m
%初始化邻接压缩表,1210表示从节点1到节点2,边的权重为10
b=[1210;
145;
231;
242;
354;
423;
439;
452;
517;
536];
netplot(A,1)%形象表示
S=inf(1,m);
%从开始的源点到每一个节点的距离
S
(1)=0;
%源点到自己的距离为0
pa=zeros(1,m);
%存储每个节点的前驱,在松弛过程中赋值
pa
(1)=1;
%源点的前趋是自己
visit=zeros(1,m);
%标记某个节点是否访问过了
index=1;
%从index节点开始搜索
%判断是否对所有节点都找的最短路径了。
可能会有源点没有路径到目标节点的情况,那就无限循环了
whilesum(visit)~=m%没有出队列操作,不过通过visit来等价的表示了
visit(index)=1;
%标记第index节点为已入列的节点
[Spa]=relax(S,pa,A,visit,index,m);
%松弛,如果两个节点间有更短的距离,则用更短的距离
index=extract_min(S,visit,index,m);
%使用已访问的最小的节点作为下一次搜索的开始节点
%最终我们需要的就是这两个值
S%源点到其他每一点的距离
pa%其他每一节点的前趋
%算法到此结束,下面只是为了形象的表示而写的。
re=[];
fori=2:
re=[re;
A=compresstable2matrix(re);
relax.m
%边缘松弛,使用更短的距离作为节点的值
function[Spa]=relax(S,pa,A,visit,index,m)
i=index;
ifA(i,j)~=inf&
visit(j)~=1%搜索没有标记过的节点
ifS(j)>
S(i)+A(i,j)%将较小的值赋给正在搜寻的节点
S(j)=S(i)+A(i,j);
extract_min.m
%提取队列中尚未标记的最小的值的序号
functionindex=extract_min(S,visit,index,m)
Mi=inf;
ifvisit(j)~=1
ifS(j)<
Mi
Mi=S(j);
index=j;
10.单元最短路径
该算法可以用来解决一般(边的权值为负)的单源最短路径问题,而dijkstra只能解决权值非负的情况。
此算法使用松弛技术,对每一个顶点,逐步减少源到该顶点的路径的估计值,直到达到最短的路径。
算法运算结果:
matlab代码如下,netplot函数在,不过当时函数中表示两节点没有路径用的是0,而现在需要改成inf:
%初始化邻接压缩表
b=[126;
147
235;
248;
25-4;
32-2;
43-3;
459;
512;
537];
%源到其他节点的最短距离,开始为inf
%寻找到的节点的前趋
%源点的前趋是自己
pre_pa=ones(1,m);
whilesum(pre_pa==pa)~=m%终止条件,判断终止的方法很多,这个应该不是最佳实践
pre_pa=pa;
fork=1:
ifpre_pa(k)~=0%对每一个已搜寻到的节点,从此节点寻找后继节点
i=k;
ifA(i,j)~=inf
S(i)+A(i,j)
%边缘松弛,取两节点间最小权值作为实际权值
%寻找前趋
compresstable2matrix.m
functionA=compresstable2matrix(b)
[n~]=size(b);
m=max(max(b(:
A=inf(m,m);
A(b(i,1),b(i,2))=b(i,3);
11.
如此经典的算法竟一直没有单独的实现过,真是遗憾啊。
广度优先搜索在过去实现的和算法时已经无意识的用到了,深度优先搜索倒是没用过。
这次单独的将两个算法实现出来,因为算法本身和图像没什么关系,所以更纯粹些。
广度优先搜索是从某一节点开始,搜索与其线连接的所有节点,按照广度方向像外扩展,直到不重复遍历所有节点。
深度优先搜索是从某一节点开始,沿着其搜索到的第一个节点不断深入下去,当无法再深入的时候,回溯节点,然后再在回溯中的某一节点开始沿另一个方向深度搜索,直到不重复的遍历所有节点。
广度优先搜索用的是队列作为临时节点存放处;
深度优先搜索可以递归实现(算法导论就是用递归实现的伪代码),不过我这里是用栈作为临时节点存放处。