我的编程空间,编程开发者的网络收藏夹
学习永远不晚

教你用Matlab制作立体动态相册

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

教你用Matlab制作立体动态相册

效果

教程部分

1 图片导入与大小重设

需要有一个名为album的文件夹和当前m文件在同一文件夹,另外ablum文件夹内至少要有一张jpg格式图片

path='.\album\';%文件夹名称
files=dir(fullfile(path,'*.jpg')); 
picNum=size(files,1);

%遍历路径下每一幅图像
for i=1:picNum
   fileName=strcat(path,files(i).name); 
   img=imread(fileName);
   img=imresize(img,[120,120]);
   imgSet{i}=img;
end

我们注意到,这里用了一次imresize将突破变为120x120大小,这里重设大小有三个作用:

  • 将不是方形的图片变为方形
  • 将图像设置固定大小,方便构造网格放置图片
  • 120x120的大小大约是能让图片表示清晰为前提下最小的大小,图片太大的话运行会卡,太小的话不清晰

2 fig axes设置

% fig axes设置
fig=figure('units','pixels','position',[50 50 600 600],...
                       'Numbertitle','off','resize','off',...
                       'name','album3d','menubar','none');
ax=axes('parent',fig,'position',[-0.5 -0.5 2 2],...
   'XLim', [-6 6],...
   'YLim', [-6 6],...
   'ZLim', [-6 6],...
   'Visible','on',...
   'XTick',[], ...
   'YTick',[],...
   'Color',[0 0 0],...
   'DataAspectRatioMode','manual',...
   'CameraPositionMode','manual');
hold(ax,'on')

大部分设置大家都能看懂,这里讲解一下一些比较少见的设置:

2.1 为什么 axes的’position’属性不设置[0 0 1 1]?

因为是3D坐标轴,设置为[0 0 1 1]后旋转起来效果是这样的,所以我们axes要设置的比figure大一圈:

2.2 为什么要设置CameraPositionMode这一奇怪的属性?

因为我们后期要频繁改变CameraPosition这一属性,而CameraPositionMode设置为manual可以让视角完全按照CameraPosition的数值来调整,至于为什么要调整视角呢?

当然是因为如果对图像位置数据进行处理数据量会贼大,因此我们不妨直接转动axes视角而非转动图片。

3 绘制图形句柄

就是绘制小型立方体,中型立方体和大型立方体,其中鼠标移动到中型立方体中心时中型立方体变成大型立方体,这个可以靠设置图形对象的XData,YData,ZData数值来改变

3.1 构造网格

由于surf曲面图可以将图像贴在上面,还可以设置透明度,我们决定用surf函数来绘制,要贴图首先要将曲面绘制出来,就要先构造曲面网格:

% 用于绘制图片的网格
[XMesh,YMesh]=meshgrid(linspace(-1,1,120),linspace(-1,1,120));
ZMesh=ones(120,120);

3.2 绘制小型立方体

% 绘制图片立方体
surfPic(1)=surf(XMesh,YMesh,ZMesh,'CData',imgSet{mod(0,picNum)+1},'EdgeColor','none','FaceColor','interp');
surfPic(2)=surf(XMesh,YMesh(end:-1:1,:),-ZMesh,'CData',imgSet{mod(1,picNum)+1},'EdgeColor','none','FaceColor','interp');
surfPic(3)=surf(ZMesh,XMesh,YMesh(end:-1:1,:),'CData',imgSet{mod(2,picNum)+1},'EdgeColor','none','FaceColor','interp');
surfPic(4)=surf(XMesh,ZMesh,YMesh(end:-1:1,:),'CData',imgSet{mod(3,picNum)+1},'EdgeColor','none','FaceColor','interp');
surfPic(5)=surf(-ZMesh,XMesh,YMesh(end:-1:1,:),'CData',imgSet{mod(4,picNum)+1},'EdgeColor','none','FaceColor','interp');
surfPic(6)=surf(XMesh,-ZMesh,YMesh(end:-1:1,:),'CData',imgSet{mod(5,picNum)+1},'EdgeColor','none','FaceColor','interp');

3.3 绘制中型立方体

有了小型立方体,中型的绘制起来就简单了起来,甚至可以用一个for循环解决,只需要循环提取小型立方体的XData,YData,ZData数据后乘以1.5绘制图像,并设置透明度即可:

% 依靠小立方体数据绘制中等立方体
for i=1:6
    surfPicA(i)=surf(surfPic(i).XData.*1.5,surfPic(i).YData.*1.5,surfPic(i).ZData.*1.5,...
        'CData',surfPic(i).CData,'EdgeColor','none','FaceColor','interp','FaceAlpha',0.7);  
end

3.4 大型立方体参数设置

