4
3

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.

Elixir Livebook ノートブックで画像・グラフを横に並べて表示する

Last updated at Posted at 2023-01-08

はじめに

Elixir Livebook で画像処理やグラフ表示をしているとき、結果を横に並べて比較したい時がありますよね

というわけで画像やグラフを横に並べる方法です

タブ切り替えで表示する場合はこちら

実行環境

  • Elixir: 1.14.2 OTP 24
  • Livebook: 0.8.0

セットアップ

画像とグラフの表示に最低限必要なモジュールをインストールします

Mix.install([
  {:nx, "~> 0.4"},
  {:kino, "~> 0.8"},
  {:kino_vega_lite, "~> 0.1.7"}
])

画像を並べる

指定した色の画像を生成する関数を用意します

generate_image = fn color ->
  {height, width} = {160, 160}

  color
  |> Nx.tensor(type: :u8)
  |> Nx.tile([height, width, 1])
  |> Kino.Image.new()
end

例えば以下のように書いた場合、一番最後の画像だけが表示されてしまいます

generate_image.([255, 0, 0])
generate_image.([0, 255, 0])
generate_image.([0, 0, 255])
generate_image.([255, 255, 0])
generate_image.([255, 0, 255])
generate_image.([0, 255, 255])

スクリーンショット 2023-01-08 23.16.59.png

以下のように Kino.render を入れると、途中でも結果を表示することができます

ただし、縦に並ぶので多くなると見にくいです

generate_image.([255, 0, 0])
generate_image.([0, 255, 0])
generate_image.([0, 0, 255])
|> Kino.render()
generate_image.([255, 255, 0])
generate_image.([255, 0, 255])
|> Kino.render()
generate_image.([0, 255, 255])

スクリーンショット 2023-01-08 23.17.45.png

表示したいものを配列に入れて Kino.Layout.grid に渡します

そのとき、 columns に列数を指定しておくと、その分横に並んで見やすくなります

[
  generate_image.([255, 0, 0]),
  generate_image.([0, 255, 0]),
  generate_image.([0, 0, 255]),
  generate_image.([255, 255, 0]),
  generate_image.([255, 0, 255]),
  generate_image.([0, 255, 255]),
]
|> Kino.Layout.grid(columns: 3)

スクリーンショット 2023-01-08 23.18.28.png

当然、 Enum.map でパイプしてもいいので、パラメータ変化に伴う結果の変化を並べて表示したいときなどに有効です

[
  [0, 0, 0], [255, 0, 0], [0, 255, 0], [0, 0, 255],
  [255, 255, 0], [255, 0, 255], [0, 255, 255], [255, 255, 255]
]
|> Enum.map(&generate_image.(&1))
|> Kino.Layout.grid(columns: 4)

スクリーンショット 2023-01-08 23.19.26.png

boxed (デフォルトは false) に true を指定すると、出力全体の外側に枠が付きます

gap で各出力の間隔を指定できます

[
  [255, 0, 0], [0, 255, 0], [0, 0, 255],
  [255, 255, 0], [255, 0, 255], [0, 255, 255]
]
|> Enum.map(&generate_image.(&1))
|> Kino.Layout.grid(columns: 3, boxed: true, gap: 60)

スクリーンショット 2023-01-08 23.20.12.png

ネストする(入れ子にする)こともできるため、複雑な形にすることも可能です

[
  generate_image.([255, 0, 0]),
  generate_image.([0, 0, 255]),
  [
    generate_image.([255, 0, 0]),
    generate_image.([0, 0, 255]),
    generate_image.([0, 0, 255]),
    generate_image.([255, 0, 0]),
  ]
  |> Kino.Layout.grid(columns: 2, gap: 10),
  generate_image.([0, 0, 255]),
  generate_image.([255, 0, 0]),
]
|> Kino.Layout.grid(columns: 5, gap: 10)

スクリーンショット 2023-01-08 23.20.51.png

グラフの場合

$ y = x^p $ のグラフをプロットする関数を用意します

plot = fn p ->
  x = Nx.iota({10})
  y = Nx.power(x, p)

  VegaLite.new(width: 180)
  |> VegaLite.data_from_values(%{x: Nx.to_flat_list(x), y: Nx.to_flat_list(y)})
  |> VegaLite.mark(:line)
  |> VegaLite.encode_field(:x, "x", type: :quantitative)
  |> VegaLite.encode_field(:y, "y", type: :quantitative)
end

画像と同じように、 Kino.Layout.grid で並べることができます

0..8
|> Enum.map(&plot.(&1))
|> Kino.Layout.grid(columns: 3)

スクリーンショット 2023-01-08 23.21.29.png

まとめ

Kino.Layout.grid によって画像やグラフを自在に並べることができました

もちろん他の出力も全て同様に扱うことが可能なので、様々な応用で表現力を向上させましょう

4
3
1

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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?