はじめに
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
表示したいものを配列に入れて Kino.Layout.tabs
に渡します
[
Red: generate_image.([255, 0, 0]),
Green: generate_image.([0, 255, 0]),
Blue: generate_image.([0, 0, 255]),
]
|> Kino.Layout.tabs()
出力の上部にタブが表示され、クリックによって切り替えられるようになりました
画像表示以外でも出力は全てタブ表示にできるので、例えば入力と出力をタブ表示にすることもできます
[
Input: [255, 0, 0],
Output: generate_image.([255, 0, 0])
]
|> Kino.Layout.tabs()
グラフ表示もやってみましょう
plot = fn value ->
x = Nx.iota({256})
VegaLite.new(width: 180)
|> VegaLite.data_from_values(%{x: Nx.to_flat_list(x), y: Nx.to_flat_list(value)})
|> VegaLite.mark(:line)
|> VegaLite.encode_field(:x, "x", type: :quantitative)
|> VegaLite.encode_field(:y, "y", type: :quantitative)
end
グラデーションになっている画像と、その画像の RGB の値をグラフ化したものです
red = Nx.iota({256})
green = [Nx.iota({128}) |> Nx.reverse(), Nx.iota({128})] |> Nx.concatenate()
blue = {256} |> Nx.iota() |> Nx.reverse()
img =
[red, green, blue]
|> Nx.stack()
|> Nx.tile([256])
|> Nx.transpose()
|> Nx.reshape({256, 256, 3})
|> Nx.as_type(:u8)
|> Kino.Image.new()
[
Image: img,
Red: plot.(red),
Green: plot.(green),
Blue: plot.(blue),
]
|> Kino.Layout.tabs()
まとめ
Kino.Layout.tabs
によって画像やグラフをタブ切り替えで表現できました
何にでも応用できるので、データを可視化する際により効果的な見せ方として活用しましょう