大型立方体参数设置时就没那么简单,如果直接乘以2.5,图片与图片之间会没有缝隙,因此我们XData,YData,ZData数据虽然都要变大,但是要乘以不一样的数值,而且各个方向上乘的数值不同,因此我们可以事先设立一个矩阵,用来存储其参数:

% 用来调整放大比例的矩阵
resizeMat=[2 2 2.5;2 2 2.5;2.5 2 2;
           2 2.5 2;2.5 2 2;2 2.5 2];

想直接画大型正方形可以试试如下代码:

% 最大图片绘制       
% for i=1:6
%     surfPicB(i)=surf(surfPic(i).XData.*resizeMat(i,1),...
%                      surfPic(i).YData.*resizeMat(i,2),...
%                      surfPic(i).ZData.*resizeMat(i,3),...
%                      'CData',surfPic(i).CData,'EdgeColor',...
%                      'none','FaceColor','interp','FaceAlpha',0.7);  
% end    

4 立方体旋转

我们只需要设置一个timer函数不断调整CameraPosition即可:

fps=40;theta=0;
rotateTimer=timer('ExecutionMode', 'FixedRate', 'Period',1/fps, 'TimerFcn', @rotateCube);
start(rotateTimer)

    function rotateCube(~,~)
        theta=theta+0.02;
        ax.CameraPosition=[cos(theta)*5*sqrt(2),sin(theta)*5*sqrt(2),5];
    end

5 获取鼠标与中心点的距离

本来想直接在timer调用的函数里写get(fig,‘CurrentPoint’);来获得鼠标当前位置的,但发现这样写只有鼠标点击窗口才会有反应,并不是鼠标移动就会有反应,因此我们再构造一个WindowButtonMotionFcn回调,!!!这一部分代码要写在上一步代码的前面!!!

lastDis=300;
preDis=300;
set(fig,'WindowButtonMotionFcn',@move2center)    
    function move2center(~,~)
        xy=get(fig,'CurrentPoint');
        preDis=sqrt(sum((xy-[300,300]).^2));
    end

preDis就是鼠标到图片中心的位置,我为什么要设置一个lastDis呢,因为每次移动鼠标都更新图像实在太卡了,因此我们要加一个判定,当且仅当以下两种情况更新图片大小

  • 之前鼠标距离中心>=150,现在<150
  • 之前鼠标距离中心<150,现在>=150

6 鼠标移动到fig中心时更新图片

将之前的rotateCube函数改成这样:

function rotateCube(~,~)
        theta=theta+0.02;
        ax.CameraPosition=[cos(theta)*5*sqrt(2),sin(theta)*5*sqrt(2),5];
        if (~all([preDis lastDis]<150))&&any([preDis lastDis]<150)
            for ii=1:6
                if preDis<150
                    surfPicA(ii).XData=surfPic(ii).XData.*resizeMat(ii,1);
                    surfPicA(ii).YData=surfPic(ii).YData.*resizeMat(ii,2);
                    surfPicA(ii).ZData=surfPic(ii).ZData.*resizeMat(ii,3);
                else
                    surfPicA(ii).XData=surfPic(ii).XData.*1.5;
                    surfPicA(ii).YData=surfPic(ii).YData.*1.5;
                    surfPicA(ii).ZData=surfPic(ii).ZData.*1.5;
                end
            end
        end
        lastDis=preDis;
    end

其中:

(~all([preDis lastDis]<150))&&any([preDis lastDis]<150)

是用来判断上一次鼠标位置和当前鼠标位置是否只有一个距离中心<150

另:

for 循环中使用else来判断应该绘制大图片还是中等图片

完整代码

function album3d
path='.\album\';%文件夹名称
files=dir(fullfile(path,'*.jpg')); 
picNum=size(files,1);

%遍历路径下每一幅图像
for i=1:picNum
   fileName=strcat(path,files(i).name); 
   img=imread(fileName);
   img=imresize(img,[120,120]);
   imgSet{i}=img;
end

% fig axes设置
fig=figure('units','pixels','position',[50 50 600 600],...
                       'Numbertitle','off','resize','off',...
                       'name','album3d','menubar','none');
ax=axes('parent',fig,'position',[-0.5 -0.5 2 2],...
   'XLim', [-6 6],...
   'YLim', [-6 6],...
   'ZLim', [-6 6],...
   'Visible','on',...
   'XTick',[], ...
   'YTick',[],...
   'Color',[0 0 0],...
   'DataAspectRatioMode','manual',...
   'CameraPositionMode','manual');
hold(ax,'on')
ax.CameraPosition=[5 5 5];

% 用于绘制图片的网格
[XMesh,YMesh]=meshgrid(linspace(-1,1,120),linspace(-1,1,120));
ZMesh=ones(120,120);

