LoginSignup
41
41

More than 5 years have passed since last update.

ImageMagick でサクッとヒートマップを作る

Last updated at Posted at 2014-03-31

みんな大好き ImageMagick ですが、手軽にサクッとヒートマップを作る記事が意外と出てこなかったのでメモ。 ImageMagick のバージョンは以下のとおり。

$ convert --version
Version: ImageMagick 6.8.6-3 2013-10-02 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2013 ImageMagick Studio LLC
Features: DPC Modules
Delegates: bzlib freetype jng jpeg png xml zlib

ヒートマップとは

ヒートマップ (heat map, temperature map) とは何かというと、こんなやつです。

result.png

データが二次元上のどんな位置に分布しているのかを可視化する場合によく使うと思います。

使い方

適当な画像とヒートマップ作成の元画像、あと座標データ (x, y) を用意します。画像とデータには特に意味はありません。

original.png
point.png
gradation.png

$ cat heatmap.csv
415,130
415,140
415,135
420,140
430,140
425,135
450,120
395,140
400,135
430,135
420,145
470,130
460,130
470,170
470,160
470,130
475,110
470,120

データを元に次のようにコマンドを叩きます。各座標データが point.png (50px x 50px) の中心に来るように x, y 座標から 25 を引いています。

size=`identify -format '%wx%h' original.png`
convert -size $size pattern:gray100 heatmap-tmp.png
convert heatmap-tmp.png -page +390+105 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +390+115 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +390+110 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +395+115 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +405+115 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +400+110 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +425+95 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +370+115 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +375+110 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +405+110 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +395+120 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +445+105 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +435+105 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +445+145 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +445+135 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +445+105 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +450+85 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +445+95 point.png -flatten heatmap-tmp.png
convert -channel ALL -clut heatmap-tmp.png gradation.png heatmap-tmp.png
composite -dissolve 50%x100% original.png heatmap-tmp.png result.png

なお座標データ CSV ファイル heatmap.csv を元に座標入力コマンドを作る Ruby スクリプト heatmap.rb は次のような感じです。

require 'csv'

ORGFILE = 'original.png'
TMPFILE = 'heatmap-tmp.png'
RESFILE = 'result.png'

POINT_PNG = 'point.png'
GRADATION_PNG = 'gradation.png'

CSVFILE = 'heatmap.csv'

puts "size=`identify -format '%wx%h' #{ORGFILE}`"
puts "convert -size $size pattern:gray100 #{TMPFILE}"
CSV.foreach(CSVFILE) do |row|
  puts "convert #{TMPFILE} -page +#{row[0].to_i - 25}+#{row[1].to_i - 25} #{POINT_PNG} -flatten #{TMPFILE}"
end
puts "convert -channel ALL -clut #{TMPFILE} #{GRADATION_PNG} #{TMPFILE}"
puts "composite -dissolve 50%x100% #{ORGFILE} #{TMPFILE} #{RESFILE}"

これを次のように一旦コマンドを確認してパイプで sh に食わせると簡単でしょう。

$ ruby heatmap.rb
size=`identify -format '%wx%h' original.png`
convert -size $size pattern:gray100 heatmap-tmp.png
convert heatmap-tmp.png -page +390+105 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +390+115 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +390+110 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +395+115 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +405+115 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +400+110 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +425+95 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +370+115 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +375+110 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +405+110 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +395+120 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +445+105 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +435+105 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +445+145 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +445+135 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +445+105 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +450+85 point.png -flatten heatmap-tmp.png
convert heatmap-tmp.png -page +445+95 point.png -flatten heatmap-tmp.png
convert -channel ALL -clut heatmap-tmp.png gradation.png heatmap-tmp.png
composite -dissolve 50%x100% original.png heatmap-tmp.png result.png
$ ruby heatmap.rb | sh

結果は次のようになります。

result.png

各コマンドの説明

一応各コマンドの意味も調べたのでメモ。

size=`identify -format '%wx%h' original.png`

identify コマンドは画像ファイルの各パラメータを取得するコマンドです。ここでは後のコマンドで使いやすいように幅と高さを 600x310 のような形式で取得します。

convert -size $size pattern:gray100 heatmap-tmp.png

ヒートマップデータを作るための一時ファイルを作成しています。
pattern:gray100 では ImageMagick 組み込みの画像パターンを指定しています。この組み込みパターンはあたかもそのパターンの画像があるかのように扱います。またサイズはヒートマップの元画像と同じサイズです。出力先ファイルとして heatmap-tmp.png という PNG ファイルを指定します。

convert heatmap-tmp.png -page +390+105 point.png -flatten heatmap-tmp.png

「どの座標がどのくらい濃いのか」というヒートマップデータを作っていきます。それまでできた heatmap-tmp.png を背景に、新たに (x, y) = (390, 105) の位置に point.png を重ねていく感じです。

convert -channel ALL -clut heatmap-tmp.png gradation.png heatmap-tmp.png

heatmap-tmp.png の濃い部分と薄い部分を gradation.png
からよしなに選んでマップする感じだと思います。あまりわかっていない。

composite -dissolve 50%x100% original.png heatmap-tmp.png result.png

オリジナル画像と作成したヒートマップ画像を重ねあわせています。
ここでは dissolve オプションで original.png を 50% の「濃さ」で、 heatmap-tmp.png を 100% の「濃さ」で重ねることを指定しています。

41
41
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
41
41