スポットライト効果をMATLABで


今年の MATLAB EXPO で、ポスターセッションの順位発表の時に以下のようなスポットライト効果を使ったプログラムを使いました。

このコードを解説してみます。

背景画像

まず、簡単なのは1から14の数字を書いた背景の画像です。(今年は14個のポスターが展示されていました。)

im = imread('num_grid_large.png');
imshow(im)

軌跡座標

この14個の数字の位置を4x4の行列とすると、スポットライトを移動したい位置を次のようにランダムに定義します。実際はrand関数を使いました。

x = [2 4 2 1 3 1 4 2 3];
y = [4 1 2 1 2 4 3 3 1];

この軌跡を直接描画してみると

% 画像の大きさに合わせてスケーリング
img_scale = [size(im,2) size(im,1)]/5;

hold on
plot(x*img_scale(1),y*img_scale(2),'o-')
hold off

スプライン補間

ただ、このままだと滑らかな動きにはなりません。

そこでスプライン補間を使って滑らかの曲線になるようにします。

num_points = length(x);

xx = interp1(1:num_points,x,1:0.05:num_points,'spline');
yy = interp1(1:num_points,y,1:0.05:num_points,'spline');

imshow(im)
hold on
plot(xx*img_scale(1),yy*img_scale(2))
plot(x*img_scale(1),y*img_scale(2),'o')
hold off

ROI オブジェクト

あとはスポットライト効果を作るだけです。

今回は Image Processing Toolbox の ROI 機能を使います。ROI 機能では様々な図形で関心領域を定義することができ、その領域の面積を計算したり、マスクを作成したりすることができます。ここではdrawellipse関数で楕円 ROI を作成します。

hh = imshow(im);
h = drawellipse('AspectRatio',1,'Center',[xx(1), yy(1)] .* img_scale,'SemiAxes',img_scale/2);

マスク作成

ROI オブジェクトのマスク機能で楕円(円)部分を切り取るマスクを作成し、もとの画像と掛け合わせることによってスポットライト完成!

BW = createMask(h);
new_im = im .* uint8(BW);
imshow(new_im)

forループ

あとは、forループを使ってこの作業を軌道のデータ点ごとに繰り返すだけです。参考までに全コードです。

im = imread('num_grid_large.png');
hh = imshow(im);

x = [2 4 2 1 3 1 4 2 3];
y = [4 1 2 1 2 4 3 3 1];

num_points = length(x);

xx = interp1(1:num_points,x,1:0.05:num_points,'spline');
yy = interp1(1:num_points,y,1:0.05:num_points,'spline');

img_scale = [size(im,2) size(im,1)]/5;
h = drawellipse('AspectRatio',1,'Center',[xx(1), yy(1)] .* img_scale,...
    'SemiAxes',img_scale/2,'Visible','off');

for id = 1:length(xx)
    h.Center = [xx(id), yy(id)] .* img_scale;
    BW = createMask(h);
    hh.CData = im .* uint8(BW);
    drawnow
end

おまけ

もちろん色画像でもできます。