Matplotlibで複数の画像を表示する
複数の画像データを見栄えよくならべて表示する方法を紹介します。
6個のデータを用意して、3列と2行にタイリングの表示にチャレンジします。
単純に連続して plt.show をコールする
まずは単純に6個の画像を出力してみます。
import numpy as np
import matplotlib.pyplot as plt
import math
w = 360
h = 360
numpix = w * h
# ubyte な1次元配列を確保する.
data0 = np.zeros( numpix, dtype=np.uint8)
data1 = np.zeros( numpix, dtype=np.uint8)
data2 = np.zeros( numpix, dtype=np.uint8)
data3 = np.zeros( numpix, dtype=np.uint8)
data4 = np.zeros( numpix, dtype=np.uint8)
data5 = np.zeros( numpix, dtype=np.uint8)
# サインデータ用の変数.
phase = 4.0
pai = math.pi
#---------------------------------------------
# ななめウロコデータを格納する.
for j in range( h ):
adrs = w * j
for i in range( w ):
level = i + j
data0[ adrs ] = level
adrs += 1
#---------------------------------------------
# 水平グラデーション.
for j in range( h ):
adrs = w * j
rate = j /( h - 1 )
level = rate * 255
for i in range( w ):
data1[ adrs ] = level
adrs += 1
#---------------------------------------------
# 垂直グラデーション.
for j in range( h ):
adrs = w * j
for i in range( w ):
rate = i /( w - 1 )
level = rate * 255
data2[ adrs ] = level
adrs += 1
#---------------------------------------------
# 垂直サイン.
for j in range( h ):
adrs = w * j
for i in range( w ):
rate_x = i /( w - 1 )
deg = rate_x * 360.0
rad = ( deg / 180.0 ) * pai
level = math.sin( phase * rad )
level += 1.0
level *= 0.5
level *= 255.0
data3[ adrs ] = level
adrs += 1
#---------------------------------------------
# 水平サイン.
for j in range( h ):
adrs = w * j
rate_y = j /( h - 1 )
deg = rate_y * 360.0
rad = ( deg / 180.0 ) * pai
level = math.sin( phase * rad )
level += 1.0
level *= 0.5
level *= 255.0
for i in range( w ):
data4[ adrs ] = level
adrs += 1
#---------------------------------------------
# ななめグラデーション.
for j in range( h ):
adrs = w * j
rate_y = j /( h - 1 )
deg = rate_y * 360.0
rad = ( deg / 180.0 ) * pai
level_y = math.sin( phase * rad )
level_y += 1.0
level_y *= 0.5
level_y *= 127.0
for i in range( w ):
rate_x = i /( w - 1 )
rate_x = i /( w - 1 )
deg = rate_x * 360.0
rad = ( deg / 180.0 ) * pai
level_x = math.sin( phase * rad )
level_x += 1.0
level_x *= 0.5
level_x *= 128.0
data5[ adrs ] = level_x + level_y
adrs += 1
#---------------------------------------------
# 2次元配列に変換する、w と h の順に注目せよ.
data0_2d = data0.reshape( h, w )
data1_2d = data1.reshape( h, w )
data2_2d = data2.reshape( h, w )
data3_2d = data3.reshape( h, w )
data4_2d = data4.reshape( h, w )
data5_2d = data5.reshape( h, w )
# Matplotlib で画像を表示する.
plt.imshow( data0_2d, cmap='gray')
plt.show()
# Matplotlib で画像を表示する.
plt.imshow( data1_2d, cmap='gray')
plt.show()
# Matplotlib で画像を表示する.
plt.imshow( data2_2d, cmap='gray')
plt.show()
# Matplotlib で画像を表示する.
plt.imshow( data3_2d, cmap='gray')
plt.show()
# Matplotlib で画像を表示する.
plt.imshow( data4_2d, cmap='gray')
plt.show()
# Matplotlib で画像を表示する.
plt.imshow( data5_2d, cmap='gray')
plt.show()
print( "finish." )
subplot を使ってタイリング画像表示する(ベタ書き版)
subplot という命令を使って、画像をオフスクリーンでタイリング書き込みしておいて、最後に plt.show 命令でイッキに表示します。
import numpy as np
import matplotlib.pyplot as plt
import math
w = 360
h = 360
numpix = w * h
# ubyte な1次元配列を確保する.
data0 = np.zeros( numpix, dtype=np.uint8)
data1 = np.zeros( numpix, dtype=np.uint8)
data2 = np.zeros( numpix, dtype=np.uint8)
data3 = np.zeros( numpix, dtype=np.uint8)
data4 = np.zeros( numpix, dtype=np.uint8)
data5 = np.zeros( numpix, dtype=np.uint8)
# サインデータ用の変数.
phase = 4.0
pai = math.pi
#---------------------------------------------
# ななめウロコデータを格納する.
for j in range( h ):
adrs = w * j
for i in range( w ):
level = i + j
data0[ adrs ] = level
adrs += 1
#---------------------------------------------
# 水平グラデーション.
for j in range( h ):
adrs = w * j
rate = j /( h - 1 )
level = rate * 255
for i in range( w ):
data1[ adrs ] = level
adrs += 1
#---------------------------------------------
# 垂直グラデーション.
for j in range( h ):
adrs = w * j
for i in range( w ):
rate = i /( w - 1 )
level = rate * 255
data2[ adrs ] = level
adrs += 1
#---------------------------------------------
# 垂直サイン.
for j in range( h ):
adrs = w * j
for i in range( w ):
rate_x = i /( w - 1 )
deg = rate_x * 360.0
rad = ( deg / 180.0 ) * pai
level = math.sin( phase * rad )
level += 1.0
level *= 0.5
level *= 255.0
data3[ adrs ] = level
adrs += 1
#---------------------------------------------
# 水平サイン.
for j in range( h ):
adrs = w * j
rate_y = j /( h - 1 )
deg = rate_y * 360.0
rad = ( deg / 180.0 ) * pai
level = math.sin( phase * rad )
level += 1.0
level *= 0.5
level *= 255.0
for i in range( w ):
data4[ adrs ] = level
adrs += 1
#---------------------------------------------
# ななめグラデーション.
for j in range( h ):
adrs = w * j
rate_y = j /( h - 1 )
deg = rate_y * 360.0
rad = ( deg / 180.0 ) * pai
level_y = math.sin( phase * rad )
level_y += 1.0
level_y *= 0.5
level_y *= 127.0
for i in range( w ):
rate_x = i /( w - 1 )
rate_x = i /( w - 1 )
deg = rate_x * 360.0
rad = ( deg / 180.0 ) * pai
level_x = math.sin( phase * rad )
level_x += 1.0
level_x *= 0.5
level_x *= 128.0
data5[ adrs ] = level_x + level_y
adrs += 1
#---------------------------------------------
# 2次元配列に変換する、w と h の順に注目せよ.
data0_2d = data0.reshape( h, w )
data1_2d = data1.reshape( h, w )
data2_2d = data2.reshape( h, w )
data3_2d = data3.reshape( h, w )
data4_2d = data4.reshape( h, w )
data5_2d = data5.reshape( h, w )
# 書き込み要素を取得する.
fig = plt.figure()
# タイルの縦横の個数.
TILE_NUM_ROW = 2
TILE_NUM_COL = 3
# プロットの位置を示すカウンタ(1スタートなのが気持ち悪い).
plot_counter = 1
ax = fig.add_subplot( TILE_NUM_ROW, TILE_NUM_COL, plot_counter )
ax.set_title( "{0}".format( plot_counter ))
ax.axis( "off" )
plt.imshow( data0_2d, cmap="gray" )
plot_counter += 1
ax = fig.add_subplot( TILE_NUM_ROW, TILE_NUM_COL, plot_counter )
ax.set_title( "{0}".format( plot_counter ))
ax.axis( "off" )
plt.imshow( data1_2d, cmap="gray" )
plot_counter += 1
ax = fig.add_subplot( TILE_NUM_ROW, TILE_NUM_COL, plot_counter )
ax.set_title( "{0}".format( plot_counter ))
ax.axis( "off" )
plt.imshow( data2_2d, cmap="gray" )
plot_counter += 1
ax = fig.add_subplot( TILE_NUM_ROW, TILE_NUM_COL, plot_counter )
ax.set_title( "{0}".format( plot_counter ))
ax.axis( "off" )
plt.imshow( data3_2d, cmap="gray" )
plot_counter += 1
ax = fig.add_subplot( TILE_NUM_ROW, TILE_NUM_COL, plot_counter )
ax.set_title( "{0}".format( plot_counter ))
ax.axis( "off" )
plt.imshow( data4_2d, cmap="gray" )
plot_counter += 1
ax = fig.add_subplot( TILE_NUM_ROW, TILE_NUM_COL, plot_counter )
ax.set_title( "{0}".format( plot_counter ))
ax.axis( "off" )
plt.imshow( data5_2d, cmap="gray" )
plot_counter += 1
plt.show()
print( "finish." )
subplot を使ってタイリング画像表示する(forループ)
さすがに上記のコードは効率が悪いので for ループに書き換えるとこうなります。
import numpy as np
import matplotlib.pyplot as plt
import math
w = 360
h = 360
numpix = w * h
# ubyte な1次元配列を確保する.
data0 = np.zeros( numpix, dtype=np.uint8)
data1 = np.zeros( numpix, dtype=np.uint8)
data2 = np.zeros( numpix, dtype=np.uint8)
data3 = np.zeros( numpix, dtype=np.uint8)
data4 = np.zeros( numpix, dtype=np.uint8)
data5 = np.zeros( numpix, dtype=np.uint8)
# サインデータ用の変数.
phase = 4.0
pai = math.pi
#---------------------------------------------
# ななめウロコデータを格納する.
for j in range( h ):
adrs = w * j
for i in range( w ):
level = i + j
data0[ adrs ] = level
adrs += 1
#---------------------------------------------
# 水平グラデーション.
for j in range( h ):
adrs = w * j
rate = j /( h - 1 )
level = rate * 255
for i in range( w ):
data1[ adrs ] = level
adrs += 1
#---------------------------------------------
# 垂直グラデーション.
for j in range( h ):
adrs = w * j
for i in range( w ):
rate = i /( w - 1 )
level = rate * 255
data2[ adrs ] = level
adrs += 1
#---------------------------------------------
# 垂直サイン.
for j in range( h ):
adrs = w * j
for i in range( w ):
rate_x = i /( w - 1 )
deg = rate_x * 360.0
rad = ( deg / 180.0 ) * pai
level = math.sin( phase * rad )
level += 1.0
level *= 0.5
level *= 255.0
data3[ adrs ] = level
adrs += 1
#---------------------------------------------
# 水平サイン.
for j in range( h ):
adrs = w * j
rate_y = j /( h - 1 )
deg = rate_y * 360.0
rad = ( deg / 180.0 ) * pai
level = math.sin( phase * rad )
level += 1.0
level *= 0.5
level *= 255.0
for i in range( w ):
data4[ adrs ] = level
adrs += 1
#---------------------------------------------
# ななめグラデーション.
for j in range( h ):
adrs = w * j
rate_y = j /( h - 1 )
deg = rate_y * 360.0
rad = ( deg / 180.0 ) * pai
level_y = math.sin( phase * rad )
level_y += 1.0
level_y *= 0.5
level_y *= 127.0
for i in range( w ):
rate_x = i /( w - 1 )
rate_x = i /( w - 1 )
deg = rate_x * 360.0
rad = ( deg / 180.0 ) * pai
level_x = math.sin( phase * rad )
level_x += 1.0
level_x *= 0.5
level_x *= 128.0
data5[ adrs ] = level_x + level_y
adrs += 1
#---------------------------------------------
# 2次元配列に変換する、w と h の順に注目せよ.
data0_2d = data0.reshape( h, w )
data1_2d = data1.reshape( h, w )
data2_2d = data2.reshape( h, w )
data3_2d = data3.reshape( h, w )
data4_2d = data4.reshape( h, w )
data5_2d = data5.reshape( h, w )
# 書き込み要素を取得する.
fig = plt.figure()
# タイルの縦横の個数.
TILE_NUM_ROW = 2
TILE_NUM_COL = 3
# データを管理するリストを作成する.
list_data = []
list_data.append( data0_2d )
list_data.append( data1_2d )
list_data.append( data2_2d )
list_data.append( data3_2d )
list_data.append( data4_2d )
list_data.append( data5_2d )
# プロットの位置を示すカウンタ(1スタートなのが気持ち悪い).
plot_counter = 1
# リストの要素回数だけループする.
for data in list_data:
ax = fig.add_subplot( TILE_NUM_ROW, TILE_NUM_COL, plot_counter )
ax.set_title( "{0}".format( plot_counter ))
ax.axis( "off" )
plt.imshow( data, cmap="gray" )
plot_counter += 1
plt.show()
print( "finish." )
ちなみに Python には foreach 文は存在しませんが、for 文がやたらと拡張定義されているので foreach のように記述することができます。
最後の for ループは下記のような書き方もできます。C言語などに慣れている人はこっちのほうがしっくりくるかもしれません。
# リストの要素回数だけループする.
for n in range( len( list_data )):
plot_num = n + 1
ax = fig.add_subplot( TILE_NUM_ROW, TILE_NUM_COL, plot_num )
ax.set_title( "{0}".format( plot_num ))
ax.axis( "off" )
plt.imshow( list_data[n], cmap="gray" )
plt.show()
print( "finish." )
先に示したプロット結果と同じですが、いちおう実行結果を示しておきます。