MATLAB | 官方举办的代码竞赛 | 第四期迷你黑客大赛赛情回顾(二)

文摘   2024-11-16 08:44   英国  

Hey , MATLAB官方举办的迷你黑客大赛距离结束只有负的好几天了:

有没有参与活动并获得MATLAB官方限量版蓝色大裤衩的?(今年还是杯子T恤啥的做礼物,下面这个是特别奖来着)

本次活动涌现出一批非常有意思的动画代码,想要查看代码运行效果,可以简单的将参赛代码和以下这几行代码放在同一个文件夹然后运行下面这几行代码:

for i = 1:96
    drawframe(i)
    drawnow
    pause(.1)
end

竞赛地址:

  • https://www.mathworks.com/matlabcentral/contests/2024-matlab-mini-hack.html

接下来就来看看本次大赛有哪些惊为天人的作品:

作品展示

Timothy / Refraction

  • https://www.mathworks.com/matlabcentral/communitycontests/contests/8/entries/16382

function drawframe(f)
persistent S Q

% Shorteners & convenience functions
l=@linspace;
v=@(x)x./vecnorm(x);
C=@circshift;
cc=@(x)C(x,[-f,-f]*4);
r=@(x)x/2+fftshift(x)/2;
F=@ifft2;
R=@reshape;
B=@erf;
Y=@sqrt;
P=@randn;
J=@meshgrid;

