MATLAB程序全套整合.docx
- 文档编号:20099191
- 上传时间:2023-04-24
- 格式:DOCX
- 页数:68
- 大小:923.70KB
MATLAB程序全套整合.docx
《MATLAB程序全套整合.docx》由会员分享,可在线阅读,更多相关《MATLAB程序全套整合.docx(68页珍藏版)》请在冰豆网上搜索。
MATLAB程序全套整合
1.全景图到穹景图
这个程序我最初是用FreeImage写的,这两天改成了matlab,再不贴上来,我就要忘了。
看到一篇文章有这样的变换,挺有意思的,就拿来试了一下,文章点此。
全景图到穹顶图变换,通俗的说就是将全景图首尾相接做成一个圆环的样子。
先看下面这张图:
下面的矩形就是我们要处理的全景图,上面的矩形是变换后的图像。
下面图像的底边对应穹顶图的内圆,顶边对应穹顶图的外圆,当然,反过来也是可以的。
程序流程:
1.定义穹顶图内圆和外圆的半径,变换后的像素就填充在这个内外半径的圆环中。
2.遍历穹顶图,当所处理当前像素位于圆环内,则通过极坐标反变换去全景图中寻找相应位置的像素进行填充。
3.遍历完图像就行了。
用的技巧和图像旋转或放大缩小都是类似的。
处理结果:
原图:
结果:
matlab代码如下:
clearall;
closeall;
clc;
img=imread('pan.jpg');
imshow(img);
[m,n]=size(img);
r1=100;%内环半径
r2=r1+m;%外环半径
imgn=zeros(2*r2,2*r2);
[re_m,re_n]=size(imgn);
fory=1:
re_m
forx=1:
re_n
dis_x=x-re_n/2;
dis_y=y-re_m/2;
l=sqrt(dis_x^2+dis_y^2);
ifl<=r2&&l>=r1
theta=0;
ify>re_m/2
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; end xx=ceil(n*theta/(2*pi)); yy=ceil(l-r1); ifyy>=1&&yy<=m&&xx>=1&&xx<=n imgn(y,x)=img(yy,xx); end end end 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); end 3.GUI读入图像 %---Executesonbuttonpressinpushbutton1. functionpushbutton1_Callback(hObject,eventdata,handles) %hObjecthandletopushbutton1(seeGCBO) %eventdatareserved-tobedefinedinafutureversionofMATLAB %handlesstructurewithhandlesanduserdata(seeGUIDATA) [filename,pathname]=uigetfile({'*.*';'*.jpg';'*.bmp';'*.gif';'*.png';'*.tif'},'ReadPic'); str=[pathnamefilename]; globalsrc_img; if~isequal([pathname,filename],[0,0]) src_img=imread(str); axes(handles.axes1); imshow(src_img); end 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结构张量 根据结构张量能区分图像的平坦区域、边缘区域与角点区域。 此算法也算是计算机科学最重要的32个算法之一了。 链接的文章中此算法名称为Strukturtensor算法,不过我搜索了一下,Strukturtensor这个单词好像是德语,翻译过来就是structuretensor结构张量了。 此处所说的张量不是相对论或黎曼几何里的张量,黎曼几何的张量好多论文都叫张量场了。 也不是数学界还没研究明白的对矩阵进行扩展的高阶张量,主要是张量分解。 这里的结构张量就是一个矩阵,一个对图像像素进行组织的数据结构而已。 像素组织而成的矩阵如下: 这个公式太常见了,在harris角点检测中就用到了。 其中Ix,Iy就是原对原图像在x和y方向求得的偏导。 然后求矩阵E的行列式K和迹H。 然后根据K和H的关系就能区分图像的区域模式了。 模式分以下三类: 平坦区域: H=0; 边缘区域: H>0&&K=0; 角点区域: H>0&&K>0; harris角点检测就用到了第三类判断。 当然,在实际应用的时候H和K的值肯定都不会是理想,所以我用的都是近似判断。 处理结果如下: 原图: 平坦区域: 边缘区域: 角点区域(好像也不全角点,求角点还是harris好了): 结构张量行列式与迹的关系: 其中红框为平坦区域,黄框为边缘区域,铝框为角点区域。 matlab代码如下: clearall;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>50&&abs(K)>0.01*10^(-9)%认为是角点区域 img(i,j)=255; end lambda(k,: )=[KH]; k=k+1; end end figure; plot(lambda(: 1),lambda(: 2),'.'); ylabel('trace');xlabel('det'); figure; imshow(img,[]) 6.模糊集图像增强 算法有很多变种。 不过主要就是以下三步。 1.设计隶属度函数将图像从空间域变换到模糊集域。 2.设计模糊增强算子,在模糊集域对图像进行处理。 3.根据第1步的隶属度函数重新将图像从模糊集域变换到空间域。 这和频域处理中的变换反变换不是很像么。 我使用的隶属度函数和模糊增强算子在这篇论文里,也算相关算法的经典论文了。 处理结果如下: 原图: 模糊集增强后: matlab代码如下: clearall;closeall;clc; img=double(imread('lena.jpg')); imshow(img,[]) [mn]=size(img); Fe=1; %控制参数 Fd=128; xmax=max(max(img)); u=(1+(xmax-img)/Fd).^(-Fe);%空间域变换到模糊域 %也可以多次迭代 fori=1: m%模糊域增强算子 forj=1: 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; end end end img=xmax-Fd.*(u.^(-1/Fe)-1);%模糊域变换回空间域 figure; imshow(uint8(img)); 7.随机游走图像 随机游走类似布朗运动,就是随机的向各个方向走吧。 虽然代码没什么技术含量,不过产生的图像实在太漂亮了,所以还是贴上来吧。 产生的图像: matlab代码如下: clearall;closeall;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];%当前像素邻域 fori=1: n r=floor(1+8*rand());%八邻域随机选一个来走 y=y+neighbour(r,1);%y方向游走 x=x+neighbour(r,2);%x方向游走 pix(i,: )=[yx];%保存坐标 end miny=min(pix(: 1));%图像坐标不可能为负,所以找最小值再整体提升为正 minx=min(pix(: 2));%同上 pix(: 1)=pix(: 1)-miny+1;%像素坐标整体变为正 pix(: 2)=pix(: 2)-minx+1; maxy=max(pix(: 1));%找最大坐标值,为开辟图像做准备 maxx=max(pix(: 2)); img=zeros(maxy,maxx);%根据maxy、maxx产生图像 fori=1: n%将游走的值赋给图像 img(pix(i,1),pix(i,2))=1; end imshow(img) 8.最大流/最小割 学习这个算法是为学习图像处理中的图割算法做准备的。 基本概念: 1.最大流是一个有向图。 2.一个流是最大流,当且仅当它的残余网络中不包括增广路径。 3.最小割就是网络中所有割中值最小的那个割,最小割是不唯一的,不过最小割的值是唯一的。 4.最大流的流量等于某一最小割的容量。 算法思想就是Ford-Fulkerson方法。 具体流程: 1.首先使用广度优先搜索找到源节点到汇节点的一条路径,为增广路径。 2.如果找不到新的从源到汇的增广路径,则上一次求得的网络就是最大流,否则向下执行。 3.找出增广路径中最小的路径的值。 5.用路径中最小的值构造最大流网络,原网络包含这个网络。 4.将增广路径中所有的路径减去最小路径这个值,形成新的网络图。 6.对新的网络图继续执行第1步。 网络图如下,没什么好办法形象表示。 我比较懒,不想画图了,真想看明白过程就看算法导论405页。 原网络: 最大流: matlab代码如下: clearall;closeall;clc %初始化邻接压缩表,算法导论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); forj=1: m ifA(i,j)>0&&isempty(find(flag==j,1)) queue(head)=j; head=head+1; flag=[flagj]; pa(j)=i; end end tail=tail+1; end ifpa(m)==0%如果搜索不到汇节点,退出循环 break; end path=[]; i=m;%从汇节点开始 k=0;%路径包含的边的个数 whilei~=1%使用前趋构造从源节点到汇节点的路径 path=[path;pa(i)iA(pa(i),i)];%存入路径 i=pa(i);%使用前趋表反向搜寻,借鉴Dijsktra中的松弛方法 k=k+1; end 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 figure; 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 clearall;closeall;clc %初始化邻接压缩表,1210表示从节点1到节点2,边的权重为10 b=[1210;145;231; 242;354;423; 439;452;517; 536]; m=max(max(b(: 1: 2)));%压缩表中最大值就是邻接矩阵的宽与高 A=compresstable2matrix(b);%从邻接压缩表构造图的矩阵表示 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);%使用已访问的最小的节点作为下一次搜索的开始节点 end %最终我们需要的就是这两个值 S%源点到其他每一点的距离 pa%其他每一节点的前趋 %算法到此结束,下面只是为了形象的表示而写的。 re=[]; fori=2: m re=[re;pa(i)iA(pa(i),i)]; end A=compresstable2matrix(re);%从邻接压缩表构造图的矩阵表示 figure; netplot(A,1)%形象表示 relax.m %边缘松弛,使用更短的距离作为节点的值 function[Spa]=relax(S,pa,A,visit,index,m) i=index; forj=1: m ifA(i,j)~=inf&&visit(j)~=1%搜索没有标记过的节点 ifS(j)>S(i)+A(i,j)%将较小的值赋给正在搜寻的节点 S(j)=S(i)+A(i,j); pa(j)=i; end end end end extract_min.m %提取队列中尚未标记的最小的值的序号 functionindex=extract_min(S,visit,index,m) Mi=inf; forj=1: m ifvisit(j)~=1 ifS(j) Mi=S(j); index=j; end end end end 10.单元最短路径 该算法可以用来解决一般(边的权值为负)的单源最短路径问题,而dijkstra只能解决权值非负的情况。 此算法使用松弛技术,对每一个顶点,逐步减少源到该顶点的路径的估计值,直到达到最短的路径。 算法运算结果: matlab代码如下,netplot函数在这里,不过当时函数中表示两节点没有路径用的是0,而现在需要改成inf: clearall;closeall;clc %初始化邻接压缩表 b=[126; 147 235; 248; 25-4; 32-2; 43-3; 459; 512; 537]; m=max(max(b(: 1: 2)));%压缩表中最大值就是邻接矩阵的宽与高 A=compresstable2matrix(b);%从邻接压缩表构造图的矩阵表示 netplot(A,1)%形象表示 S=inf(1,m);%源到其他节点的最短距离,开始为inf S (1)=0;%源点到自己的距离为0 pa=zeros(1,m);%寻找到的节点的前趋 pa (1)=1;%源点的前趋是自己 pre_pa=ones(1,m); whilesum(pre_pa==pa)~=m%终止条件,判断终止的方法很多,这个应该不是最佳实践 pre_pa=pa; fork=1: m ifpre_pa(k)~=0%对每一个已搜寻到的节点,从此节点寻找后继节点 i=k; forj=1: m ifA(i,j)~=inf ifS(j)>S(i)+A(i,j) S(j)=S(i)+A(i,j);%边缘松弛,取两节点间最小权值作为实际权值 pa(j)=i;%寻找前趋 end end end end end end %最终我们需要的就是这两个值 S%源点到其他每一点的距离 pa%其他每一节点的前趋 %算法到此结束,下面只是为了形象的表示而写的。 re=[]; fori=2: m re=[re;pa(i)iA(pa(i),i)]; end A=compresstable2matrix(re);%从邻接压缩表构造图的矩阵表示 figure; netplot(A,1)%形象表示 compresstable2matrix.m functionA=compresstable2matrix(b) [n~]=size(b); m=max(max(b(: 1: 2))); A=inf(m,m); fori=1: n A(b(i,1),b(i,2))=b(i,3); end end 11. 如此经典的算法竟一直没有单独的实现过,真是遗憾啊。 广度优先搜索在过去实现的二值图像连通区域标记和prim最小生成树算法时已经无意识的用到了,深度优先搜索倒是没用过。 这次单独的将两个算法实现出来,因为算法本身和图像没什么关系,所以更纯粹些。 广度优先搜索是从某一节点开始,搜索与其线连接的所有节点,按照广度方向像外扩展,直到不重复遍历所有节点。 深度优先搜索是从某一节点开始,沿着其搜索到的第一个节点不断深入下去,当无法再深入的时候,回溯节点,然后再在回溯中的某一节点开始沿另一个
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MATLAB 程序 全套 整合