見出し画像

MATLAB で透明度付きプロット~円は rectangle で

MATLAB の Line は透明度が指定できない?


ツイッターで

「MATLAB の Line は透明度が指定できない」

という投稿を見かけました。

「そうなんだよな~」

と思って代替方法を。

patch 関数

th = 0:pi/20:2*pi;
y = sin(th);
patch([th,fliplr(th)],[y,fliplr(y)],'b','LineWidth',2,'EdgeColor','b',"EdgeAlpha",0.1);
patch([th,fliplr(th)],[y,fliplr(y)]+0.2,'b','LineWidth',2,'EdgeColor','b',"EdgeAlpha",0.5);
patch 関数による透明度付きプロット

"patch" なら、α を指定できます。
ただ、本来は多角形の描画関数なので始点と終点を一致させる必要があり、上記スクリプトのように flip を使って折り返しています。

> 2022/06/11 追記


flip しなくても最後に NaN を追加すれば良いことが公式ドキュメントに書いてありました。
そういえば見た気がする・・。

th2 = [th NaN];  y2 = [y NaN];
patch(th2,y2,'b','LineWidth',2,'EdgeColor','b',"EdgeAlpha",0.1);
patch(th2,y2+0.2,'b','LineWidth',2,'EdgeColor','b',"EdgeAlpha",0.5);

最後の例も修正しました。



似たような関数で "polyshape" があります。こちらも透明度は指定可能ですが「囲まれた領域」が含まれている必要があり、上記のような指定はできません。

polyshapeの使用例はこちらをご覧ください。


隠された4次元目

でもその後、「あれ・・?」となんかモヤモヤ・・。

急に、

「確か、4次元目に直接指定すれば Line でも α が指定できた気がする!?」

というのを思い出しました!

for alpha = 0:0.1:1
    plot(y+alpha, LineWidth=2, Color=[1 0.5 0 alpha])
    if alpha == 0; hold on; end
end
hold off
plot 関数による透明度付きプロット

できました!

なぜかマニュアルにも載ってないですし、

>> p=plot(y, LineWidth=2, Color=[1 0.5 0 0.1])

p = 

  Line のプロパティ:

              Color: [1 0.5000 0]

プロパティにも表示されません。

実行結果

しかし、

p.Color=[p.Color 0.5];

とプロパティを変更すれば透明度が更新されます。

透明度を更新


rectangle 関数

同様に "rectangle" も、直接 α チャネルを指定すればokです。(u_u)

for r=0.1:0.1:1
    pos = [0 0 r r];
    rectangle(Position=pos, LineWidth=2, EdgeColor=[0 0 1 r^3], Curvature=[1 1])
    pos = [-r/2 -r/2 r r];
    rectangle(Position=pos, LineWidth=2, EdgeColor=[1 0 0 r^3], Curvature=[1 1])
end
rectangle 関数による透明度付きプロット


確かだいぶ前にできることに気付いたんですが、

しばらく経って「できたっけ?」

と思ってマニュアル確認すると載ってないので、

「勘違いだったか・・」

と思ってしまっていたようです。(^_^;)


後から透明度変更

後から透明度を変更すれば、このようなこともできます。
一旦全て同じ透明度で描いてから、後から透明度だけを変更しています。

一旦全てを同じ透明度で描画
後から部分的に透明度を変更
% clear
f = figure(1);
cla

line = true;  % true : plot、false : patch

% 背景画面描画
th = 0:pi/20:2*pi;
y = sin(th);
for alpha = 0:0.1:1
    plot(th, (y+alpha/2), LineWidth=2, Color=[1 0.5 0 alpha])
    if alpha == 0; hold on; end
end


th = 0:pi/50:2*pi;  % 各sin関数のステップ設定
th2 = 0:pi/50:2*pi; % 移動量設定
N = length(th2);
clear p
p = gobjects(1,N);  % 各sin関数のグラフィックオブジェクト初期化
cols = zeros(N,3);  % 各色保存用

alpha = 0.5;  % 確認用透明度
cnt = 1;
for dth = th2
    y = sin(th - dth);
    col = squeeze(lab2rgb([75, cos(dth-pi)*100, sin(dth-pi)*100]));  % L*a*b
    col = min(col,1);  col = max(col,0);
    if line
        p(cnt) = plot(th,y,LineWidth=3,Color=[col alpha]);    
        cols(cnt,:) = col;
    else
        xx = [th,NaN];  yy = [y,NaN];
        p(cnt) = patch(xx,yy,'b',LineWidth=3,EdgeColor=col,EdgeAlpha=alpha);
    end
    if cnt==1; hold on; end
    cnt = cnt + 1;
    drawnow
end

hold off

% 透明化
for k=1:length(p)
    if line
        p(k).Color = [cols(k,:) 0];
    else
        p(k).EdgeAlpha = 0;
    end
end


we = false;  % trueでgifファイル保存
st = true;  % 1st frame
filename = 'LineAlpha.gif';
N2 = 20;  % 一度に可視化する数
for j=1:length(th2)
    for k=0:N2
        idx = mod(j+k, length(th2));
        idx = max(idx,1);
        alpha = (k/N2)^2;
        if line
            p(idx).Color = [cols(idx,:) alpha];
        else
            p(idx).EdgeAlpha = alpha;
        end
        xlim([0 max(th)])
    end
    drawnow

    if we
        frame = getframe(f);  % capture with border frame
        % frame = getframe(gca);  % take image only
        gr = frame2im(frame);
        gr = imresize(gr,0.5);
        [bA,map] = rgb2ind(gr,256);
        if (st)
            imwrite(bA,map,filename,'gif','LoopCount',Inf,'DelayTime',1/15);
            st = false;
        else
            imwrite(bA,map,filename,'gif','WriteMode','append','DelayTime',1/15);
        end
    end
end
if we; disp('Finished'); end  % ライブスクリプト動作では後半が表示されなかったりするので

もちろん色自体も変えられます。


なぜ、マニュアルに載っていないんでしょうね~?(;¬_¬)

そのうち、指定できなくなってしまうのでしょうか・・?

正式対応して欲しい!


MATLAB標準には「円を描く」命令はない!

ところで、「rectangle 関数」のスクリプト例にはもうひとネタ含まれています。

そう、"rectangle" なのに円が描かれています。

MATLAB標準には「円を描く」命令はない(!)のですが、
(Image Processing Toolbox には "viscircles" があります)

"rectangle" で "Curvature=[1 1]" と指定すれば(楕)円になります(=1でもok)

ただしあくまでも矩形描画関数ですので、外接矩形の左下座標を指定する必要があります。

透明度、大事ですよね。(-_☆)


この記事が気に入ったらサポートをしてみませんか?