28
27

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 5 years have passed since last update.

RubyでRubyを描く

Last updated at Posted at 2016-09-13

RubyでRubyを描く // Speaker Deck
RubyKaigi2016最終日の次の日に開催された第74回 Ruby関西 勉強会で発表した内容とその補足になります。

RubyをRubyで描く とは

一ヶ月ほど前、RubyKaigiを目前にしてテンションが高まりRubyのロゴ
_ruby.jpeg
(Copyright © 2006, Yukihiro Matsumoto)

をRubyで描いて信仰心を深めたいという衝動に駆られました。

画像を数値化

とりあえずこのRubyのロゴを数値化します。

Screenshot 2016-09-13 02.16.53.png

ImageMagickのwrapperであるRMagick使いました。

require 'RMagick'
include Magick

# 画像の読み込み
image = ImageList.new('ruby-kit/ruby.jpg')

# ピクセル毎に赤色要素だけを数値化して2次元配列に
z = image.rows.downto(0).map do |y|
  image.columns.times.map do |x|
    image.pixel_color(x, y).red
  end
end

元の画像が1000x1000pxぐらいだったのでzの配列のサイズも1000x1000になっています。

Heatmap化

とりあえず簡単に画像っぽいものを描くならヒートマップですね。

Screenshot 2016-09-13 02.16.13.png 簡単に説明すると、数値を色で表現できる可視化手法で上の例だと値が小さいほど青く、大きいほど赤く表示されます。 Githubのアレです。 Screenshot 2016-09-13 02.19.56.png

今回は僕がSciRuby.jpの活動の一環として書いているrbplotlyというgemで描画しています。

require 'rbplotly'

data = [{
  z: z,
  type: :heatmap,
  colorscale: [
    [0.0,  'rgb(  0,   0,   0)'],
    [0.7,  'rgb(256,   0,   0)'],
    [0.95, 'rgb(256, 256, 256)'],
    [1.0,  'rgb(256, 256, 256)']
  ]
}]
layout = { width: 700, height: 700 }

plot = Plotly::Plot.new(data: data, layout: layout)
plot.show # IRuby上以外では#generate_htmlや#download_imageを。
          # 詳しくは https://github.com/ash1day/rbplotly 参照

colorscaleを0〜1で指定するところがポイントです。デフォルトでは上の例のように青〜赤なのですが、今回は画像を再現したいので黒〜赤〜白としています。

結果と比較

結果

Screenshot 2016-09-13 02.27.09.png

colorscaleを手動でチューニングしたこともあり、結構似ました。

比較

Screenshot 2016-09-13 02.27.33.png

左が元の画像です。やっぱりちょっと深みがありますね。

カラーバリエーション

色の指定を黒〜緑〜白や、黒〜青〜白とすることにより色を変化させることができます。
Screenshot 2016-09-13 02.32.24.png

Heatmapでの問題点

  • 色の指定が面倒
  • 「それ、画像貼った方がいいんじゃない?」という痛いところを突かれやすい。

Scatter Plot

というわけで、もっとグラフ描いてる感が出る可視化手法Scatter Plotで描いてみます。何のことはない点プロットです。

Screenshot 2016-09-13 02.36.28.png

好きな色を指定できるように今度は先ほど配列化した数値をマーカーの濃度に適用します。

# opacityの設定が0〜1なので正規化
max = z.flatten.max
min = z.flatten.min
denom = max - min
z.map! { |row| row.map { |red| 1 - (red - min).to_f / denom } }

trace = {
  x: z.length.times.map { z.first.length.times.to_a }.flatten,
  y: z.length.times.map { |y| Array.new(z.first.length - 1, y) }.flatten,
  type: :scatter,
  mode: :markers,
  marker: { size: 1, color: 'rgb(255, 65, 54)', opacity: z.flatten }
}
layout = { width: 700, height: 700 }

plot = Plotly::Plot.new(data: [trace], layout: layout)
plot.show

Heatmap版と比べて色の指定が簡単になっているのが分かるでしょうか。これなら何色のRubyでも書けそうですね。

結果

Screenshot 2016-09-13 02.51.16.png

ナウなフラットデザインっぽい色のRubyが描けました。(白い部分も点は打たれていますが、opacityがほぼ0なため見えなくなっています。)

28
27
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
28
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?