MATLABでお絵描き

MATLAB本体でお絵描きをするにはginput関数を使いますが、使い勝手はよくありません。 別売りのImage Processing Toolboxにはim○○という関数が用意されていて、大変便利です。

Contents

image関数でMRIの表示

imagescとcolormap関数を使えばMRIの表示はできるのですが、特定の領域だけを別の色で表現することはできません。 そこでimage関数を使います。image関数の値は0~1の小数、または0~255の整数です。ここでは整数を採用します。

load mri;
D=int16(squeeze(D));
[dx,dy,dz]=size(D);
D0=squeeze(D(:,:,round(dz/2)));
D0=double(D0);
clim=[min(D0(:)),max(D0(:))];
Dmap=round((D0-clim(1))/(clim(2)-clim(1))*255);
Dmap(Dmap<0)=0;Dmap(Dmap>255)=255;
Dmap=Dmap+1;
map=gray(256);
D1=zeros(dx,dy,3);
[dx,dy]=size(D0);
for x=1:dx
    for y=1:dy;
        D1(x,y,:)=map(Dmap(x,y),:);
    end;
end;
figure('color',[1,1,1]);
image(D1);daspect([1,1,1]);
title('通常表示');

threshold=linspace(clim(1),clim(2),11);
threshold=threshold([7,9]);% 閾値を60 ~ 80%とする。
D1=zeros(dx,dy,3);
map2=map;
map2(:,2:3)=0;
for x=1:dx
    for y=1:dy
        d=D0(x,y);
        if d<threshold(1)
            D1(x,y,:)=map(Dmap(x,y),:);
        elseif d>threshold(2)
            D1(x,y,:)=map(Dmap(x,y),:);
        else
            D1(x,y,:)=map2(Dmap(x,y),:);
        end;
    end;
end;
figure('color',[1,1,1]);
image(D1);daspect([1,1,1]);
title(sprintf('閾値 %0.0f - %0.0fを赤でマスク',threshold(1),threshold(2)));

D1=zeros(dx,dy,3);
Dmask=repmat(uint8(0),dx,dy);
r2=(dx/10)^2+(dy/10)^2;
p0=[dx,dy]/2;
p1=p0+sqrt(r2)*[1,-sqrt(3)];% Y軸、X軸の順番
p2=p0+sqrt(r2)*[1,sqrt(3)];
p3=p0+sqrt(r2)*[-sqrt(3),0];
for x=1:dx
    for y=1:dy;
        if (x-p1(1))^2+(y-p1(2))^2<r2
            Dmask(x,y)=1;
        elseif (x-p2(1))^2+(y-p2(2))^2<r2
            Dmask(x,y)=2;
        elseif (x-p3(1))^2+(y-p3(2))^2<r2
            Dmask(x,y)=3;
        end;
    end;
end;
map2=map;
map2(:,2:3)=0;
map3=map;
map3(:,1:2)=0;
map4=map;
map4(:,[1,3])=0;
for x=1:dx
    for y=1:dy;
        switch Dmask(x,y)
            case 1;D1(x,y,:)=map2(Dmap(x,y),:);
            case 2;D1(x,y,:)=map3(Dmap(x,y),:);
            case 3;D1(x,y,:)=map4(Dmap(x,y),:);
            otherwise;D1(x,y,:)=map(Dmap(x,y),:);
        end;
    end;
end;
figure('color',[1,1,1]);
image(D1);daspect([1,1,1]);
title('三カ所をマスクして表示');

ginput関数でお絵描き

マスク無し画像を描画後、ginput関数を使って線を描いてみます。 十時カーソルが出て、離した時に点が選択されますが、表示はされません。 押しっぱなしでは点は選択されません。点選択途中の線は描画されません。 Returnボタンを押せば点の選択は終了となり、そのときに線が描画されます。

map=gray(256);
D1=zeros(dx,dy,3);
[dx,dy]=size(D0);
for x=1:dx
    for y=1:dy;
        D1(x,y,:)=map(Dmap(x,y),:);
    end;
end;
figure('color',[1,1,1]);
image(D1);daspect([1,1,1]);
hold on;

[x,y]=ginput;
plot(x,y,'color',[0,1,1],'linewidth',2);
title(sprintf('ginput関数を使ってマウスで%d点選んだとき',numel(x)));

ginput関数でお絵描き(ちょっと改良)

ボタンを押したら線が表示できるように改良しました。ラバーバンドではありません。 選択を終了するのはゆっくりダブルクリックするか、トリプルクリックしてください。

figure('color',[1,1,1]);
image(D1);daspect([1,1,1]);
hold on;
for n=1:1000
   [x(n),y(n)]=ginput(1);

   if n>1
       if all([x(n-1),y(n-1)]==[x(n),y(n)]);
           break;
       end;
       plot([x(n-1),x(n)],[y(n-1),y(n)],'color',[0,1,1],'linewidth',2);
   end;

end;
title(sprintf('ginput関数を使ってマウスで%d点選んだとき',numel(n)));

impoint関数でお絵描き

Image Processing Toolboxのimpoint関数を使います。 今度はマウスボタンを押したら、ちゃんと点が表示されます。 選択を終了するのはゆっくりダブルクリックするか、トリプルクリックしてください。 選んだ点はドラッグできます。

figure('color',[1,1,1]);
image(D1);daspect([1,1,1]);
hold on;
clear h;
P0=[0,0];
for n=1:1000
    title(sprintf('impoint関数を使って%d点選んだとき',n-1));
    h(n)=impoint;
    hline=findobj(h(n),'type','line');
    set(hline,'color',[0,1,1]);
    hc=get(h(n),'children');
    P1=[get(hc(1),'xdata'),get(hc(1),'ydata')];

    if all(P0==P1);
        delete(h(n));
        break;
    end;
    P0=P1;
end;

imline関数でお絵描き

Image processing Toolboxのimline関数を使います。 ラバーバンドっぽくなります。カーソルを離すと離したところから線が描画されます。 終了するには枠外をクリックします。 尚、線はドラッグして移動することができますが、線と線は繋がってないので、 選択された線分だけが移動します。

figure('color',[1,1,1]);
image(D1);daspect([1,1,1]);
hold on;
clear h;
check=0;
for n=1:1000
    h(n)=imline;
    set(findobj(h(n),'type','line'),'color',[0,1,1]);
    p=get(gca,'currentpoint');
    if p(1,1)<0;check=1;break;end;
    if p(1,1)>dx;check=1;break;end;
    if p(1,2)<0;check=1;break;end;
    if p(1,2)>dy;check=1;break;end;
end;
if check==1
    delete(h(n));
end;
title(sprintf('imline関数を使って%d本の線を選んだとき',length(h)));

imfreehand関数でお絵描き

Image Processing Toolboxのimfreehand関数を使います。 ドラッグした軌跡がそのまま描画されます。 ボタンを離すと、囲まれた領域を閉じて領域を作成し、終了します。 領域はドラッグして移動することができます。

figure('color',[1,1,1]);
image(D1);daspect([1,1,1]);
hold on;
clear h;
delete(findobj(gcf,'type','line'));
h=imfreehand;
position=wait(h);
hl=findobj(h,'type','line');
set(hl,'color',[0,1,1]);