MATLAB | 文艺复兴:万圣节使用 MATLAB 绘制黑人抬棺动画

hey,大家好久不见,万圣节快到了,来一期趣味编程叭,这期进行一个文艺复兴。绘制黑人抬棺动画:

本期代码的灵感来自 Cleve Moler 的博客:

该博文讲了 Nikolaus Troje 收集的人类步态数据集的经过和原理(仅展示部分):

大体就是让一批受试者佩戴标记,在跑步机上行走,由动作捕捉系统记录 15 个关键节点的三维运动轨迹。对每个受试者的步态轨迹先用五项傅里叶级数拟合,再对所有受试者的傅里叶系数做主成分分析,提取出 5 个主成分,分别对应静态姿态、前进运动、侧向摇摆和两种弹跳模式。

原版代码有 6 个参数,这里为了简单都使用的默认值,所以黑人抬棺动画的人物动作都一模一样,大家可以自行去查看源代码:

进行修改,这里不再赘述。

完整代码

matlab 复制代码
function hrtg
% WALKER  Human gait. Version: March 5, 2016.
%
% References:
% http://blogs.mathworks.com/cleve/2016/04/11/the-eigenwalker-model-of-the-human-gait
% http://jov.arvojournals.org/article.aspx?articleid=2192503
% http://www.biomotionlab.ca/walking.php
% http://www.biomotionlab.ca/Text/WDP2002_Troje.pdf
% http://www.biomotionlab.ca/Text/trojeChapter07b.pdf

% 图窗及坐标区域创建
fig = figure('Units','normalized', 'Position',[.1,.1,.6,.8], 'Color',[1,1,1]);
ax = axes('Parent',fig, 'Position',[0,0,1,1], 'NextPlot','add', 'DataAspectRatio',[1,1,1], ...
    'XColor','none', 'YColor','none', 'ZColor','none');
C = [500, 0;  500, 1500;  500, 3000; 
    -500, 0; -500, 1500; -500, 3000]; N = size(C, 1);
axis([-750,750,-750,750,0,1650] + ...
    [min(C(:,1)), max(C(:,1)), min(C(:,2)), max(C(:,2)), 0, 0])
view(158,20); 

% 获取骨骼数据及笑脸数据,这里 getGenderMeans 存的是男性数据与女性数据均值
V = getGenderMeans(); H = getHappyFace();
X = reshape(V(:,1), 15, 3);
L = {[5 12], [2 3 4 5 6 7 8], [9 10 11 12 13 14 15]};  % Links

% 循环绘制 6 个骨架及笑脸
bHdls = gobjects(N, 4); fHdls = gobjects(N, 1);
for i = 1:N
    for k = 1:3
        bHdls(i, k) = line(ax, X(L{k}, 1) + C(i, 1), X(L{k}, 2) + C(i, 2), X(L{k}, 3), ...
            'color','k', 'marker','o', 'markersize',5, 'linewidth',6);
    end
    bHdls(1).Marker = 'none';
    fHdls(i) = line(ax, [H(:,1) + X(1, 1); X(5, 1)] + C(i, 1), ...
                        [H(:,2) + X(1, 2); X(5, 2)] + C(i, 2), ...
                        [H(:,3) + X(1, 3); X(5, 3)], 'Color','k', 'LineWidth',2.5);
end

% 绘制棺材:懒,直接拿俩立方体拼一起了
bV1 = [.03 .03 0; .97 .03 0; .97 .97 0; .03 .97 0; 0 0 1; 1 0 1; 1 1 1; 0 1 1];
bV2 = [.05 .04 0; .95 .04 0; .95 .96 0; .05 .96 0; .5 .3 1; .5 .3 1; .5 .7 1; .5 .7 1];
bF = [1 2 3 4; 5 6 7 8; 1 2 6 5; 2 3 7 6; 3 4 8 7; 4 1 5 8];
bV1 = bV1.*repmat([750, 3300, 200], [8,1]) + repmat([-375, -150, 1260], [8,1]);
bV2 = bV2.*repmat([750, 3300, 150], [8,1]) + repmat([-375, -150, 1460], [8,1]);
bP = X(6, :);
pHdl1 = patch(ax, 'Vertices',bV1, 'Faces',bF, ...
    'FaceColor',[182,122,99]./255, 'EdgeColor',[108,66,48]./255, 'LineWidth',1.5);
pHdl2 = patch(ax, 'Vertices',bV2, 'Faces',bF, ...
    'FaceColor',[182,122,99]./255, 'EdgeColor',[108,66,48]./255, 'LineWidth',1.5);

% 循环刷新动作
period = 151.5751;
omega = 2*pi/period;
for f = 1:1e4
    t = f*period/48;
    c = [1 sin(omega*t), cos(omega*t), sin(2*omega*t), cos(2*omega*t)]';
    X = reshape(V*c, 15, 3);
    for i = 1:N
        for k = 1:3
            set(bHdls(i, k),'XData',X(L{k}, 1) + C(i, 1), 'YData',X(L{k}, 2) + C(i, 2), 'ZData',X(L{k}, 3));
        end
        set(fHdls(i), 'XData', [H(:,1) + X(1, 1); X(5, 1)] + C(i, 1), ...
                      'YData', [H(:,2) + X(1, 2); X(5, 2)] + C(i, 2), ...
                      'ZData', [H(:,3) + X(1, 3); X(5, 3)])
    end
    set(pHdl1, 'Vertices',bV1 - bP + X(6, :))
    set(pHdl2, 'Vertices',bV2 - bP + X(6, :))
    pause(.02)
