广告位联系
返回顶部
分享到

使用Matlab制作立体动态相册的方法

C语言 来源:互联网 作者:秩名 发布时间:2022-03-01 15:14:25 人浏览
摘要

效果 教程部分 1 图片导入与大小重设 需要有一个名为album的文件夹和当前m文件在同一文件夹,另外ablum文件夹内至少要有一张jpg格式图片 1 2 3 4 5 6 7 8 9 10 11 path=.\album\;%文件夹名称 fil

效果

教程部分

1 图片导入与大小重设

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

1

2

3

4

5

6

7

8

9

10

11

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设置

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

% 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函数来绘制,要贴图首先要将曲面绘制出来,就要先构造曲面网格:

1

2

3

% 用于绘制图片的网格

[XMesh,YMesh]=meshgrid(linspace(-1,1,120),linspace(-1,1,120));

ZMesh=ones(120,120);

3.2 绘制小型立方体

1

2

3

4

5

6

7

% 绘制图片立方体

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绘制图像,并设置透明度即可:

1

2

3

4

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数据虽然都要变大,但是要乘以不一样的数值,而且各个方向上乘的数值不同,因此我们可以事先设立一个矩阵,用来存储其参数:

1

2

3

% 用来调整放大比例的矩阵

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];

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

1

2

3

4

5

6

7

8

% 最大图片绘制      

% 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即可:

1

2

3

4

5

6

7

8

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回调,!!!这一部分代码要写在上一步代码的前面!!!

1

2

3

4

5

6

7

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函数改成这样:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

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来判断应该绘制大图片还是中等图片

完整代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

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


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://slandarer.blog.csdn.net/article/details/118858258
相关文章
  • C++中类的六大默认成员函数的介绍

    C++中类的六大默认成员函数的介绍
    一、类的默认成员函数 二、构造函数Date(形参列表) 构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。 默认构造函数:无参的构
  • C/C++实现遍历文件夹最全方法总结介绍

    C/C++实现遍历文件夹最全方法总结介绍
    一、filesystem(推荐) 在c++17中,引入了文件系统,使用起来非常方便 在VS中,可以直接在项目属性中调整: 只要是C++17即以上都可 然后头文件
  • C语言实现手写Map(数组+链表+红黑树)的代码

    C语言实现手写Map(数组+链表+红黑树)的代码
    要求 需要准备数组集合(List) 数据结构 需要准备单向链表(Linked) 数据结构 需要准备红黑树(Rbtree)数据结构 需要准备红黑树和链表适配策略
  • MySQL系列教程之使用C语言来连接数据库

    MySQL系列教程之使用C语言来连接数据库
    写在前面 知道了 Java中使用 JDBC编程 来连接数据库了,但是使用 C语言 来连接数据库却总是连接不上去~ 立即安排一波使用 C语言连接 MySQL数
  • 基于C语言实现简单学生成绩管理系统

    基于C语言实现简单学生成绩管理系统
    一、系统主要功能 1、密码登录 2、输入数据 3、查询成绩 4、修改成绩 5、输出所有学生成绩 6、退出系统 二、代码实现 1 2 3 4 5 6 7 8 9 10 11
  • C语言实现共享单车管理系统

    C语言实现共享单车管理系统
    1.功能模块图; 2.各个模块详细的功能描述。 1.登陆:登陆分为用户登陆,管理员登陆以及维修员登录,登陆后不同的用户所执行的操作
  • C++继承与菱形继承的介绍

    C++继承与菱形继承的介绍
    继承的概念和定义 继承机制是面向对象程序设计的一种实现代码复用的重要手段,它允许程序员在保持原有类特性的基础上进行拓展,增加
  • C/C++指针介绍与使用介绍

    C/C++指针介绍与使用介绍
    什么是指针 C/C++语言拥有在程序运行时获得变量的地址和操作地址的能力,这种用来操作地址的特殊类型变量被称作指针。 翻译翻译什么
  • C++进程的创建和进程ID标识介绍
    进程的ID 进程的ID,可称为PID。它是进程的唯一标识,类似于我们的身份证号是唯一标识,因为名字可能会和其他人相同,生日可能会与其他
  • C++分析如何用虚析构与纯虚析构处理内存泄漏

    C++分析如何用虚析构与纯虚析构处理内存泄漏
    一、问题引入 使用多态时,如果有一些子类的成员开辟在堆区,那么在父类执行完毕释放后,没有办法去释放子类的内存,这样会导致内存
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计