13
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MATLAB ロゴを使った MATLAB ロゴのモザイクアート

Last updated at Posted at 2021-11-30

先月行われたMATLAB Central 20周年記念の MATLAB Mini Hack.280文字以内のMATLABコードでどれだけ美しい画像が描けるか,というとても面白いコンテストでした.1700近くのエントリーがありました.本当に280字以内で描いたのか,というものがたくさんありました.

私はあまり数学的な美しい図は思いつかなかったので,MATLABのロゴを使ったモザイクアートを作ってみました.ここでそのコードを解説します.

logo_mosaic.gif

コンテストで使ったコードはこちらになります:Mosaic Membrane

ただ,その後もう少し考えてみたらもっと簡単にできることが判明しました.今回は簡単な方を紹介します.

Code(Display)
logo;
c = getframe;
im = im2double(c.cdata);
im2 = imresize(im, 1/8);
im3 = imresize(im, [20 20]);
im4 = imresize(im, [1 1]);
im_diff = im2 - im4;
[r,c,~] = size(im2);
for i1 = 1:r
    for i2 = 1:c
        out{i1,i2} = im3 + im_diff(i1,i2,:);
    end
end
imshow(cell2mat(out))

解説

1. MATLAB ロゴ

まずはモザイクを作る画像とベースとなるタイル(今回は両方とも同じ画像)の MATLAB ロゴの画像を用意するのですが,標準デモ関数(スクリプト)の logo を使って,表示されるロゴのスクリーンキャプチャーを getframe 関数で取得します.

Code
logo;
c = getframe

figure_0.png

Output
c = 
       cdata: [840x818x3 uint8]
    colormap: []

c は構造体で,その中の cdata フィールドに画像データが含まれています.通常 uint8 型で定義してありますが,後にいろいろ演算を行うので double 型に変換します.

Code
im = im2double(c.cdata);
whos im
Output
  Name        Size                  Bytes  Class     Attributes

  im        840x818x3            16490880  double              

2. モザイク用画像の準備

モザイク画像とは,それぞれのピクセルを別の画像で表現して作り上げるので,最終的にできあがる画像はもとの画像よりも大きくなります.よって,今回は処理時間を短縮するために元の画像の大きさを小さくします.

Code
im2 = imresize(im, 1/8);    % 1/8の大きさ
whos im2
Output
  Name        Size                Bytes  Class     Attributes

  im2       105x103x3            259560  double              

また,各ピクセルを作り上げる画像の大きさを設定します.今回は 20 x 20 の大きさに調整します.

Code
im3 = imresize(im, [20 20]);
whos im3
Output
  Name       Size              Bytes  Class     Attributes

  im3       20x20x3             9600  double              

つまり,最終画像は 2100 x 2060 の大きさになります.

3. ピクセルに近似させるには

モザイク画像を作成するためには,タイルとして使う画像をうまく組み合わせて元の画像を再現するのですが,タイルとして使う画像が MATLAB ロゴの一枚となるとどうすればよいのでしょうか.

それを実現するためにロゴの画像の色を調整しました.

例えば,ロゴに赤み,緑み,青みを増すには

Code
imR = im2 + reshape([0.5 0 0],1,1,3);
imG = im2 + reshape([0 0.5 0],1,1,3);
imB = im2 + reshape([0 0 0.5],1,1,3);
figure, tiledlayout(1,3,"TileSpacing","tight","Padding","tight")
nexttile
imshow(imR), title("赤み","Color","red")
nexttile
imshow(imG), title("緑み","Color","red")
nexttile
imshow(imB), title("青み","Color","red")

figure_1.png

4. 色の距離の計算

色みを付ける方法が分かったので,後はそれぞれのタイルの色をどの程度調整するかを計算するだけです.

まずは,タイルの "平均の色" を計算するために,画像を1ピクセルに縮小します.

Code
im4 = imresize(im,[1 1])
Output
im4 = 
im4(:,:,1) =
    0.2236
im4(:,:,2) =
    0.1066
im4(:,:,3) =
    0.0474
Code
figure, imshow(im4)

figure_2.png

なるほど.背景が黒いので全体的に黒いですね.ちょっとオレンジ・茶色がかっていますね.

さて,この色からもともとのロゴの画像の各ピクセルの色との差を計算すればよいのです.

Code
im_diff = im2 - im4;
whos im_diff
Output
  Name           Size                Bytes  Class     Attributes

  im_diff      105x103x3            259560  double              

im_diff はもとの画像と同じ大きさで,各ピクセルの値は1ピクセルロゴとの色の差を表しています.

5. モザイク画像の組み立て

これで準備完了.最後にそれぞれのピクセルをタイル(+上で求めた色の差分)に置き換えれば完了です.ただし,タイルは 20 x 20 の大きさなので単純に1ピクセルを置き換えるわけにはいかないので,セル配列で集約します.

Code
[r,c,~] = size(im2);
for i1 = 1:r
    for i2 = 1:c
        out{i1,i2} = im3 + im_diff(i1,i2,:);
    end
end

% 最初の3行3列を見てみよう
out(1:3,1:3)
1 2 3
1 20x20x3 double 20x20x3 double 20x20x3 double
2 20x20x3 double 20x20x3 double 20x20x3 double
3 20x20x3 double 20x20x3 double 20x20x3 double

最後にすべてをくっつけます.

Code
imOut = cell2mat(out);
whos imOut
Output
  Name          Size                    Bytes  Class     Attributes

  imOut      2100x2060x3            103824000  double              
Code
imshow(imOut)

figure_3.png

おしまい

試しに2階層のモザイクアートを作ってみました.ロゴの原型が分かるようにすると画素数が大きくなってしまい,ちょっと処理が重くなりましたが,もっと性能の良いPCだったらいろいろ楽しめると思います.

large_mosaic2.gif

13
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?