% Make sand and rocks
rng(2,'v4');
N=768;                                          % Multiple of 96 for smooth transition
q=l(-1,1,N+1);
q=q(1:N);
[q1,q2]=J(q);
k=exp(6i*P(N))./(q.^2+q'.^2+2e-6);              % Complex spatial noise
k1=B(abs(F(k))*.5)*0.6-.36;                     % Rocks
n=hann(N)*hann(N)';                             % K-space smoother
k2=abs(F(k.*n.^300))*3+P(N)/200;                % Sand
k2=C(k2+sin(q*30*pi)/20,[-1,-1]*30*-1)/20-.2;   % Adding ripples & offsets to sand
[k,ki]=max(cc(cat(3,r(k1),r(k2))),[],3);        % Combining & indices for coloration

% Sky function: image will be refracted through interface
[x,y,z]=sphere(100);
s=v([1;1;1]);
g=.5-B((Y(sum(((cat(3,x,y,z)-permute(s,[3,2,1])).^2),3))-.5)*5)/2;      % Sky & sun
g=g+B(l(-1.5,1,101)'*3)/2+.5;                                           % Adding horizon
[A,E]=J(l(-pi,pi,101),l(-pi/2,pi/2,101));                               % Associated grid for interpolation

% Angle span
ags=l(0,2*pi,97);

% Camera positions, targets & up-vectors
p=sin(ags(1:end-1))/40;
cy=[p-.8;-p-.8;-cos(2*ags(1:end-1))/15+.05];
cu=C([-p;p;ones(1,96)],[0,5])*1.3;
ct=C(cy.*[1;1;1.4],[0,-5])+[.2;.2;0];
c=cy(:,f);                                      % Current camera position


% Water surface spectrum generation function
d=@(a,b,c,h)ifftshift(n.^10.*exp(6i*P(N)+h*1i)./((q+a).^2+(q+b)'.^2+c));
wt=cc(r(real(F(d(.01,.01,5e-5,ags(f)*3)*.3+d(.02,.06,1e-3,9*ags(f))/3))/5+.4));  % Water surface

% % % Now start computing refractions
% Surf normals of water -> used for refraction
[x,y,z]=surfnorm(q1,q2,wt);
M=[x(:),y(:),z(:)];                 % Normals
X=[q1(:),q2(:),wt(:)];              % Face centers

% Refraction: Camera to surface
ry=v(X'-c)';                                % Camera to surface vectors
I=dot(M,ry,2);                              
I(I<0)=0;                                   % Values <0 would be pointing wrong way
t=Y(1-1.1.^2*(1-I.^2)).*M+1.1*(ry-I.*M);    % Refracted ray vectors
G=imag(t(:,3))~=0;                          % Beyond total reflection
t=real(t);
[Z,L,~]=cart2sph(t(:,1),t(:,2),t(:,3));     % Az & El. of vectors on water surface
L=R(interp2(A,E,g,Z,L,'cubic',0),[N,N]);    % Interpolation into sky map
L(G)=0;

% Refraction: Sun to sand
I=M(:,3);                                   % Sediment normal is ostensibly normal so this is a shortcut
t=real(v((Y(1-0.95.^2*(1-I.^2)).*M+0.95*([0,0,1]-I.*M))')');    % Refracted ray vectors
dxy=t(:,1:2).*(-.2-X(:,3))./t(:,3);                             % Ray intersection offsets
qp=[q1(:),q2(:)];

% More than 10 neighbors is preferable but times out in online execution
[~,D]=knnsearch(qp+dxy,qp,'K',10);                              % Search for 10 closest intersections
V=sum(exp(-1e5*(D.^2)),2)*1.3;                                  % Exponential distance gives caustic value.

% Avoid lighting objects: lambertian scattering approx. for sediment
% surface
[sx,sy,sz]=surfnorm(q1,q2,k);
vc=sx*s(1)+sy*s(2)+sz*s(3);

% Lambertian scattering for surface in non-refracted regions
cwv=v(X'-c)';
[sx,sy,sz]=surfnorm(q1,q2,wt);
wc=R(sx(:).*cwv(:,1)+sy(:).*cwv(:,2)+sz(:).*cwv(:,3),[N,N]);

% Now create coloring for sediment
o=ones(N,N);
c1=cat(3,1,.9,.8).*o;       % Sand
c2=flip(c1,3)/3;            % rock
cA=o.*cat(3,0,.6,1)/2;      % Ambient color;
m=ki-1;                     % mask
cl=(c1.*m+(1-m).*c2).*vc*1.5.*B(R(V,[N,N])/10)*2;   % Color-map

% Create coloring for watersased on refraction of sunlight & ambient
mp=flipud(sky);
mp(1,:)=[0,.6,1]/2;
L(L<.5)=1.5*wc(L<.5);
L(L<.5)=.5;
L(L>1.5)=1.5;
W=ind2rgb(round(255*rescale(L)),mp);

% Need to fade to blue so get distances...
w=B(R(Y(sum((c-[q1(:),q2(:),k(:)]').^2)),[N,N])*2-2)/2+.5;
cl=w.*cA+(1-w).*cl;
W=w.*cA+(1-w).*W;
qn=-((q+1)'.^2+(q+1).^2).^2/50;

% Plotting
if f==1
S=surf(q,q',k,cl);
hold;
Q=surf(q,q',wt+qn,W);
shading flat;
=axis equal off
set(gcf,'color',[0,.6,1]/2);
camproj p
camva(65);
else
S.CData=cl;
Q.CData=W;
S.ZData=k;
Q.ZData=wt+qn;
end
campos(c);
camtarget(ct(:,f));
camup(cu(:,f));
end

Vasilis Bellos / Spooky Halloween

  • https://www.mathworks.com/matlabcentral/communitycontests/contests/8/entries/16391

function drawframe(f)

persistent M A T H W O R K S

% Function shorteners
P=@linspace;
u=@arrayfun;
m=@material;
p=@squeeze;
k=@makehgtform;
i=@find;
n=@numel;

if f==1
    
    % Capillary wave parameters
    % s=.072; % water surface tension (N/m)
    % r=1025; % saltwater density (kg/m^3)
    % r=1e3; % freshwater density (kg/m^3) (saves a character)
    % a=.03; % ripple amplitude (m)
    % T=1; % ripple period (s)
    % w=2*pi/T; % angular frequency (rad/s)
    % Dispersion
    % k1=(w^2*r/s)^(1/3); % wavenumber (rad/m)
    % L=2*pi/k1; % wavelength (m)
    % c=L/T; % wave celerity (m/s)
    % ph=pi/2; % initial phase (rad)

    % Fs=24; % Sampling frequency (96/4)
    T=1/24:1/24:4% Time vector

    % Define the spatial domain (requires fine spatial discretisation for the ripples & adjusted periodicity to facilitate the seamless loop)
    S=4% Controls the spatial discretisation & the movement speed between frames
    M=P(-1.5,1.5,S*96+1); % x
    A=M; % P(-1.5,1.5,S*96+1); % y

    % Define the initial coordinates for each pumpkin
    % W=-1.25:.25:1.5; % xc
    W=(-5:6)/4% xc
    O=repmat([0,-.5,.5],1,4); % yc

    % % Corrected values
    % [~,ind]=u(@(i)min(abs(M-xc(i))),1:n(xc)); W=M(ind);
    % [~,ind]=u(@(i)min(abs(A-xy(i))),1:n(xy)); O=A(ind);
    
    % Calculate the water surface elevation
    H=C(T,M,A,W,O,n,P,p,i);

    % Plotting
    axes(Po=[-.5,-.5,2,2],Vis=0,Ne='a')
    axis([M([1,end]),A([1,end]),-.2,.2],'equal')

    % Water surface
    R=surf(M,A,p(H(f,:,:))',EdgeC='n',FaceC='k',FaceA=.8);
  
    % Camera
    view(3)
    campos([-9 -9 9]) % Tim's trick to save 3 chars
    camva(6)

    % Lighting
    camlight; % This helps discern some the pumpkin details
    light(St='l',Po=[2,2,1],Col='g'% Back light
    lighting g
    
    % Pumpkins
    K=u(@(i)E(P),1:n(W));
    % Duplicate
    K(n(K)+1:2*n(K))=copyobj(K,gca);

    % m(R,'shiny') % Water material
    m('shiny'% Water material
    m(K,[.45,.7,.25]) % Pumpkin material
    
end

% Updating frames

% Water surface
R.ZData=p(circshift(H(f,:,:),S*f,2))';

% Pumpkins

% Add advection
c=[diff(M(1:2))*S*f 0 0]; % Center

% Add rotation
r=P(0,4*pi,2*(n(T)+1));

% x-offset
o=diff(M([1,end]));

for j=1:n(K)

    try
        s=c+[W(j),O(j),H(f,i(M>=W(j),1),i(A>=O(j),1))];
    catch
        s=c-[o,0,0]+[W(j-n(W)),O(j-n(O)),H(f,i(M>=W(j-n(W)),1),i(A>=O(j-n(O)),1))];
    end  
    
    set(K(j),'M',k(Translate=s,Zrotate=r(f)*(-1)^j)); % Some direction variation
    
end

end

    % Capillary wave calculation function
    function e=C(t,x,y,xc,yc,n,l,q,d)

        % Windowing for damping in time
        g=[l(0,1,n(t)/8),l(1,0,n(t)*7/8)]; % Quick ramp-up and then gradual decay

        [X,Y]=meshgrid(x,y);
        for j=1:n(xc)
            for i=1:n(t)

                e(i,:,:,j)=.03*g(i)*sin(2*pi*t(i)-82*sqrt((X-xc(j)).^2+(Y-yc(j)).^2)+pi/2);

                r=.2*t(i);
                x1=abs(x-xc(j))<r;
                y1=abs(y-yc(j))<r;
                
                % Mask
                m=x1.*y1';
                % 3D Hanning window mask to simulate ripple propagation & damping in space
                m(m==1)=ones(n(d(x1==1)),n(d(y1==1)))'.*(hann(n(d(x1==1))).*hann(n(d(y1==1)))')';
                
                e(i,:,:,j)=q(e(i,:,:,j))'.*m';
            end
        end
        e=sum(e,4);
        
    end

    % Pumpkin drawing function
    function P=E(l)
       
        r=@repmat;
        C=@cos;
        S=@sin;
        f=@flip;
        z=@size;
        
        % n=100;
        n=200;
        F=.18;
        p=pi
        
        % Body
        [X,Y,Z]=sphere(n);
        R=(1-(1-mod(0:.1:n/10,2)).^2/12);
        X=R.*X;Y=R.*Y;Z=Z.*R;
                
        % Draw the face for the mask
        
        % Mouth
        x=[-5:5,f(-5:5)]*.12;
        a=[.25 -.5 -.4 -.8 -.65];
        b=[.25 -.1 0 -.4 -.25];
        y=[a -.95 f(a) b -.5 f(b)]*.6+.5;
        
        % Right eye
        x1=[-.42 -.06 -.06 -.42];
        y1=[.6 .5 .5 .9];
        
        % Left eye
        % x2=abs(x1);
        % y2=y1;
                
        % Apply the face mask
        M % Changing this to nested massively lowers the character count
        
        H(1)=surf(X*F,Y*F,(.8+(-l(1,-1,n+1)'.^4)*.3).*Z*F,FaceC=[1,.4,.1],EdgeC='n');

        % Stem
        s=[1.5 1 repelem(.76)].*[r([.1 .06],1,n/20.1]';
        [t,q]=meshgrid(0:p/15:p/2,l(0,p,n/10+1));

        H(2)=surf(r(-(.4-C(q).*s).*C(t)+.4,2,1)*F,[-S(q).*s;S(q).*s]*F,r((.5-C(q).*s).*S(t)+.55,2,1)*F,FaceC='#008000',EdgeC='n');
        
        P=hgtransform;
        set(H,'Pa',P);
      
        % x-rotation
        % function e(X,Y,Z,t)
        function e(t) % Nested
        % Rotation matrices
            Rx=[1 0 0;0 C(t) -S(t);0 S(t) C(t)];
            % Ry=[cos(t(2)) 0 sin(t(2));0 1 0;-sin(t(2)) 0 cos(t(2))];
            % Rz=[cos(t(3)) -sin(t(3)) 0;sin(t(3)) cos(t(3)) 0;0 0 1];
            for i=1:z(X,1)
                for j=1:z(X,2)
                    % r=Rx*Ry*Rz*[X(i,j);Y(i,j);Z(i,j)];
                    d=Rx*[X(i,j);Y(i,j);Z(i,j)];
                    X(i,j)=d(1);
                    Y(i,j)=d(2);
                    Z(i,j)=d(3);
                end
            end
        end        
        
        % Masking function
        % function [X,Y,Z]=M(X,Y,Z,x,y,x1,y1,x2,y2)
        function M % Nested
    
            % Surface is in the form of
            % -1 -1 . . . -1 -1
            %  .  . . . .  .  .
            %  .  . . . .  .  .
            %  1  1 . . .  1  1
            % Easy enough to mask w/ inpolygon (mask projected onto pumpkin)
            
            i=@inpolygon;
            % Rotate to align ribs with face
            % [X,Y,Z]=e(X,Y,Z,-pi/2);
            e(-p/2);
            % Mask
            m=ones(z(Z));
            % mask((i(X,Y,x,y)|i(X,Y,x1,y1)|i(X,Y,x2,y2))&Z>=0)=NaN;
            m((i(X,Y,x,y)|i(X,Y,x1,y1)|i(X,Y,abs(x1),y1))&Z>=0)=NaN;
            Z=Z.*m;
            % Rotate back
            % [X,Y,Z]=e(X,Y,Z.*m,pi/2);
            e(p/2);
            
        end
    
    end

Matteo / Trapped particles++

  • https://www.mathworks.com/matlabcentral/communitycontests/contests/8/entries/16395

% This demo features a simple particle system, where particles are emanated
% from a point source located at the origin and follow trajectories
% described by Brownian motion while being constrained to move inside the
% 3D unit ball. Each particle is assigned its own dynamic properties and
% deforms and changes its color according to its position and lifetime.
% When a particle collides with the unit sphere, a "lightning" that
% connects that particle with the origin is drawn.
% Additionally, the plot in the current axes is captured and
% post-processing effects are applied to it (chromatic aberration, blooming).
 
function drawframe(f)
persistent O
% Global parameters to fine-tune visual output:
n=75;                % number of particles
F=96;                 % number of frames
col0=[0.2 0.6 1];   % color of particles (at the origin)
col1=[1 0.6 0.2];   % color of particles (on the unit sphere)
step=0.1;             % distance travelled by particle at each time step
fov=120;               % camera field-of-view
outsize=[320 320];     % size of output frames

% Rename frequently occurring functions with long names to save characters:
tpf=@transformPointsForward;
r=@rescale;
g=@imgaussfilt;
m=@(a,b)mod(a-1,b)+1;

% Do not recalculate animation frames that have been already created!
if size(O,4)==F
    imshow(O(:,:,:,f),Border="tight");
    return
end

% Start by rendering animation from frame 41 to have a better thumbnail:
f=m(f+40,F);

% Precalculate data for animation: 
% Imploding factor (used to make animation loop smoothly):
rho=g([ones(F-20,1);zeros(20,1)],10,FilterSize=[61 1]);

% Calculate coordinates of the particles at each frame by applying
% Brownian motion:
rng twister;
P=randn(F,n,3)*step;
P=imgaussfilt3(P,4,FilterSize=[255 1 1],Padding="circular");
P=rho.*cumsum(P);

% Constrain the particles to lie inside the unit ball:
R=vecnorm(P,2,3).*ones(1,1,3);
out=R>1;
P(out)=P(out)./R(out);

% Generate transformation matrices to make particles wobble:
M3=0.2*rescale(rand(1,1,n),1/2,2).*(eye(3)+(randn(3,3,n)*0.2 .*blkdiag(ones(2),0)) );
M3=imgaussfilt3(M3,[1e-2 1e-2 1],'Padding','circular');
M=affinetform3d;
for i=1:n
    M(i)=affinetform3d(blkdiag(M3(:,:,i),1));
end

% Generate the texture image for the particles:
tex=r(fspecial('gaussian',32,8/6))+0.3*r(fspecial('gaussian',32,32/6));
tex=imadjust(tex,[0 0.6]);

% Set figure background to black:
figure(1);
set(gcf,'Pos',[0 0 outsize],'Color',col0/10);

% Remove axes and set camera properties:
cla;
axis equal off;
axis([-1 1 -1 1 -1 1]);
campos([0 0 cscd(fov/2)]);
camup([0 1 0]);
camva(fov);
camproj perspective;
set(gca,YDir="normal",Units="normalized",Position=[0 0 1 1],Clipping="off");

% For each particle that touches the unit sphere,draw a "lightning"
% emanating from the origin and reaching that particle:
rng shuffle twister;
q=0.02*randn(20,n,3);
q([1 end],:,:)=0;
l=linspace(0,1,20)'.*P(f,:,:)+q;
l(:,~out(f,:,1),:)=[];
line(l(:,:,1),l(:,:,2),l(:,:,3),'LineW',1.5,'Color',[col1 0.2]);

% In object space,each particle is represented as one quad with its
% vertices sitting on the corners of the unit square of the xy-plane:
[X0,Y0,Z0]=meshgrid([-1 1],[-1 1],0);

% Get the xyz-coordinates of the unit sphere:
[U0,V0,W0]=sphere(64);

% Render settings for particles:
preset={'EdgeC','none','FaceL','none','FaceA','texturemap','AlphaDataM','none'};

% Loop to draw particles:
for k=1:n
    % Take the next matrix and apply the corresponding distortion to the unit square:
    q=m(k+f,n);
    [X,Y,Z]=tpf(M(q),X0,Y0,Z0);

    % Assign color to each particle such that particles that are
    % close to the origin are more blue and those that are closer to the
    % unit sphere are reddish.
    col=interp1([0;1],[col0;col1],min(R(f,k),1).^3 );
    
    % Assign alpha value to each particle such that particles that are
    % far from the observer tend to fade away:
    alpha=r(P(f,k,3),0.1,1,InputMin=-1,InputMax=1);
    
    % Draw the current particle:
    surface(X+P(f,k,1),Y+P(f,k,2),Z+P(f,k,3),'FaceC',col,'AlphaData',tex*alpha,preset{:});
end

% Slightly rotate the unit sphere:
RT=rigidtform3d(5*sin(2*pi*f/F.*[1 1 1]+[0 pi/3 pi/4]),[0 0 0]);
[U,V,W]=tpf(RT,U0,V0,W0);
surface(U,W,V,'FaceC','none','EdgeC',col0,'EdgeA',0.05,'LineW',rand*5);

% Post-Processing part...
A=im2double(frame2im(getframe(gca)));

% Simulate chromatic aberration by zooming each color channels by a
% slightly different factor:
[U,V]=meshgrid(linspace(-1,1,width(A)),linspace(-1,1,height(A)) );
D=-cat(3,U,V)*6;
for c=1:3
    A(:,:,c)=imwarp(A(:,:,c),D*(c-1),'linear');
end

% Apply monochromatic Gaussian noise (only for uncompressed video):
% A=max(min(A+randn(size(A,1:2))*3/255,1),0);

% Apply "blooming" to the image:
B=rgb2gray(A);
B=imadjust(B,[0.1 1]);
B=g(B,32,FilterSize=193,Padding="replicate");
B=r(B);
A=A+r(B);

% Restore original frame number:
f=m(f-40,F);

% Display post-processed image and store it in a persistent variable:
imshow(A,Border="tight");
O(:,:,:,f)=A;
end

Kaustubh / Never Gonna Give You Up

  • https://www.mathworks.com/matlabcentral/communitycontests/contests/8/entries/16403

这个放代码没啥意义,这是真正意义上的迷你黑客,本次活动要求提交一个音频来配合MATLAB制作的动画生成有声视频,这位参赛者把视频的数据藏进了音频数据中:


Jenny Bosten / Lake view to the Nort

  • https://www.mathworks.com/matlabcentral/communitycontests/contests/8/entries/16404

function drawframe(f)
persistent I1 l
    if f==1
        %Declare functions to save space
        u=@linspace;
        e=@rescale;
        n=@normpdf;
        h=@flipud;
        z=@zeros;
        l=@repelem;
        M=@repmat;
        d=@rand;
        b=@randi;
        q=1000;
        st=30%number of striations
        cb=4%number of colorbands (note if this increases > 3, more RGBs will be needed

        %makes a matrix of stars, initially these are 2x4 rectangles as every
        %other pixel will be taken later
        m=l((d(q/4,q/2)/.5+.5).*floor(b(3*q/2,q/4,q/2)/(3*q/2)),4,2);
        m(m~=0)=1;

        %vector of values as basis for drawing image
        X=u(-1,1,q);
        [th1, r1] = cart2pol(X,X');
        th=u(pi,2*pi,st*2);
        %matrix of coords to draw into
        [y,x]=meshgrid(X);
        k1=erf(abs(ifft2(exp(6i*randn(q))./(X.^2+X'.^2+9e-5)))); %rock texture from Tim!
        a1=z(q);
        a2=a1+1;
        a2(x<(.3*(3*-y.^2+3*k1(1,:))+.8))=0;
        M3=M(.55*k1.*a2,1,1,3);
        M3(:,:,2)=M3(:,:,2)*1.2;

        %y offsets of the striations - in an arc
        yo=z(st,cb,96);
        el=-[sin(th(1:st).') sin(th(st+1:2*st).') ]-.5;
        yo(:,:,1)=[el-.5 el-1.4];
        %medium offsets for the first 2 striations in each colour band
        yo(1:4,:,1)=[z(4,2)-.3 z(4,2)-1.2];

        %yo: pregenerate Y offset jitter to return to baseline within 96 frames (to
        %avoid jumps between the segments of the movie stitched together by
        %contestMovieGenerator
        %ic: pre-generate increments in x position of striations to go back to starting position
        %over 96 frames
        ic=z(st,cb,96);
        ic(:,:,1)=1.5*(sort(d(st,cb))-.5);
        ic(1:2,1:cb,1)=z(2,cb);
        ic(3:4,1:cb,1)=z(2,cb)+(d(2,cb)-.5);
        for p=1:47
            ic(:,:,p+1)=ic(:,:,p)+(d(st,cb)-.5)/80;
            yo(1:4,:,p+1)=yo(1:4,:,p)+.15.*(d(4,cb)-.5);
            yo(5:end,:,p+1)=yo(5:end,:,p)+.1.*(d(st-4,cb)-.5);
        end
        for p=1:48
            ic(:,:,p+48)=ic(:,:,49-p);
            yo(:,:,p+48)=yo(:,:,49-p);
        end

        %x offsets of 3 main colour bands
        o=[-.7 .7 -.7 .7];

        %Gaussian standard deviations of striation bands
        wg=.008+(z(st,cb));
        wg(1:2,:)=.5*ones(2,cb); %large standard deviations for 2 bands in each colour
        wg(3:4,:)=.2*ones(2,cb);

        %start and end RGB values per colour band
        R2=[1 .49 .45 .84 .74 .66
            .83 .07 .30  .66 .71 .64
            .70 .89 .82 .47 .74 .29];
        R2(4,:)=R2(3,:);

        %standard deviation of striations in the Y
        yg=(d(st,cb)+.3)./3;

        %large stanard deviations for the first 2 striations in each colour
        %band
        yg(1:4,:)=z(4,cb)+.5;

        %opacity of each colour band
        ap=[.9 .9 .7 .7];

        %angles of striations in each colour gradient
        an=[u(-.25,0,st)
            u(0,.25,st)];
        an=[an;an];

        %striation jitter in angle
        aj=(d(st,1)-.5)*.08;

        % decides whether striations will be increments or decrements in
        % intensity
        mu=round(d(st,cb)+.2)*2-1;

        %first 2 in each band are always increments
        mu(1:2,:)=ones(2,cb);
        mu(3:4,:)=-ones(2,cb);

        m6=e(n(x,-.3,.8),0,1); %these matrices the position of the colour bands (Gaussian filter)
        m7=e(n(x,.5,.8),0,1);
        x2=h(x+.4); %these matrices control the position of the colour gradients behind the aurora bands
        x3=h(x+1);
        I1=z(q,q,3,48); %declare large image matrix
        ps=u(.5,.8,10)
        for fg=1:48 %make 48 frames (animation changes every 2 frames)
            fm=z(q,q,3);
            %This is done for each frame
            for i1=1:cb
                a=a1;
                for j=1:st
                    %rotate the x and y matrices to achieve striations at an angle.
                    %Includes jitter.
                    y1=y*cos(an(i1,j)+aj(j))+x*sin(an(i1,j)+aj(j));
                    x1=y*sin(an(i1,j)+aj(j))+x*cos(an(i1,j)+aj(j));

                    %this is the line that creates 24 striation layers on each frame
                    %and adds them to the current matrix for the frame. The y1 part
                    %does the striation in the x direction. The x1 part puts a Gaussian
                    %envelope in the vertical Y direction, also with jitter. The wg
                    %part scales the intensity of the striation inversely to the
                    %standard deviation. Adjusting the .^7 parameter can change the
                    %results.
                    a=a+mu(j,i1)*(wg(j,i1).^ps(randi(10))).*e(n(y1,ic(j,i1,2*fg)+o(i1),wg(j,i1)),0,.2).*e(n(-x1,yo(j,i1,2*fg)+.3,yg(j,i1)),0,.2);
                end
                %compiles the matrix for each colour band in a cell array, applies a
                %vertical mask to create the vertical gradient to black (well, rotated
                %vertical)
                p1{i1}=a;
                %Creates an RGB matrix for one of the colour bands as a straight
                %gradient in the Y direction
                mm=m7;
                xx=x3;
                for j=1:3
                    if i1<=2
                        mm=m6;
                        xx=x2;
                    end
                    %combines aurora Gaussian mask with color gradient matrices with RGB applied, different
                    %for the upper and lower aurora bands
                    b1(:,:,j)=mm.*(xx.*R2(i1,j)+(1-xx).*R2(i1,j+3));
                end
                %combines the RGB matrix with the striations to create striated colour
                %matrices. Saves one for each of the 3 colour bands in a cell array
                fm=fm+b1.*M(e(p1{i1},-.1,ap(i1)),1,1,3);
            end
            fm(M3>0)=M3(M3>0);%add mountain
            %Creates star twinkles
            m1=m.*(d(q)*.5+.3);
            m1(M3(:,:,1)>0)=a1(M3(:,:,1)>0);%remove any stars from inside mountain
            m1=[m1(1:2:end,:);h(m1(1:2:end,:))]; %reflect stars
            %combines the 3 RGB images into one RGB matrix
            fm1=fm(1:2:end,:,:);
            fm2=h(fm1).*.5%reflects and darkens the main image
            for k=1:q/2
                fm2(k,:,:)=circshift(fm2(k,:,:),b(15),2); %creates ripples
            end
            I1(:,:,:,fg)=M(m1,1,1,3)+e([fm1;fm2].*e(-r1,0,1),0,1); %creates the image by combining the reflected and unreflected elements and the stars. Rescales.
        end
    end
    b1=l(1:48,1,2);
    image(I1(:,:,:,b1(f))) %presents the RGB image, every other frame to slow down
    camva(4.8)
end

Kaustubh / The Matrix : Laboratory

  • https://www.mathworks.com/matlabcentral/communitycontests/contests/8/entries/16389

function drawframe(f)

    persistent text_str offsets ycoor xcoor

    numChars = 48;
    numColumns = 200;
    
    if f==1

        figure
        set(gca,'Position',[0 0 1 1])
       
        % Generate random characters within the specified range
        randomUnicodeCodes = randi([33126], numChars, numColumns);
        text_str = cellstr(char(randomUnicodeCodes(:)));

        % offsets the start of animation for a given column
        offsets = randi([0,95],numColumns,1);

        xcoor = randi([0,600],numColumns,1);
        ycoor = randi([-300,0],numColumns,1);
    
    end
    
    im = zeros(600,600,3);
    
    textSize = 18;
    ydelta = 1.2 * textSize;
    trailLength = 32;

    % Precompute row and column indices
    [cIdx, rIdx] = meshgrid(1:numColumns, 1:numChars);
    cIdx = cIdx(:);
    rIdx = rIdx(:);
    
    % Calculate position matrix
    position = [xcoor(cIdx), ycoor(cIdx) + rIdx * ydelta];

    % Calculate color matrix
    progress = mod(offsets(cIdx) + f, 96);
    inTrail = (2 * rIdx <= progress) & (2 * rIdx > progress - trailLength);
    clr = zeros(numChars * numColumns, 3);
    clr(inTrail, 2) = 1 - (progress(inTrail) - 2 * rIdx(inTrail)) / trailLength;
    clr(inTrail, 1) = clr(inTrail, 2) / 2;
    clr(inTrail, 3) = clr(inTrail, 1) / 2;


    % Condition for on-screen positions
    onScreenIdx = (position(:,1) >= 1 & position(:,1) <= 600 & ...
                   position(:,2) >= 1 & position(:,2) <= 600);

    % Condition for non-black colors
    nonBlackIdx = any(clr ~= 02);

    % Combine conditions
    validIdx = onScreenIdx & nonBlackIdx;

    % Filter position, text, and color arrays
    filteredPosition = position(validIdx, :);
    filteredText = text_str(validIdx);
    filteredClr = clr(validIdx, :);

    % Insert only the valid text
    im = insertText(im, filteredPosition, filteredText, FontSize=textSize, ...
                    BoxOpacity=0, TextColor=filteredClr);

    % the character at the beginning of the trail
    for c=1:numColumns
        im = insertText(im,[xcoor(c) ycoor(c)+mod(offsets(c) + f, 96)/2*ydelta], text_str(c+f), FontSize=textSize, ...
                    BoxOpacity=0, TextColor=[0.5 1 0.3]);
    end

    imshow(im)
end

Zhaoxu Liu / slandarer / Dragon in the deep sea

  • https://www.mathworks.com/matlabcentral/communitycontests/contests/8/entries/16319

function drawframe(f)
persistent M V R T D rT dH N
if f == 1
V=[ -.016,.822-.074,.809-.114,.781-.147,.738-.149,.687-.150,.630;
          -.157,.554-.166,.482-.176,.425-.208,.368-.237,.298-.284,.216;
          -.317,.143-.338,.091-.362,.037;-.382,-.006;-.420,-.051;-.460,-.084;
         -.477,-.110;-.430,-.103;-.387,-.084;-.352,-.065;-.317,-.060;-.300,-.082;
         -.331,-.139;-.359,-.201;-.385,-.262;-.415,-.342;-.451,-.418;-.494,-.510;
         -.533,-.599;-.569,-.675;-.607,-.753;-.647,-.829;-.689,-.932;-.699,-.988;
         -.639,-.905;-.581,-.809;-.534,-.717;-.489,-.642;-.442,-.543;-.393,-.447;
         -.339,-.362;-.295,-.296;-.251,-.251;-.206,-.241;-.183,-.281;-.175,-.350;
         -.156,-.434;-.136,-.521;-.128,-.594;-.103,-.677;-.083,-.739;-.067,-.813;-.039,-.852];
V=[0,.82;V;V(end:-1:1,:).*[-1,1];0,.82];
V=V-mean(V,1);
F=1:size(V,1);
Y=V(:,2);
Y=(Y-min(Y))./(max(Y)-min(Y));
N=60;
R=sin(linspace(pi/4,5*pi/6,N))./1.2;
R=[R',R'];R(1,:)=[1,1];
R(5,:)=[2,.6];
R(10,:)=[3.7,.4];
R(15,:)=[1.8,.6];
T=[zeros(N,1),ones(N,1)];
M=zeros(N,2);
D=M;
rT=@(Mat,t)Mat*[cos(t),sin(t);-sin(t),cos(t)];
C=[68,231,197;211,102,88;38,52,95]./255;
C1=C(2,:)+Y.*(C(1,:)-C(2,:));
C2=C(3,:)+Y.*(C(1,:)-C(3,:));
hold on
set(gca,'Color','k','DataAspectRatio',[1,1,1],'Position',[0,0,1,1],'YTick',[]);
axis([-5,5,-5,5])
FV='FaceVertexCData';
FC={FV,C1,'FaceAlpha',.7};
dH(1)=patch('Faces',F,'Vertices',V-[2,0],FV,C1,'FaceColor','interp','EdgeColor','none','FaceAlpha',.95);
for i=2:N
    dH(i)=patch('Faces',F,'Vertices',V.*R(i,:)-[2,i./2.5-.3],FV,C2,'FaceColor','interp','EdgeColor','none',FC{3:4});
end
set(dH(5),FC{:})
set(dH(10),FC{:})
set(dH(15),FC{:})
for i=N:-1:1,uistack(dH(i),'top');end
for i=1:N
    M(i,:)=mean(get(dH(i),'Vertices'),1);
end
D=diff(M(:,2));
else
t=f/96*4*pi;r=10*(1-cos(t));
Pos=[r*cos(t).*2*((f>48)-.5),-r*sin(t).*1.5] + [2,0];
Dir=Pos-M(1,:);
Dir=Dir./norm(Dir);
T=(T(1:end,:)+[Dir;T(1:end-1,:)])./2;
T=T./(vecnorm(T')');
theta=atan2(T(:,2),T(:,1))-pi/2;
M(1,:)=M(1,:)+(Pos-M(1,:))./80;
M(2:end,:)=M(1,:)+[cumsum(D.*T(2:end,1)),cumsum(D.*T(2:end,2))];
for ii=1:N
    set(dH(ii),'Vertices',rT(V.*R(ii,:),theta(ii))+M(ii,:))
end
end
end

Malik / Moonlit Night

  • https://www.mathworks.com/matlabcentral/communitycontests/contests/8/entries/16414

% This entry is a remix of the previous two entries from last years:
% 1) 'Midnattsol' created by Jenny Boston 
%     https://www.mathworks.com/matlabcentral/communitycontests/contests/6/entries/12937

% 2) 'the mountains are calling' created by Jr
%     https://www.mathworks.com/matlabcentral/communitycontests/contests/4/entries/3246

% Thanks to both of them. While remixing, I learned a lot.
% I will explain the changes I've made throughout the code.

function drawframe(f)
% Modified the RGB triplets to create a moonlit night sky view:
% Black-Navy-Blue-White
    g1 = [0 0 010 24 4630 60 10090 130 180180 210 240240 240 255];
    g2 = [0 0 05 15 3015 30 6080 100 160150 180 220240 240 255];

    
    tf = 96% Total number of frames
    z = linspace(16100);
    d = [linspace(1030, tf / 2), linspace(3010, tf / 2)];
    x(:, :, 1) = interp1(1:6, g1, z);
    x(:, :, 2) = interp1(1:6, g2, z);
    x = permute(x, [312]);
    x = permute(interp1([1, tf], x, 1:2:tf), [231]) ./ 255;
    x = cat(3, x, x(:, :, end:-1:1));

    a = 1000;
    X = linspace(-255255, a);
    % Removed the linearly generated vectors 'q' & 'm' used for creating
    % the sunset & sunrise view in the original entry.
    
    % Moon effect
    % Changed [t, r] = cart2pol(X - q(f), 100 + X' - 100 * cos(m(f))) 
    % to make the moon static.
    [t, r] = cart2pol(X, 100 + X');
    [x_i, y_i] = find(r < 15);
    [x_i2, y_i2] = find(r < 5);

    b = x(:, :, f);
    j = [0.9 0.9 1];  % Light gray for the moon glow
    colormap([jflipud(b)]);

    r(r < 14) = 0.9;

    % To keep the mountains static throughout the animation, I added
    % 'rng default' in the createMountains function. Therefore, I added 
    % 'rng shuffle' here to preserve randomness in the river current.
    rng shuffle
    for k = 1:300
        % Adjusted some parameters
        y(k, :) = circshift(r(min(x_i), :), randi(30) - 15);
        y(k, y_i2 + round(randi(round(d(f))) - d(f) / 2)) = 0.9;
    end

    imagesc([r(100:600, :); y]);
    axis equal;
    axis off;
    xlim([100 900]);

    % Draw Mountains
    mountains = createMountains();
    hold on;
    for i = length(mountains):-1:1
        mountainColor = i / 8 * [30 60 100] / 255;
        fill(mountains{i}(:, 1), mountains{i}(:, 2), mountainColor, 'EdgeColor''none');
    end
    hold off;
    camva(5.9);
end

% Mountain Range
function mountains = createMountains()
    % Set the random number generator to default so that the sequence 
    % remains the same across frames, ensuring the mountain range stays fixed.
    rng default 

    c = 900;  % Maximum x-coordinate
    n = 800;  
    m = 0.8;  
    mountains = cell(81);  % Store mountain data

    % Set the height range for the mountains: the base is at y = 500 
    % and the peak can rise up to y = 370. Set the peak to a low value and 
    % the foot to a high value because of 'circshift'.
    peak = 370;
    foot = 500;

    % Create 8 mountains
    for i = 8:-1:1
        y_mountain = peak + i / (8 + 3) * (foot - peak);  % Height between peak and foot
        a = 160 * m^(i - 1);
        u = c * (1 - (i - 1) / 8);
        x_mountain = linspace(100, c, n);
        p = y_mountain / 700 * 4 * pi;
        t = x_mountain * 2 * pi / u;
        q = sin(p + t) + sin(p + 0.3 * t);
        r_mountain = y_mountain + q * a + cumsum(sqrt(0.4 * a) * randn(1, n)) + 3.2^(i - 1);

        % Normalize r_mountain to be between the peak and foot
        r_mountain = foot - (foot - peak) * (r_mountain - min(r_mountain)) / ...
                    (max(r_mountain) - min(r_mountain));

        v = [x_mountain' r_mountain'; c foot; 0 foot];
        mountains{i} = v;  % Store the mountain polygon
    end
end

William Dean / Trefoil Spring

  • https://www.mathworks.com/matlabcentral/communitycontests/contests/8/entries/16407

    function drawframe(f)
    % draws the surface of a 'spring' stretched along the path of a trefoil
    % knot with a compression wave travelling through it
        persistent N n H t x y z X Y Z u v w R nT F CM U MC L C S D p

        % setup
        if f == 1

            %% helper functions

            F = @cellfun;
            CM = @cell2mat;
            MC = @mat2cell;
            L = @linspace;
            C = @cos;
            S = @sin;
            U = 'UniformOutput';
            D = {'XData','YData','ZData','CData'};
            p = 2*pi;

            %% figure/axes

            % set axes props
            set(gca,'Visible','off','Units','Normalized','InnerPosition',[0 0 1 1],'XLim',[-4 4],'YLim',[-4.4 3.6],'ZLim',[-4 4],'NextPlot','Add');
            pbaspect([1 1 1]);daspect([1 1 1]);

            % set figure background color
            set(gcf,'Color',[0 0 0]);

            % lighting
            lighting gouraud;
            camlight headlight;

            %% tube/spiral properties

            % number of circles used to define the tube surface
            N = 6720;
            % number of points to create each circle cross-section
            n = 50;
            % radius of the central rube, defines the distance of the spiral
            % from the central path
            R = .5;
            % Number of spiral turns around the central tube
            nT = 48;
            % parameter for the trefoil knot curve
            t = L(0, p, N);
            % trefoil knot parametric equations
            x = S(t) + 2 * S(2 * t);
            y = C(t) - 2 * C(2 * t);
            z = -S(3 * t);
            % tube surface
            H = surf(D{1},[],D{2},[],D{3},[],D{4},[],'EdgeColor','none','FaceAlpha',1);

        end


        %% set up compression wave

        % index shift for this frame
        I = mod((f - 1) * (N / 96), N); % Shift by fixed amount per frame
        % modify t with cosine shaped compression effect, centered on mod((f-1)/96,95)*2*pi, intensity 0.4
        tM = cumsum(1-.4*C(t-mod((f-1)/96,95)*p));
        tM = tM / max(tM) * p;
        % shift the compressed t
        tS = [I+1:N,1:I];
        tSh = tM(tS);
        % interpolate x, y, and z using the compressed, shifted t values
        Q = @(a) interp1(t,a(tS),tSh,'pchip');
        xC = Q(x); yC = Q(y); zC = Q(z);

        %% create the tube and the spiral

        % anonymous func to set last column equal to first column
        W = @(a) a(:,[1:N-1,1]);
        % get trefoil tube surface (X,Y,Z) and spiral path (u,v,w) coordinates
        [X,Y,Z,u,v,w] = ST(xC,yC,zC,R);
        % match spiral endpoints
        u = W(u); v = W(v); w = W(w);
        % create another tube that follows the spiral path
        [X,Y,Z,~,~,~] = ST(u,v,w,.1);
        % match endpoints
        X = W(X); Y = W(Y); Z = W(Z);
        % reorder the circle points to correct overtwisting
        % -> for each circle, i, rotate circle i+1 until distance between
        %    points minimized
        for i = 1:N-1
            j = i+1;
            [~,l] = min(sqrt((X(:,j)-X(1,i)).^2+(Y(:,j)-Y(1,i)).^2+(Z(:,j)-Z(1,i)).^2));
            k = [l:n,1:l-1];
            X(:,j) = X(k,j); Y(:,j) = Y(k,j); Z(:,j) = Z(k,j);
        end

        % sometimes need the swap below if the spiral tube radius is very small
        % X(:,1) = X(:,end);
        % Y(:,1) = Y(:,end);
        % Z(:,1) = Z(:,end);
        % make sure the last point of each circle is identical to the first point
        X(n,:) = X(1,:);
        Y(n,:) = Y(1,:);
        Z(n,:) = Z(1,:);

        %% update surface
        
        % update tube surface coordinates
        set(H,D{1},X,D{2},Y,D{3},Z,D{4},repmat(L(0,1,N),n,1));
        % shift the colormap to move colors along the spiral
        M = hsv;
        Ci = round((f/96)*256);
        colormap(M([Ci+1:end,1:Ci],:));

        drawnow
        
        function [TX,TY,TZ,SX,SY,SZ] = ST(PX,PY,PZ,CR)
        % returns surface coordinates for a tube (TX, TY, & TZ) traveling along the path 
        % defined by PX, PY, and PZ. Also returns coordinates for the path of a
        % spiral (SX, SY, & SZ) traveling along the outside of the tube.
        
            c = @cross;
            g = @norm;
            d = @diff;

            % points along the path
            P = [PX',PY',PZ'];
        
            % cell array of normalized tangent vectors at each point along the path
            tN = F(@(a) a/g(a),MC([d(P([1:N,1],1)) d(P([1:N,2],2)) d(P([1:N,3],3))],ones(N,1),3),U,0);
        
            % find two vectors normal to each tangent to form a basis for each circle
            N1 = F(@(a) c(a,[1 0 0]),tN,U,0);
            N1 = F(@(a) a/g(a),N1,U,0);
            N2 = F(@(a,b) c(a,b),tN,N1,U,0);
        
            % generate circle points around each point on the path
            T = L(0, p, n);
            % coordinates for each circle
            cPt = F(@(a,b) CR*(a'*C(T)+b'*S(T))',N1,N2,U,0);
            % make sure the endpoints exactly match
            cPt = F(@(a) a([1:end-1,1],:),cPt,U,0);
        
            % cell array of tube surface points
            K = F(@(a,b) a+b,MC(P,ones(N,1),3),cPt,U,0);
        
            % matrices of tube surface points
            TX = CM(F(@(a) a(:,1),K,U,0)');
            TY = CM(F(@(a) a(:,2),K,U,0)');
            TZ = CM(F(@(a) a(:,3),K,U,0)');
        
            % spiral angles
            A = p * nT * (1:N) / (N-1);
            % spiral points
            SP = CM(F(@(a,b,i) [P(i,1)+CR*C(A(i))*a(1)+CR*S(A(i))*b(1);P(i,2)+CR*C(A(i))*a(2)+CR*S(A(i))*b(2);P(i,3)+CR*C(A(i))*a(3)+CR*S(A(i))*b(3)],N1',N2',arrayfun(@(ii,1:N,U,0),U,0));
            SX = SP(1,:);
            SY = SP(2,:);
            SZ = SP(3,:);
        
        end

    end

后言

这期参赛人数和提交作品数量少了很多,但是精品率明显提高,MATLAB官方代码竞赛已经举办多期,由图片到动图再到视频制作,每一年的挑战性都在慢慢增大,大家可以蹲一下明年的竞赛看看会是什么形式,万一能拿到纪念品还是很有意义的:


slandarer随笔
slandarer个人公众号,目前主要更新MATLAB相关内容。
 最新文章