教你用Matlab制作立體動(dòng)態(tài)相冊(cè)
效果


教程部分
1 圖片導(dǎo)入與大小重設(shè)
需要有一個(gè)名為album的文件夾和當(dāng)前m文件在同一文件夾,另外ablum文件夾內(nèi)至少要有一張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將突破變?yōu)?20x120大小,這里重設(shè)大小有三個(gè)作用:
- 將不是方形的圖片變?yōu)榉叫?/li>
- 將圖像設(shè)置固定大小,方便構(gòu)造網(wǎng)格放置圖片
- 120x120的大小大約是能讓圖片表示清晰為前提下最小的大小,圖片太大的話運(yùn)行會(huì)卡,太小的話不清晰
2 fig axes設(shè)置
% fig axes設(shè)置
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')
大部分設(shè)置大家都能看懂,這里講解一下一些比較少見的設(shè)置:
2.1 為什么 axes的’position’屬性不設(shè)置[0 0 1 1]?
因?yàn)槭?D坐標(biāo)軸,設(shè)置為[0 0 1 1]后旋轉(zhuǎn)起來效果是這樣的,所以我們axes要設(shè)置的比figure大一圈:

2.2 為什么要設(shè)置CameraPositionMode這一奇怪的屬性?
因?yàn)槲覀兒笃谝l繁改變CameraPosition這一屬性,而CameraPositionMode設(shè)置為manual可以讓視角完全按照CameraPosition的數(shù)值來調(diào)整,至于為什么要調(diào)整視角呢?
當(dāng)然是因?yàn)槿绻麑?duì)圖像位置數(shù)據(jù)進(jìn)行處理數(shù)據(jù)量會(huì)賊大,因此我們不妨直接轉(zhuǎn)動(dòng)axes視角而非轉(zhuǎn)動(dòng)圖片。
3 繪制圖形句柄
就是繪制小型立方體,中型立方體和大型立方體,其中鼠標(biāo)移動(dòng)到中型立方體中心時(shí)中型立方體變成大型立方體,這個(gè)可以靠設(shè)置圖形對(duì)象的XData,YData,ZData數(shù)值來改變
3.1 構(gòu)造網(wǎng)格
由于surf曲面圖可以將圖像貼在上面,還可以設(shè)置透明度,我們決定用surf函數(shù)來繪制,要貼圖首先要將曲面繪制出來,就要先構(gòu)造曲面網(wǎng)格:
% 用于繪制圖片的網(wǎng)格 [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 繪制中型立方體
有了小型立方體,中型的繪制起來就簡(jiǎn)單了起來,甚至可以用一個(gè)for循環(huán)解決,只需要循環(huán)提取小型立方體的XData,YData,ZData數(shù)據(jù)后乘以1.5繪制圖像,并設(shè)置透明度即可:
% 依靠小立方體數(shù)據(jù)繪制中等立方體
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 大型立方體參數(shù)設(shè)置
大型立方體參數(shù)設(shè)置時(shí)就沒那么簡(jiǎn)單,如果直接乘以2.5,圖片與圖片之間會(huì)沒有縫隙,因此我們XData,YData,ZData數(shù)據(jù)雖然都要變大,但是要乘以不一樣的數(shù)值,而且各個(gè)方向上乘的數(shù)值不同,因此我們可以事先設(shè)立一個(gè)矩陣,用來存儲(chǔ)其參數(shù):
% 用來調(diào)整放大比例的矩陣
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 立方體旋轉(zhuǎn)
我們只需要設(shè)置一個(gè)timer函數(shù)不斷調(diào)整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 獲取鼠標(biāo)與中心點(diǎn)的距離
本來想直接在timer調(diào)用的函數(shù)里寫get(fig,‘CurrentPoint’);來獲得鼠標(biāo)當(dāng)前位置的,但發(fā)現(xiàn)這樣寫只有鼠標(biāo)點(diǎn)擊窗口才會(huì)有反應(yīng),并不是鼠標(biāo)移動(dòng)就會(huì)有反應(yīng),因此我們?cè)贅?gòu)造一個(gè)WindowButtonMotionFcn回調(diào),?。?!這一部分代碼要寫在上一步代碼的前面?。?!
lastDis=300;
preDis=300;
set(fig,'WindowButtonMotionFcn',@move2center)
function move2center(~,~)
xy=get(fig,'CurrentPoint');
preDis=sqrt(sum((xy-[300,300]).^2));
end
preDis就是鼠標(biāo)到圖片中心的位置,我為什么要設(shè)置一個(gè)lastDis呢,因?yàn)槊看我苿?dòng)鼠標(biāo)都更新圖像實(shí)在太卡了,因此我們要加一個(gè)判定,當(dāng)且僅當(dāng)以下兩種情況更新圖片大小
- 之前鼠標(biāo)距離中心>=150,現(xiàn)在<150
- 之前鼠標(biāo)距離中心<150,現(xiàn)在>=150
6 鼠標(biāo)移動(dòng)到fig中心時(shí)更新圖片
將之前的rotateCube函數(shù)改成這樣:
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)
是用來判斷上一次鼠標(biāo)位置和當(dāng)前鼠標(biāo)位置是否只有一個(gè)距離中心<150
另:
for 循環(huán)中使用else來判斷應(yīng)該繪制大圖片還是中等圖片
完整代碼
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設(shè)置
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];
% 用于繪制圖片的網(wǎng)格
[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');
% 依靠小立方體數(shù)據(jù)繪制中等立方體
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
% 用來調(diào)整放大比例的矩陣
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制作立體動(dòng)態(tài)相冊(cè)的詳細(xì)內(nèi)容,更多關(guān)于Matlab制作立體相冊(cè)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Visual Studio 2010/2013編譯V8引擎步驟分享
這篇文章主要介紹了使用Visual Studio 2013編譯V8引擎步驟分享,需要的朋友可以參考下2015-08-08
C++制作鼠標(biāo)連點(diǎn)器實(shí)例代碼
大家好,本篇文章主要講的是C++制作鼠標(biāo)連點(diǎn)器實(shí)例代碼,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2022-01-01
C語言實(shí)現(xiàn)個(gè)人財(cái)務(wù)管理
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)個(gè)人財(cái)務(wù)管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11