end

% warkers.mat 中的数据,觉得还得单独下载会比较麻烦于是直接放这了
    function V = getGenderMeans(~, ~)
        V = .1.*[5,-43,-182,0,1; 2064,14,-131,11,39; 2092,-215,-192,28,15;
            1660,-72,-173,-1,3; -7,-78,-173,2,1; -1664,-79,-178,4,-3;
            -2097,-246,-200,-28,-20; -2016,-36,-168,-19,-49; 536,53,127,0,15;
            794,11,83,-3,47; 931,-73,-145,1,-2; 20,-63,-113,1,0;
            -883,-74,-146,1,-1; -831,17,74,2,-47; -567,61,125,0,-20;
            205,-11,-4,-37,27; 500,-1010,-256,37,9; -686,-606,-174,-11,17;
            -59,-153,-52,-57,32; -114,-7,-4,-62,35; -177,139,44,-61,34;
            -717,691,170,-12,16; 414,1174,254,36,0; -544,2214,-576,327,-259;
            859,1247,170,51,264; -42,-10,-29,-115,80; 78,-10,0,-115,67;
            -58,-10,33,-116,79; 832,-1240,-175,56,266; -557,-2227,586,349,-271;
            13837,1,0,70,86; 7695,-189,-11,124,6; 9721,61,44,82,59;
            12251,-20,22,76,85; 12058,1,0,74,85; 12320,21,-23,78,82;
            9774,-65,-39,83,49; 7766,224,17,119,-23; 984,-120,548,-105,266;
            4122,250,49,123,30; 7897,-12,-31,70,84; 8766,1,1,70,87;
            7889,13,32,70,86; 4157,-249,-52,124,35; 985,127,-548,-116,269];
    end
    function HF = getHappyFace(~, ~)
        HF = [80,0,0; 73.91,0,30.61; 56.57,0,56.57; 30.61,0,73.91; 0,0,80; -30.61,0,73.91; -56.57,0,56.57;
            -73.91,0,30.61; -80,0,0; -73.91,0,-30.61; -56.57,0,-56.57; -30.61,0,-73.91; 0,0,-80; 30.61,0,-73.91;
            56.57,0,-56.57; 73.91,0,-30.61; 80,0,0; NaN,NaN,NaN; -8,0,32; -9.22,0,38.12; -12.69,0,43.31;
            -17.88,0,46.78; -24,0,48; -30.12,0,46.78; -35.31,0,43.31; -38.78,0,38.12; -40,0,32; -38.78,0,25.88;
            -35.31,0,20.69; -30.12,0,17.22; -24,0,16; -17.88,0,17.22; -12.69,0,20.69; -9.22,0,25.88; -8,0,32;
            NaN,NaN,NaN;  40,0,32; 38.78,0,38.12; 35.31,0,43.31; 30.12,0,46.78; 24,0,48; 17.88,0,46.78;
            12.69,0,43.31; 9.22,0,38.12; 8,0,32; 9.22,0,25.88; 12.69,0,20.69; 17.88,0,17.22; 24,0,16;
            30.12,0,17.22; 35.31,0,20.69; 38.78,0,25.88; 40,0,32; NaN,NaN,NaN; -48,0,-19.73; -32,0,-38.4;
            -16,0,-49.6; 0,0,-53.33; 16,0,-49.6; 32,0,-38.4; 48,0,-19.73; NaN,NaN,NaN; 0,0,-80];
    end
end

完

大家万圣节快乐 hiahiahia ~

完整代码网盘:

相关推荐
大江东去浪淘尽千古风流人物7 小时前
【FLORA】机器人视频标注引擎解析:三模型如何产出动作指令与四类奖励信号
matlab·机器人·跨模态·遥感·图像匹配·1024程序员节·特征描述符
星夜离尘5621 小时前
MATLAB ADC 码流触顶诊断:命中数、缺口分段与削顶不可辨识性
开发语言·matlab
Evand J1 天前
【MATLAB例程】平面下,5基站对待定位点的定位。基于距离辅助下的AOA。完整代码下载链接
开发语言·matlab·平面·定位·导航·测距·aoa
iCxhust1 天前
MATLAB SPWM仿真
开发语言·matlab
Moonnnn.2 天前
【MATLAB】零基础入门
matlab
且撷相思红豆枝3 天前
Simulink学习笔记(一)
笔记·学习·matlab
星夜离尘563 天前
MATLAB 角度解缠遇到丢样:先分段,再说明圈数为什么不可恢复
开发语言·matlab
chhttty4 天前
Simulink电机控制框架
matlab·simulink
星夜离尘565 天前
MATLAB 工程实验:不等间隔流量积分,先把缺口与覆盖率说清楚
开发语言·matlab·时间戳·数据质量·数值积分