% 绘制图片立方体
surfPic(1)=surf(XMesh,YMesh,ZMesh,'CData',imgSet{mod(0,picNum)+1},'EdgeColor','none','FaceColor','interp');
surfPic(2)=surf(XMesh,YMesh(end:-1:1,:),-ZMesh,'CData',imgSet{mod(1,picNum)+1},'EdgeColor','none','FaceColor','interp');
surfPic(3)=surf(ZMesh,XMesh,YMesh(end:-1:1,:),'CData',imgSet{mod(2,picNum)+1},'EdgeColor','none','FaceColor','interp');
surfPic(4)=surf(XMesh,ZMesh,YMesh(end:-1:1,:),'CData',imgSet{mod(3,picNum)+1},'EdgeColor','none','FaceColor','interp');
surfPic(5)=surf(-ZMesh,XMesh,YMesh(end:-1:1,:),'CData',imgSet{mod(4,picNum)+1},'EdgeColor','none','FaceColor','interp');
surfPic(6)=surf(XMesh,-ZMesh,YMesh(end:-1:1,:),'CData',imgSet{mod(5,picNum)+1},'EdgeColor','none','FaceColor','interp');

% 依靠小立方体数据绘制中等立方体
for i=1:6
    surfPicA(i)=surf(surfPic(i).XData.*1.5,surfPic(i).YData.*1.5,surfPic(i).ZData.*1.5,...
        'CData',surfPic(i).CData,'EdgeColor','none','FaceColor','interp','FaceAlpha',0.7);  
end

% 用来调整放大比例的矩阵
resizeMat=[2 2 2.5;2 2 2.5;2.5 2 2;
           2 2.5 2;2.5 2 2;2 2.5 2];

% 最大图片绘制       
% for i=1:6
%     surfPicB(i)=surf(surfPic(i).XData.*resizeMat(i,1),...
%                      surfPic(i).YData.*resizeMat(i,2),...
%                      surfPic(i).ZData.*resizeMat(i,3),...
%                      'CData',surfPic(i).CData,'EdgeColor',...
%                      'none','FaceColor','interp','FaceAlpha',0.7);  
% end     


lastDis=300;
preDis=300;
set(fig,'WindowButtonMotionFcn',@move2center)    
    function move2center(~,~)
        xy=get(fig,'CurrentPoint');
        preDis=sqrt(sum((xy-[300,300]).^2));
    end



fps=40;theta=0;
rotateTimer=timer('ExecutionMode', 'FixedRate', 'Period',1/fps, 'TimerFcn', @rotateCube);
start(rotateTimer)



    function rotateCube(~,~)
        theta=theta+0.02;
        ax.CameraPosition=[cos(theta)*5*sqrt(2),sin(theta)*5*sqrt(2),5];
        if (~all([preDis lastDis]<150))&&any([preDis lastDis]<150)
            for ii=1:6
                if preDis<150
                    surfPicA(ii).XData=surfPic(ii).XData.*resizeMat(ii,1);
                    surfPicA(ii).YData=surfPic(ii).YData.*resizeMat(ii,2);
                    surfPicA(ii).ZData=surfPic(ii).ZData.*resizeMat(ii,3);
                else
                    surfPicA(ii).XData=surfPic(ii).XData.*1.5;
                    surfPicA(ii).YData=surfPic(ii).YData.*1.5;
                    surfPicA(ii).ZData=surfPic(ii).ZData.*1.5;
                end
            end
        end
        lastDis=preDis;
    end




% 弃用方案:太卡
% set(fig,'WindowButtonMotionFcn',@move2center)    
%     function move2center(~,~)
%         xy=get(fig,'CurrentPoint');
%         dis=sum((xy-[300,300]).^2);
%         for ii=1:6
%             if dis<200
%                 surfPicA(ii).XData=surfPic(ii).XData.*resizeMat(ii,1);
%                 surfPicA(ii).YData=surfPic(ii).YData.*resizeMat(ii,2);
%                 surfPicA(ii).ZData=surfPic(ii).ZData.*resizeMat(ii,3);
%             else
%                 surfPicA(ii).XData=surfPic(ii).XData;
%                 surfPicA(ii).YData=surfPic(ii).YData;
%                 surfPicA(ii).ZData=surfPic(ii).ZData;
%             end    
%         end
%         
%         
%         
%     end

end

以上就是教你用Matlab制作立体动态相册的详细内容,更多关于Matlab制作立体相册的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

教你用Matlab制作立体动态相册

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么用Matlab制作立体动态相册

小编给大家分享一下怎么用Matlab制作立体动态相册,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!效果教程部分1 图片导入与大小重设需要有一个名为album的文件夹和当前m文件在同一文件夹,另外ablum文件夹内至少要有一
2023-06-29

如何使用html+css制作一个3D立体相册

这篇文章主要介绍了如何使用html+css制作一个3D立体相册的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇如何使用html+css制作一个3D立体相册文章都会有所收获,下面我们一起来看看吧。一、先看效果二、实
2023-07-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录