css3魔方3乘3每层旋转_我的MATLAB魔方新玩法:拼出任意图案!

本文介绍了如何使用MATLAB改进的算法生成高阶魔方,并展示了如何将给定图像拼接到魔方表面,以实现复杂图案展示。通过详细步骤和代码,作者分享了从图像预处理到魔方旋转的全过程,包括70阶魔方的生成和一个实例演示。
摘要由CSDN通过智能技术生成

f48fc9fe91ee537de2ef99ce48db6c47.png

更新:

添加代码链接:nkyang/MagicCube

有时间的话,会陆续把之前文章的代码都整理好了传到github上去,这样个人文章里面就不会出现代码,文章可读性更好。


我又回来更新了,在上一次的文章中,我写了一个可以用来玩魔方的程序,当时在文章的结尾处,我展示了一个用七阶魔方拼出心形图案的例子。

易夕:MATLAB画图技巧:让魔方转起来!​zhuanlan.zhihu.com
d05a9d3ed1c5d5ee4f2c76a9e810328c.png

进一步地,能否拼出更复杂的图案?给定一张图片作为参考,能否使用高阶魔方拼出清晰的画面?这就是本文要解决的问题。

1.高效的高阶魔方生成函数

一个很重要的问题就是,上次的魔方构造函数的复杂度很高。一个N阶魔方,是用N^3个立方体构成,每个立方体包括7个hgtransfrom对象,6个patch对象。当N>30时,程序会慢的令人发指,光生成魔方可能就需要一个小时以上。所以我改进了程序,现在的N阶魔方,由6*N^2个patch对象构成,每个patch对象对应1个hgtransform对象。

%% 创建一个n×n的魔方
function t = magicCube(n)
x = [-1 -1  0  0];
y = [-1  0  0 -1];
z = [0 0 0 0];
c = colormap(jet(6));
t = gobjects(n,n,n); 
% lw为线宽,对于高阶魔方,线要细
lw = 0.25;
for ii = 1:n
    for jj = 1:n
        for kk = 1:6
            switch kk
                case 1
                    t(ii,jj,1) = hgtransform('Parent',gca);
                    patch(x+ii-n/2,y+jj-n/2,z-n/2,c(kk,:),'Parent',t(ii,jj,1),'LineWidth',lw);
                case 2
                    t(ii,1,jj) = hgtransform('Parent',gca);
                    patch(x+ii-n/2,z-n/2,y+jj-n/2,c(kk,:),'Parent',t(ii,1,jj),'LineWidth',lw);
                case 3
                    t(1,ii,jj) = hgtransform('Parent',gca);
                    patch(z-n/2,x+ii-n/2,y+jj-n/2,c(kk,:),'Parent',t(1,ii,jj),'LineWidth',lw);
                case 4
                    t(n,ii,jj) = hgtransform('Parent',gca);
                    patch(z+n/2,x+ii-n/2,y+jj-n/2,c(kk,:),'Parent',t(n,ii,jj),'LineWidth',lw);
                case 5
                    t(ii,n,jj) = hgtransform('Parent',gca);
                    patch(x+ii-n/2,z+n/2,y+jj-n/2,c(kk,:),'Parent',t(ii,n,jj),'LineWidth',lw);
                case 6
                    t(ii,jj,n) = hgtransform('Parent',gca);
                    patch(x+ii-n/2,y+jj-n/2,z+n/2,c(kk,:),'Parent',t(ii,jj,n),'LineWidth',lw);
            end
        end
    end
end
end

2. XYZ轴旋转函数

以X轴为例,ids层逆时针旋转90度的函数为(ids可以是数组,这样调用起来比较方便)

%% X轴方向进行逆时针旋转
function t = rotX(t,ids)
N = length(t);
Rx = makehgtform('xrotate',pi/2);
for x = ids
    for y = 1:N
        for z = 1:N
            if isgraphics(t(x,y,z),'hgtransform')
                t(x,y,z).Matrix = Rx*t(x,y,z).Matrix;
            end
        end
    end
    t(x,:,:) = rot90(squeeze(t(x,:,:)));
end

ids层顺时针旋转90度的函数如下:

%% X轴方向进行顺时针旋转
function t = rotX_(t,ids)
N = length(t);
Rx = makehgtform('xrotate',-pi/2);
for x = ids
    for y = 1:N
        for z = 1:N
            if isgraphics(t(x,y,z),'hgtransform')
                t(x,y,z).Matrix = Rx*t(x,y,z).Matrix;
            end
        end
    end
    t(x,:,:) = rot90(squeeze(t(x,:,:)),3);
end

y轴,z轴的函数就不贴了,不然文章就是大段的代码了...

3.根据输入的图像,用高阶魔方拼出来

首先,对于N阶魔方,只有中间的(N-2)*(N-2)的范围可以用来表示图像。我们需要将输入的图像,灰度化,二值化成为一个(N-2)*(N-2)的矩阵。

以一个70阶矩阵为例,其中要表示的图片来自于我之前的一篇文章。(裁掉了周围的空白)

易夕:MATLAB:如何画南开大学校徽?​zhuanlan.zhihu.com
73623ed0e0049df96176472f21cbcd37.png

图像预处理(读取图像,灰度化,二值化,resize图片大小)

N = 70;
data = imread('NKlogo.png');
data = rgb2gray(data);
data = imbinarize(data);
data = imresize(data,[N-2,N-2]);

70阶魔方的生成。大约需要10分钟来生成如此高阶的魔方。(目前实际存在的最高阶的魔方是一个模仿爱好者用3D打印DIY的33阶魔方,花了200多个小时组装,重点是,我觉得很丑...链接在这里)

figure()
ax = gca;
ax.Box = 'off';
axis(ax,'equal','off',[-N,N,-N,N,-N,N]/2);
ax.Projection = 'perspective';
t = magicCube(N);
[A,map] = rgb2ind(frame2im(getframe),256);
imwrite(A,map,'2.gif','LoopCount',65535,'DelayTime',0);

看一看效果图,令人震撼的70阶魔方!

286dc682d1976bf9684ed7252a7e416a.png

按照给出的图片信息,实现魔方的旋转。

for ii = 1:N-2
    ids = N-find(~data(ii,:));
    t = rotZ_(t,N-ii);
    t = rotY(t,ids);
    t = rotZ(t,N-ii);
    t = rotY_(t,ids);`
end

魔方整个旋转的过程,我写入到了一个动图中,如下图所示。Gif大小超过10M,无法上传,这是压缩后的结果。(整个程序,包含写入动图在内,跑了大概10个小时。)

9fca3483ef5bcb985497f43666863f8b.gif
这张图片,花了10个多小时

从不同的角度来看最后的结果。有重影,具体不是很清楚怎么造成的。

5eca72e24f7e60f29c6927d6107ff1e1.gif
哪位大佬知道重影是怎么回事

最后,附送一张32阶魔方拼出的渣打银行logo图。

1e3c109c697874c449d541a0e8d7c0aa.png
搞定了!

专栏目录

易夕:MATLAB Tricks 专栏目录​zhuanlan.zhihu.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值